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