1 module hunt.http.server.Http1ServerRequestHandler;
2 
3 import hunt.http.server.Http1ServerConnection;
4 import hunt.http.server.HttpServerOptions;
5 import hunt.http.server.HttpServerRequest;
6 import hunt.http.server.HttpServerResponse;
7 import hunt.http.server.ServerHttpHandler;
8 
9 import hunt.http.codec.http.decode.HttpParser;
10 import hunt.http.codec.http.model;
11 
12 import hunt.http.HttpField;
13 import hunt.http.HttpFields;
14 import hunt.http.HttpHeader;
15 import hunt.http.HttpMethod;
16 import hunt.http.HttpResponse;
17 import hunt.http.HttpVersion;
18 
19 import hunt.io.ByteBuffer;
20 import hunt.text.Common;
21 
22 import hunt.logging;
23 import std.string : icmp;
24 
25 // alias RequestHandler = HttpParser.RequestHandler;
26 
27 
28 /**
29  * 
30  */
31 class Http1ServerRequestHandler : HttpRequestParsingHandler {
32     package HttpServerRequest request;
33     package HttpServerResponse response;
34     package Http1ServerConnection connection;
35     package Http1ServerResponseOutputStream outputStream;
36     package ServerHttpHandler serverHttpHandler;
37     package HttpFields trailer;
38     private HttpServerOptions _options;
39 
40     this(ServerHttpHandler serverHttpHandler, HttpServerOptions options) {
41         this.serverHttpHandler = serverHttpHandler;
42         _options = options;
43     }
44 
45     override bool startRequest(string method, string uri, HttpVersion ver) {
46         version (HUNT_HTTP_DEBUG) {
47             tracef("server received the request line, %s, %s, %s", method, uri, ver);
48         }
49 
50         request = new HttpServerRequest(method, uri, ver, _options);
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         assert(request !is null, "Execute startRequest first");
90         return serverHttpHandler.contentComplete(request, response, outputStream, connection);
91     }
92 
93     override void parsedTrailer(HttpField field) {
94         if (trailer is null) {
95             trailer = new HttpFields();
96             request.setTrailerSupplier(() => trailer);
97         }
98         trailer.add(field);
99     }
100 
101     override bool messageComplete() {
102         try {
103             if (connection.getUpgradeHttp2Complete() || connection.getUpgradeWebSocketComplete()) {
104                 return true;
105             } else {
106                 bool success = connection.upgradeProtocol(request, response,
107                         outputStream, connection);
108                 return success || serverHttpHandler.messageComplete(request,
109                         response, outputStream, connection);
110             }
111         } catch (Exception ex) {
112             error("Upgrade failed: ", ex.msg);
113             return true;
114         } finally {
115             connection.getParser().reset();
116         }
117     }
118 
119     override void badMessage(int status, string reason) {
120         if(response is null) {
121             response = new HttpServerResponse(status, reason);
122             outputStream = new Http1ServerResponseOutputStream(response, connection);
123         }
124         serverHttpHandler.badMessage(status, reason, request, response, outputStream, connection);
125     }
126 
127     void badMessage(BadMessageException failure) {
128         badMessage(failure.getCode(), failure.getReason());
129     }
130 
131     override void earlyEOF() {
132         serverHttpHandler.earlyEOF(request, response, outputStream, connection);
133     }
134 
135     override int getHeaderCacheSize() {
136         return 1024;
137     }
138 
139 }