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 }