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