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 }