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         if(!_options.canUpgrade()) {
103             return true;
104         }
105         
106         try {
107             if (connection.getUpgradeHttp2Complete() || connection.getUpgradeWebSocketComplete()) {
108                 return true;
109             } else {
110                 bool success = connection.upgradeProtocol(request, response,
111                         outputStream, connection);
112                 return success || serverHttpHandler.messageComplete(request,
113                         response, outputStream, connection);
114             }
115         } catch (Exception ex) {
116             error("Upgrade failed: ", ex.msg);
117             return true;
118         } finally {
119             connection.getParser().reset();
120         }
121     }
122 
123     override void badMessage(int status, string reason) {
124         if(response is null) {
125             response = new HttpServerResponse(status, reason);
126             outputStream = new Http1ServerResponseOutputStream(response, connection);
127         }
128         serverHttpHandler.badMessage(status, reason, request, response, outputStream, connection);
129     }
130 
131     void badMessage(BadMessageException failure) {
132         badMessage(failure.getCode(), failure.getReason());
133     }
134 
135     override void earlyEOF() {
136         serverHttpHandler.earlyEOF(request, response, outputStream, connection);
137     }
138 
139     override int getHeaderCacheSize() {
140         return 1024;
141     }
142 
143 }