1 module client; 2 3 import std.stdio; 4 5 import hunt.http.client.ClientHttp2SessionListener; 6 import hunt.http.client.HttpClient; 7 import hunt.http.client.Http2ClientConnection; 8 import hunt.http.client.HttpClientConnection; 9 10 import hunt.http.codec.http.frame; 11 import hunt.http.codec.http.model; 12 import hunt.http.codec.http.stream; 13 14 import hunt.lang.exception; 15 import hunt.lang.common; 16 import hunt.util.concurrent.FuturePromise; 17 18 import hunt.container; 19 import hunt.logging; 20 import std.format; 21 22 23 void main(string[] args) { 24 25 enum host = "127.0.0.1"; 26 enum port = 6677; 27 28 Http2Configuration http2Configuration = new Http2Configuration(); 29 http2Configuration.setSecureConnectionEnabled(false); 30 http2Configuration.setFlowControlStrategy("simple"); 31 http2Configuration.getTcpConfiguration().setTimeout(60 * 1000); 32 http2Configuration.setProtocol(HttpVersion.HTTP_2.asString()); 33 34 FuturePromise!(HttpClientConnection) promise = new FuturePromise!(HttpClientConnection)(); 35 HttpClient client = new HttpClient(http2Configuration); 36 37 client.connect(host, port, promise, new class ClientHttp2SessionListener { 38 39 override 40 Map!(int, int) onPreface(Session session) { 41 infof("client preface: %s", session); 42 Map!(int, int) settings = new HashMap!(int, int)(); 43 settings.put(SettingsFrame.HEADER_TABLE_SIZE, http2Configuration.getMaxDynamicTableSize()); 44 settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, http2Configuration.getInitialStreamSendWindow()); 45 return settings; 46 } 47 48 override 49 StreamListener onNewStream(Stream stream, HeadersFrame frame) { 50 return null; 51 } 52 53 override 54 void onSettings(Session session, SettingsFrame frame) { 55 infof("client received settings frame: %s", frame.toString()); 56 } 57 58 override 59 void onPing(Session session, PingFrame frame) { 60 } 61 62 override 63 void onReset(Session session, ResetFrame frame) { 64 infof("client resets %s", frame.toString()); 65 } 66 67 override 68 void onClose(Session session, GoAwayFrame frame) { 69 infof("client is closed %s", frame.toString()); 70 } 71 72 override 73 void onFailure(Session session, Exception failure) { 74 errorf("client failure, %s", failure, session); 75 } 76 77 override 78 bool onIdleTimeout(Session session) { 79 return false; 80 } 81 }); 82 83 84 HttpFields fields = new HttpFields(); 85 fields.put(HttpHeader.ACCEPT, "text/html"); 86 fields.put(HttpHeader.USER_AGENT, "Hunt Client 1.0"); 87 fields.put(HttpHeader.CONTENT_LENGTH, "28"); 88 HttpRequest metaData = new HttpRequest("POST", HttpScheme.HTTP, 89 new HostPortHttpField(format("%s:%d", host, port)), "/data", HttpVersion.HTTP_2, fields); 90 91 HttpConnection connection = promise.get(); 92 Http2ClientConnection clientConnection = cast(Http2ClientConnection) connection; 93 94 FuturePromise!(Stream) streamPromise = new FuturePromise!(Stream)(); 95 auto http2Session = clientConnection.getHttp2Session(); 96 http2Session.newStream(new HeadersFrame(metaData, null, false), streamPromise, 97 new class StreamListener { 98 99 override 100 void onHeaders(Stream stream, HeadersFrame frame) { 101 infof("client received headers: %s", frame.toString()); 102 } 103 104 override 105 StreamListener onPush(Stream stream, 106 PushPromiseFrame frame) { 107 return null; 108 } 109 110 override 111 void onData(Stream stream, DataFrame frame, Callback callback) { 112 infof("client received data: %s, %s", BufferUtils.toString(frame.getData()), frame.toString()); 113 callback.succeeded(); 114 } 115 116 void onReset(Stream stream, ResetFrame frame, Callback callback) { 117 try { 118 onReset(stream, frame); 119 callback.succeeded(); 120 } catch (Exception x) { 121 callback.failed(x); 122 } 123 } 124 125 override 126 void onReset(Stream stream, ResetFrame frame) { 127 infof("client reset: %s, %s", stream, frame.toString()); 128 } 129 130 override 131 bool onIdleTimeout(Stream stream, Exception x) { 132 errorf("the client stream %s is timeout", stream.toString()); 133 return true; 134 } 135 136 override string toString() 137 { 138 return super.toString(); 139 } 140 141 } 142 ); 143 144 Stream clientStream = streamPromise.get(); 145 infof("client stream id is %d", clientStream.getId()); 146 147 DataFrame smallDataFrame = new DataFrame(clientStream.getId(), 148 ByteBuffer.wrap(cast(byte[])"hello world!"), false); 149 DataFrame bigDataFrame = new DataFrame(clientStream.getId(), 150 ByteBuffer.wrap(cast(byte[])"big hello world!"), true); 151 152 clientStream.data(smallDataFrame, new class NoopCallback { 153 154 override 155 void succeeded() { 156 infof("client sents small data success"); 157 clientStream.data(bigDataFrame, new class NoopCallback { 158 159 override 160 void succeeded() { 161 infof("client sents big data success"); 162 } 163 164 override 165 void failed(Exception x) { 166 infof("client sents big data failure"); 167 } 168 }); 169 } 170 171 override 172 void failed(Exception x) { 173 infof("client sents small data failure"); 174 } 175 }); 176 177 }