package net.cubespace.dynmap.multiserver.HTTP.Handler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.*; import io.netty.handler.stream.ChunkedStream; import net.cubespace.dynmap.multiserver.DynmapServer; import net.cubespace.dynmap.multiserver.HTTP.HandlerUtil; import net.cubespace.dynmap.multiserver.Main; import net.cubespace.dynmap.multiserver.util.AbstractFile; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import static io.netty.handler.codec.http.HttpHeaders.Names.*; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; /** * @author geNAZt (fabian.fassbender42@googlemail.com) */ public class FacesFileHandler implements IHandler { @Override public void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { //Get the correct DynmapServer for (DynmapServer dynmapServer : Main.getDynmapServers()) { AbstractFile file = dynmapServer.getFile(request.getUri()); if (file.exists()) { if (file.isHidden() || !file.exists()) { HandlerUtil.sendError(ctx, NOT_FOUND); return; } if (!file.isFile()) { HandlerUtil.sendError(ctx, FORBIDDEN); return; } // Cache Validation String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE); if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HandlerUtil.HTTP_DATE_FORMAT, Locale.US); Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince); // Only compare up to the second because the datetime format we send to the client // does not have milliseconds long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000; long fileLastModifiedSeconds = file.lastModified() / 1000; if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) { HandlerUtil.sendNotModified(ctx); return; } } ReadableByteChannel channel = Channels.newChannel(file.getInputStream()); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); HandlerUtil.setContentTypeHeader(response, file.getName()); HandlerUtil.setDateAndCacheHeaders(response, file.lastModified()); response.headers().set(CONTENT_LENGTH, file.length()); response.headers().set(CONNECTION, HttpHeaders.Values.CLOSE); response.headers().set(VARY, ACCEPT_ENCODING); // Write the initial line and the header. ctx.write(response); // Write the content. ctx.write(new ChunkedStream(file.getInputStream())); ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); return; } } HandlerUtil.sendError(ctx, NOT_FOUND); } }