package divconq.web.ui.adapter; import java.io.IOException; import io.netty.handler.codec.http.HttpChunkedInput; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedNioFile; import divconq.filestore.CommonPath; import divconq.io.CacheFile; import divconq.web.IOutputAdapter; import divconq.web.Response; import divconq.web.WebContext; import divconq.web.WebSite; public class StaticOutputAdapter implements IOutputAdapter { public CommonPath webpath = null; public CacheFile file = null; protected String mime = null; @Override public void init(WebSite site, CacheFile file, CommonPath web, boolean isPreview) { this.webpath = web; this.file = file; this.mime = site.getMimeType(this.file.getExt()); } @Override public void execute(WebContext ctx) throws Exception { Response resp = ctx.getResponse(); resp.setHeader("Content-Type", this.mime); resp.setDateHeader("Date", System.currentTimeMillis()); resp.setDateHeader("Last-Modified", this.file.getWhen()); resp.setHeader("X-UA-Compatible", "IE=Edge,chrome=1"); if (ctx.getRequest().hasHeader("If-Modified-Since")) { long dd = this.file.getWhen() - ctx.getRequest().getDateHeader("If-Modified-Since"); // getDate does not return consistent results because milliseconds // are not cleared correctly see: // https://sourceforge.net/tracker/index.php?func=detail&aid=3162870&group_id=62369&atid=500353 // so ignore differences of less than 1000, they are false positives if (dd < 1000) { resp.setStatus(HttpResponseStatus.NOT_MODIFIED); ctx.send(); return; } } if (!ctx.getSite().getMimeCompress(this.mime)) resp.setHeader(HttpHeaders.Names.CONTENT_ENCODING, HttpHeaders.Values.IDENTITY); ctx.sendStart(0); // TODO send from memory cache if small enough try { ctx.send(new HttpChunkedInput(new ChunkedNioFile(this.file.getFilePath().toFile()))); // TODO not ideal, cleanup so direct reference to path is not needed } catch (IOException x) { // TODO improve support } ctx.sendEnd(); } }