1 module hunt.http.server.Http2ServerRequestHandler; 2 3 import hunt.http.server.HttpServerResponse; 4 import hunt.http.server.Http2ServerConnection; 5 import hunt.http.server.ServerHttpHandler; 6 import hunt.http.server.ServerSessionListener; 7 8 import hunt.http.codec.http.frame; 9 import hunt.http.codec.http.model; 10 import hunt.http.codec.http.stream.AbstractHttp2OutputStream; 11 import hunt.http.codec.http.stream.Session; 12 import hunt.http.codec.http.stream.Stream; 13 14 import hunt.http.codec.http.stream.DataFrameHandler; 15 16 import hunt.http.HttpFields; 17 import hunt.http.HttpHeader; 18 import hunt.http.HttpMetaData; 19 import hunt.http.HttpMethod; 20 import hunt.http.HttpRequest; 21 import hunt.http.HttpResponse; 22 import hunt.http.HttpStatus; 23 import hunt.http.HttpVersion; 24 import hunt.http.Version; 25 26 import hunt.Exceptions; 27 import hunt.util.Common; 28 import hunt.text.Common; 29 30 import hunt.logging; 31 import std.conv; 32 import std.string; 33 34 alias StreamListener = hunt.http.codec.http.stream.Stream.Stream.Listener; 35 36 /** 37 */ 38 class Http2ServerRequestHandler : ServerSessionListener.Adapter { 39 40 private ServerHttpHandler serverHttpHandler; 41 Http2ServerConnection connection; 42 43 this(ServerHttpHandler serverHttpHandler) { 44 this.serverHttpHandler = serverHttpHandler; 45 } 46 47 override 48 void onClose(Session session, GoAwayFrame frame) { 49 warningf("Server received the GoAwayFrame -> %s", frame.toString()); 50 connection.close(); 51 } 52 53 override 54 void onFailure(Session session, Exception failure) { 55 errorf("Server failure: " ~ session.toString(), failure); 56 // Optional.ofNullable(connection).ifPresent(IO::close); 57 if(connection !is null) 58 connection.close(); 59 } 60 61 override 62 void onReset(Session session, ResetFrame frame) { 63 warningf("Server received ResetFrame %s", frame.toString()); 64 // Optional.ofNullable(connection).ifPresent(IO::close); 65 66 if(connection !is null) 67 connection.close(); 68 } 69 70 override 71 StreamListener onNewStream(Stream stream, HeadersFrame headersFrame) { 72 if (!headersFrame.getMetaData().isRequest()) { 73 throw new IllegalArgumentException("the stream " ~ stream.getId().to!string() ~ " received meta data that is not request type"); 74 } 75 76 version(HUNT_DEBUG) { 77 tracef("Server received stream: %s, %s", stream.getId(), headersFrame.toString()); 78 } 79 80 HttpRequest request = cast(HttpRequest) headersFrame.getMetaData(); 81 HttpResponse response = new HttpServerResponse(); 82 ServerHttp2OutputStream output = new ServerHttp2OutputStream(response, stream); 83 84 string expectedValue = request.getFields().get(HttpHeader.EXPECT); 85 if ("100-continue".equalsIgnoreCase(expectedValue)) { 86 bool skipNext = serverHttpHandler.accept100Continue(request, response, output, connection); 87 if (!skipNext) { 88 HttpResponse continue100 = new HttpResponse(HttpVersion.HTTP_1_1, 89 HttpStatus.CONTINUE_100, HttpStatus.Code.CONTINUE.getMessage(), 90 new HttpFields(), -1); 91 output.writeFrame(new HeadersFrame(stream.getId(), continue100, null, false)); 92 } 93 } else { 94 serverHttpHandler.headerComplete(request, response, output, connection); 95 if (headersFrame.isEndStream()) { 96 serverHttpHandler.messageComplete(request, response, output, connection); 97 } 98 } 99 100 101 102 return new class StreamListener.Adapter { 103 override 104 void onHeaders(Stream stream, HeadersFrame trailerFrame) { 105 version(HUNT_DEBUG) { 106 tracef("Server received trailer frame: %s, %s", stream.toString(), trailerFrame); 107 } 108 109 if (trailerFrame.isEndStream()) { 110 request.setTrailerSupplier(() => trailerFrame.getMetaData().getFields()); 111 serverHttpHandler.contentComplete(request, response, output, connection); 112 serverHttpHandler.messageComplete(request, response, output, connection); 113 } else { 114 throw new IllegalArgumentException("the stream " ~ stream.getId().to!string() ~ " received illegal meta data"); 115 } 116 } 117 118 override 119 void onData(Stream stream, DataFrame dataFrame, Callback callback) { 120 DataFrameHandler.handleDataFrame(dataFrame, callback, request, response, output, connection, serverHttpHandler); 121 } 122 123 override 124 void onReset(Stream stream, ResetFrame resetFrame) { 125 int errorCode = resetFrame.getError(); 126 string reason; 127 int status = HttpStatus.INTERNAL_SERVER_ERROR_500; 128 if (isValidErrorCode(errorCode)) { 129 switch (cast(ErrorCode)errorCode) { 130 case ErrorCode.PROTOCOL_ERROR: 131 status = HttpStatus.BAD_REQUEST_400; 132 break; 133 default: 134 status = HttpStatus.INTERNAL_SERVER_ERROR_500; 135 break; 136 } 137 reason = (cast(ErrorCode)errorCode).to!string().toLower(); 138 } 139 else 140 reason = "error=" ~ resetFrame.getError().to!string(); 141 142 serverHttpHandler.badMessage(status, reason, request, response, output, connection); 143 } 144 }; 145 } 146 147 static class ServerHttp2OutputStream : AbstractHttp2OutputStream { 148 149 private Stream stream; 150 151 this(HttpMetaData info, Stream stream) { 152 super(info, false); 153 this.stream = stream; 154 info.getFields().put(HttpHeader.X_POWERED_BY, X_POWERED_BY_VALUE); 155 info.getFields().put(HttpHeader.SERVER, SERVER_VALUE); 156 } 157 158 override 159 protected Stream getStream() { 160 return stream; 161 } 162 } 163 164 }