1 module hunt.http.server.Http1ServerRequestHandler; 2 3 import hunt.http.server.Http1ServerConnection; 4 import hunt.http.server.HttpServerHandler; 5 import hunt.http.server.HttpServerResponse; 6 import hunt.http.server.ServerHttpHandler; 7 8 import hunt.http.codec.http.decode.HttpParser; 9 import hunt.http.codec.http.model; 10 11 import hunt.container.ByteBuffer; 12 import hunt.string; 13 14 import hunt.logging; 15 import std.string : icmp; 16 17 alias RequestHandler = HttpParser.RequestHandler; 18 19 20 class HttpServerRequest : HttpRequest { 21 22 this(string method, string uri, HttpVersion ver) { 23 enum string connect = HttpMethod.CONNECT.asString(); 24 super(method, 25 new HttpURI(icmp(method, connect) == 0 ? "http://" ~ uri : uri), 26 ver, new HttpFields()); 27 // super(method, new HttpURI(HttpMethod.fromString(method) == HttpMethod.CONNECT ? "http://" ~ uri : uri), ver, new HttpFields()); 28 } 29 } 30 31 /** 32 */ 33 class Http1ServerRequestHandler : RequestHandler { 34 package(hunt.http.server) HttpRequest request; 35 package(hunt.http.server) HttpResponse response; 36 package(hunt.http.server) Http1ServerConnection connection; 37 package(hunt.http.server) Http1ServerResponseOutputStream outputStream; 38 package(hunt.http.server) ServerHttpHandler serverHttpHandler; 39 package(hunt.http.server) HttpFields trailer; 40 41 this(ServerHttpHandler serverHttpHandler) { 42 this.serverHttpHandler = serverHttpHandler; 43 } 44 45 override bool startRequest(string method, string uri, HttpVersion ver) { 46 version (HUNT_DEBUG) { 47 tracef("server received the request line, %s, %s, %s", method, uri, ver); 48 } 49 50 request = new HttpServerRequest(method, uri, ver); 51 response = new HttpServerResponse(); 52 outputStream = new Http1ServerResponseOutputStream(response, connection); 53 54 return HttpMethod.PRI.isSame(method) && connection.directUpgradeHttp2(request); 55 } 56 57 override void parsedHeader(HttpField field) { 58 request.getFields().add(field); 59 } 60 61 override bool headerComplete() { 62 if (HttpMethod.CONNECT.asString().equalsIgnoreCase(request.getMethod())) { 63 return serverHttpHandler.acceptHttpTunnelConnection(request, 64 response, outputStream, connection); 65 } else { 66 string expectedValue = request.getFields().get(HttpHeader.EXPECT); 67 if ("100-continue".equalsIgnoreCase(expectedValue)) { 68 bool skipNext = serverHttpHandler.accept100Continue(request, 69 response, outputStream, connection); 70 if (skipNext) { 71 return true; 72 } else { 73 connection.response100Continue(); 74 return serverHttpHandler.headerComplete(request, response, 75 outputStream, connection); 76 } 77 } else { 78 return serverHttpHandler.headerComplete(request, response, 79 outputStream, connection); 80 } 81 } 82 } 83 84 override bool content(ByteBuffer item) { 85 return serverHttpHandler.content(item, request, response, outputStream, connection); 86 } 87 88 override bool contentComplete() { 89 return serverHttpHandler.contentComplete(request, response, outputStream, connection); 90 } 91 92 override void parsedTrailer(HttpField field) { 93 if (trailer is null) { 94 trailer = new HttpFields(); 95 request.setTrailerSupplier(() => trailer); 96 } 97 trailer.add(field); 98 } 99 100 override bool messageComplete() { 101 try { 102 if (connection.getUpgradeHttp2Complete() || connection.getUpgradeWebSocketComplete()) { 103 return true; 104 } else { 105 bool success = connection.upgradeProtocol(request, response, 106 outputStream, connection); 107 return success || serverHttpHandler.messageComplete(request, 108 response, outputStream, connection); 109 } 110 } catch (Exception ex) { 111 error("Upgrade failed: ", ex.msg); 112 return true; 113 } finally { 114 connection.getParser().reset(); 115 } 116 } 117 118 override void badMessage(int status, string reason) { 119 serverHttpHandler.badMessage(status, reason, request, response, outputStream, connection); 120 } 121 122 void badMessage(BadMessageException failure) { 123 badMessage(failure.getCode(), failure.getReason()); 124 } 125 126 override void earlyEOF() { 127 serverHttpHandler.earlyEOF(request, response, outputStream, connection); 128 } 129 130 override int getHeaderCacheSize() { 131 return 1024; 132 } 133 134 }