package jj.http.server; import java.math.BigDecimal; import java.net.SocketAddress; import java.net.URI; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Locale; import java.util.Map.Entry; import javax.inject.Inject; import javax.inject.Singleton; import jj.http.server.uri.URIMatch; import jj.util.Sequence; import io.netty.channel.ChannelHandlerContext; import io.netty.util.AsciiString; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpMethod; @Singleton class HttpServerRequestImpl implements HttpServerRequest { private static final Sequence sequence = new Sequence(); private static final AsciiString HEADER_X_HOST = new AsciiString("X-Host"); private static final AsciiString HEADER_X_FORWARDED_PROTO = new AsciiString("X-Forwarded-Proto"); private final long startTime = System.nanoTime(); private final String id = sequence.next(); private final FullHttpRequest request; private final URIMatch uriMatch; private final ChannelHandlerContext ctx; @Inject HttpServerRequestImpl(final FullHttpRequest request, final ChannelHandlerContext ctx) { this.request = request; this.uriMatch = new URIMatch(request.uri()); this.ctx = ctx; } @Override public BigDecimal wallTime() { return BigDecimal.valueOf(System.nanoTime() - startTime, 6); } @Override public String id() { return id; } @Override public String host() { CharSequence xHost = header(HEADER_X_HOST); CharSequence host = header(HttpHeaderNames.HOST); return (xHost == null ? host : xHost).toString(); } @Override public boolean secure() { return "https".equals(header(HEADER_X_FORWARDED_PROTO)); } @Override public URI absoluteUri() { return URI.create( new StringBuilder("http") .append(secure() ? "s" : "") .append("://") .append(host()) .append(uriMatch().uri) .toString() ); } /** * @return */ @Override public long timestamp() { return startTime; } /** * @return */ @Override public Charset charset() { return StandardCharsets.UTF_8; } public URIMatch uriMatch() { return uriMatch; } /** * @param ifNoneMatch * @return */ @Override public boolean hasHeader(AsciiString ifNoneMatch) { return request.headers().contains(ifNoneMatch); } /** * @param etag * @return */ @Override public CharSequence header(AsciiString name) { return request.headers().get(name); } /** * @return */ @Override public String body() { return request.content().toString(charset()); } /** * @return */ @Override public HttpMethod method() { return request.method(); } /** * @return */ @Override public Iterable<Entry<String, String>> allHeaders() { return request.headers(); } @Override public Locale locale() { // TODO make this not hard-coded! haha return Locale.US; } @Override public Cookie cookie(String name) { return null; } @Override public List<Cookie> cookies() { // TODO Auto-generated method stub return null; } /** * @return */ public SocketAddress remoteAddress() { return ctx.channel().remoteAddress(); } /** * @return */ protected FullHttpRequest request() { return request; } @Override public String toString() { return request.toString(); } }