1 module hunt.http.server.Http1ServerDecoder;
2 
3 import hunt.http.server.Http1ServerConnection;
4 import hunt.http.server.Http1ServerTunnelConnection;
5 import hunt.http.server.Http2ServerDecoder;
6 
7 import hunt.http.codec.http.decode.HttpParser;
8 import hunt.http.codec.websocket.decode.WebSocketDecoder;
9 
10 import hunt.http.HttpConnection;
11 import hunt.http.HttpConnection;
12 import hunt.net.codec.Decoder;
13 import hunt.http.HttpConnection;
14 import hunt.net.Connection;
15 
16 import hunt.io.ByteBuffer;
17 import hunt.io.BufferUtils;
18 import hunt.Exceptions;
19 import hunt.logging;
20 import std.conv;
21 
22 /**
23 */
24 class Http1ServerDecoder : DecoderChain {
25 
26     private WebSocketDecoder webSocketDecoder;
27     private Http2ServerDecoder http2ServerDecoder;
28 
29     this(WebSocketDecoder webSocketDecoder, Http2ServerDecoder http2ServerDecoder) {
30         super(null);
31         this.webSocketDecoder = webSocketDecoder;
32         this.http2ServerDecoder = http2ServerDecoder;
33     }
34 
35     override void decode(ByteBuffer buffer, Connection session) {
36         ByteBuffer buf = BufferUtils.toHeapBuffer(buffer);
37 
38         Object attachment = session.getAttribute(HttpConnection.NAME);
39         version (HUNT_HTTP_DEBUG) {
40             tracef("session type: %s", attachment is null ? "null" : typeid(attachment).name);
41         }
42 
43         AbstractHttpConnection abstractConnection = cast(AbstractHttpConnection) attachment;
44         if (abstractConnection is null) {
45             warningf("Bad connection instance: %s", attachment is null ? "null" : typeid(attachment).name);
46             return;
47         }
48 
49         switch (abstractConnection.getConnectionType()) {
50         case HttpConnectionType.HTTP1: {
51                 Http1ServerConnection http1Connection = cast(Http1ServerConnection) attachment;
52                 if (http1Connection.getTunnelConnectionPromise() is null) {
53                     HttpParser parser = http1Connection.getParser();
54                     version (HUNT_HTTP_DEBUG) trace("runing http1 parser for a buffer...");
55                     while (buf.hasRemaining()) {
56                         parser.parseNext(buf);
57                         if (http1Connection.getUpgradeHttp2Complete()) {
58                             http2ServerDecoder.decode(buf, session);
59                             break;
60                         } else if (http1Connection.getUpgradeWebSocketComplete()) {
61                             webSocketDecoder.decode(buf, session);
62                             break;
63                         }
64                     }
65                     version (HUNT_HTTP_DEBUG) trace("http1 parsing done for a buffer...");
66                 } else {
67                     Http1ServerTunnelConnection tunnelConnection = http1Connection.createHttpTunnel();
68                     if (tunnelConnection.content != null) {
69                         tunnelConnection.content(buf);
70                     }
71                 }
72             }
73             break;
74         case HttpConnectionType.HTTP2: {
75                 http2ServerDecoder.decode(buf, session);
76             }
77             break;
78         case HttpConnectionType.WEB_SOCKET: {
79                 webSocketDecoder.decode(buf, session);
80             }
81             break;
82         case HttpConnectionType.HTTP_TUNNEL: {
83                 Http1ServerTunnelConnection tunnelConnection = 
84                     cast(Http1ServerTunnelConnection) session.getAttribute(HttpConnection.NAME); // session.getAttachment();
85                 if (tunnelConnection.content != null) {
86                     tunnelConnection.content(buf);
87                 }
88             }
89             break;
90         default:
91             throw new IllegalStateException("client does not support the protocol " ~ to!string(
92                     abstractConnection.getConnectionType()));
93         }
94     }
95 }