1 | // |
2 | // HTTPServerTest.cpp |
3 | // |
4 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "HTTPServerTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "Poco/Net/HTTPServer.h" |
15 | #include "Poco/Net/HTTPServerParams.h" |
16 | #include "Poco/Net/AbstractHTTPRequestHandler.h" |
17 | #include "Poco/Net/HTTPRequestHandlerFactory.h" |
18 | #include "Poco/Net/HTTPClientSession.h" |
19 | #include "Poco/Net/HTTPRequest.h" |
20 | #include "Poco/Net/HTTPServerRequest.h" |
21 | #include "Poco/Net/HTTPResponse.h" |
22 | #include "Poco/Net/HTTPServerResponse.h" |
23 | #include "Poco/Net/ServerSocket.h" |
24 | #include "Poco/StreamCopier.h" |
25 | #include <sstream> |
26 | |
27 | |
28 | using Poco::Net::HTTPServer; |
29 | using Poco::Net::HTTPServerParams; |
30 | using Poco::Net::HTTPRequestHandler; |
31 | using Poco::Net::AbstractHTTPRequestHandler; |
32 | using Poco::Net::HTTPRequestHandlerFactory; |
33 | using Poco::Net::HTTPClientSession; |
34 | using Poco::Net::HTTPRequest; |
35 | using Poco::Net::HTTPServerRequest; |
36 | using Poco::Net::HTTPResponse; |
37 | using Poco::Net::HTTPServerResponse; |
38 | using Poco::Net::HTTPMessage; |
39 | using Poco::Net::ServerSocket; |
40 | using Poco::StreamCopier; |
41 | |
42 | |
43 | namespace |
44 | { |
45 | class EchoBodyRequestHandler: public HTTPRequestHandler |
46 | { |
47 | public: |
48 | void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) |
49 | { |
50 | if (request.getChunkedTransferEncoding()) |
51 | response.setChunkedTransferEncoding(true); |
52 | else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH) |
53 | response.setContentLength(request.getContentLength()); |
54 | |
55 | response.setContentType(request.getContentType()); |
56 | |
57 | std::istream& istr = request.stream(); |
58 | std::ostream& ostr = response.send(); |
59 | StreamCopier::copyStream(istr, ostr); |
60 | } |
61 | }; |
62 | |
63 | class EchoHeaderRequestHandler: public HTTPRequestHandler |
64 | { |
65 | public: |
66 | void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) |
67 | { |
68 | std::ostringstream osstr; |
69 | request.write(osstr); |
70 | int n = (int) osstr.str().length(); |
71 | response.setContentLength(n); |
72 | std::ostream& ostr = response.send(); |
73 | if (request.getMethod() != HTTPRequest::HTTP_HEAD) |
74 | request.write(ostr); |
75 | } |
76 | }; |
77 | |
78 | class RedirectRequestHandler: public AbstractHTTPRequestHandler |
79 | { |
80 | public: |
81 | void run() |
82 | { |
83 | response().redirect("http://www.appinf.com/" ); |
84 | } |
85 | }; |
86 | |
87 | class AuthRequestHandler: public HTTPRequestHandler |
88 | { |
89 | public: |
90 | void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) |
91 | { |
92 | response.requireAuthentication("/auth" ); |
93 | response.send(); |
94 | } |
95 | }; |
96 | |
97 | class BufferRequestHandler: public HTTPRequestHandler |
98 | { |
99 | public: |
100 | void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) |
101 | { |
102 | std::string data("xxxxxxxxxx" ); |
103 | response.sendBuffer(data.data(), data.length()); |
104 | } |
105 | }; |
106 | |
107 | class RequestHandlerFactory: public HTTPRequestHandlerFactory |
108 | { |
109 | public: |
110 | HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) |
111 | { |
112 | if (request.getURI() == "/echoBody" ) |
113 | return new EchoBodyRequestHandler; |
114 | else if (request.getURI() == "/echoHeader" ) |
115 | return new EchoHeaderRequestHandler; |
116 | else if (request.getURI() == "/redirect" ) |
117 | return new RedirectRequestHandler(); |
118 | else if (request.getURI() == "/auth" ) |
119 | return new AuthRequestHandler(); |
120 | else if (request.getURI() == "/buffer" ) |
121 | return new BufferRequestHandler(); |
122 | else |
123 | return 0; |
124 | } |
125 | }; |
126 | } |
127 | |
128 | |
129 | HTTPServerTest::HTTPServerTest(const std::string& name): CppUnit::TestCase(name) |
130 | { |
131 | } |
132 | |
133 | |
134 | HTTPServerTest::~HTTPServerTest() |
135 | { |
136 | } |
137 | |
138 | |
139 | void HTTPServerTest::testIdentityRequest() |
140 | { |
141 | ServerSocket svs(0); |
142 | HTTPServerParams* pParams = new HTTPServerParams; |
143 | pParams->setKeepAlive(false); |
144 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
145 | srv.start(); |
146 | |
147 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
148 | std::string body(5000, 'x'); |
149 | HTTPRequest request("POST" , "/echoBody" ); |
150 | request.setContentLength((int) body.length()); |
151 | request.setContentType("text/plain" ); |
152 | cs.sendRequest(request) << body; |
153 | HTTPResponse response; |
154 | std::string rbody; |
155 | cs.receiveResponse(response) >> rbody; |
156 | assertTrue (response.getContentLength() == body.size()); |
157 | assertTrue (response.getContentType() == "text/plain" ); |
158 | assertTrue (rbody == body); |
159 | } |
160 | |
161 | |
162 | void HTTPServerTest::testPutIdentityRequest() |
163 | { |
164 | ServerSocket svs(0); |
165 | HTTPServerParams* pParams = new HTTPServerParams; |
166 | pParams->setKeepAlive(false); |
167 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
168 | srv.start(); |
169 | |
170 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
171 | std::string body(5000, 'x'); |
172 | HTTPRequest request("PUT" , "/echoBody" ); |
173 | request.setContentLength((int) body.length()); |
174 | request.setContentType("text/plain" ); |
175 | cs.sendRequest(request) << body; |
176 | HTTPResponse response; |
177 | std::string rbody; |
178 | cs.receiveResponse(response) >> rbody; |
179 | assertTrue (response.getContentLength() == body.size()); |
180 | assertTrue (response.getContentType() == "text/plain" ); |
181 | assertTrue (rbody == body); |
182 | } |
183 | |
184 | |
185 | void HTTPServerTest::testChunkedRequest() |
186 | { |
187 | ServerSocket svs(0); |
188 | HTTPServerParams* pParams = new HTTPServerParams; |
189 | pParams->setKeepAlive(false); |
190 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
191 | srv.start(); |
192 | |
193 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
194 | std::string body(5000, 'x'); |
195 | HTTPRequest request("POST" , "/echoBody" ); |
196 | request.setContentType("text/plain" ); |
197 | request.setChunkedTransferEncoding(true); |
198 | cs.sendRequest(request) << body; |
199 | HTTPResponse response; |
200 | std::string rbody; |
201 | cs.receiveResponse(response) >> rbody; |
202 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
203 | assertTrue (response.getContentType() == "text/plain" ); |
204 | assertTrue (response.getChunkedTransferEncoding()); |
205 | assertTrue (rbody == body); |
206 | } |
207 | |
208 | |
209 | void HTTPServerTest::testClosedRequest() |
210 | { |
211 | ServerSocket svs(0); |
212 | HTTPServerParams* pParams = new HTTPServerParams; |
213 | pParams->setKeepAlive(false); |
214 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
215 | srv.start(); |
216 | |
217 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
218 | std::string body(5000, 'x'); |
219 | HTTPRequest request("POST" , "/echoBody" ); |
220 | request.setContentType("text/plain" ); |
221 | cs.sendRequest(request) << body; |
222 | HTTPResponse response; |
223 | std::string rbody; |
224 | cs.receiveResponse(response) >> rbody; |
225 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
226 | assertTrue (response.getContentType() == "text/plain" ); |
227 | assertTrue (!response.getChunkedTransferEncoding()); |
228 | assertTrue (rbody == body); |
229 | } |
230 | |
231 | |
232 | void HTTPServerTest::testIdentityRequestKeepAlive() |
233 | { |
234 | HTTPServer srv(new RequestHandlerFactory, 8008); |
235 | srv.start(); |
236 | |
237 | HTTPClientSession cs("127.0.0.1" , srv.socket().address().port()); |
238 | cs.setKeepAlive(true); |
239 | std::string body(5000, 'x'); |
240 | HTTPRequest request("POST" , "/echoBody" , HTTPMessage::HTTP_1_1); |
241 | request.setContentLength((int) body.length()); |
242 | request.setContentType("text/plain" ); |
243 | cs.sendRequest(request) << body; |
244 | HTTPResponse response; |
245 | std::string rbody; |
246 | cs.receiveResponse(response) >> rbody; |
247 | assertTrue (response.getContentLength() == body.size()); |
248 | assertTrue (response.getContentType() == "text/plain" ); |
249 | assertTrue (response.getKeepAlive()); |
250 | assertTrue (rbody == body); |
251 | |
252 | body.assign(1000, 'y'); |
253 | request.setContentLength((int) body.length()); |
254 | request.setKeepAlive(false); |
255 | cs.sendRequest(request) << body; |
256 | cs.receiveResponse(response) >> rbody; |
257 | assertTrue (response.getContentLength() == body.size()); |
258 | assertTrue (response.getContentType() == "text/plain" ); |
259 | assertTrue (!response.getKeepAlive()); |
260 | assertTrue (rbody == body);} |
261 | |
262 | |
263 | void HTTPServerTest::testChunkedRequestKeepAlive() |
264 | { |
265 | HTTPServer srv(new RequestHandlerFactory, 8009); |
266 | srv.start(); |
267 | |
268 | HTTPClientSession cs("127.0.0.1" , srv.socket().address().port()); |
269 | cs.setKeepAlive(true); |
270 | std::string body(5000, 'x'); |
271 | HTTPRequest request("POST" , "/echoBody" , HTTPMessage::HTTP_1_1); |
272 | request.setContentType("text/plain" ); |
273 | request.setChunkedTransferEncoding(true); |
274 | cs.sendRequest(request) << body; |
275 | HTTPResponse response; |
276 | std::string rbody; |
277 | cs.receiveResponse(response) >> rbody; |
278 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
279 | assertTrue (response.getContentType() == "text/plain" ); |
280 | assertTrue (response.getChunkedTransferEncoding()); |
281 | assertTrue (rbody == body); |
282 | |
283 | body.assign(1000, 'y'); |
284 | request.setKeepAlive(false); |
285 | cs.sendRequest(request) << body; |
286 | cs.receiveResponse(response) >> rbody; |
287 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
288 | assertTrue (response.getContentType() == "text/plain" ); |
289 | assertTrue (response.getChunkedTransferEncoding()); |
290 | assertTrue (!response.getKeepAlive()); |
291 | assertTrue (rbody == body); |
292 | } |
293 | |
294 | |
295 | void HTTPServerTest::testClosedRequestKeepAlive() |
296 | { |
297 | HTTPServer srv(new RequestHandlerFactory, 8010); |
298 | srv.start(); |
299 | |
300 | HTTPClientSession cs("127.0.0.1" , srv.socket().address().port()); |
301 | std::string body(5000, 'x'); |
302 | HTTPRequest request("POST" , "/echoBody" ); |
303 | request.setContentType("text/plain" ); |
304 | cs.sendRequest(request) << body; |
305 | HTTPResponse response; |
306 | std::string rbody; |
307 | cs.receiveResponse(response) >> rbody; |
308 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
309 | assertTrue (response.getContentType() == "text/plain" ); |
310 | assertTrue (!response.getChunkedTransferEncoding()); |
311 | assertTrue (!response.getKeepAlive()); |
312 | assertTrue (rbody == body); |
313 | } |
314 | |
315 | |
316 | void HTTPServerTest::testMaxKeepAlive() |
317 | { |
318 | ServerSocket svs(0); |
319 | HTTPServerParams* pParams = new HTTPServerParams; |
320 | pParams->setKeepAlive(true); |
321 | pParams->setMaxKeepAliveRequests(4); |
322 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
323 | srv.start(); |
324 | |
325 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
326 | cs.setKeepAlive(true); |
327 | HTTPRequest request("POST" , "/echoBody" , HTTPMessage::HTTP_1_1); |
328 | request.setContentType("text/plain" ); |
329 | request.setChunkedTransferEncoding(true); |
330 | std::string body(5000, 'x'); |
331 | for (int i = 0; i < 3; ++i) |
332 | { |
333 | cs.sendRequest(request) << body; |
334 | HTTPResponse response; |
335 | std::string rbody; |
336 | cs.receiveResponse(response) >> rbody; |
337 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
338 | assertTrue (response.getContentType() == "text/plain" ); |
339 | assertTrue (response.getChunkedTransferEncoding()); |
340 | assertTrue (response.getKeepAlive()); |
341 | assertTrue (rbody == body); |
342 | } |
343 | |
344 | { |
345 | cs.sendRequest(request) << body; |
346 | HTTPResponse response; |
347 | std::string rbody; |
348 | cs.receiveResponse(response) >> rbody; |
349 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
350 | assertTrue (response.getContentType() == "text/plain" ); |
351 | assertTrue (response.getChunkedTransferEncoding()); |
352 | assertTrue (!response.getKeepAlive()); |
353 | assertTrue (rbody == body); |
354 | } |
355 | |
356 | { |
357 | cs.setKeepAlive(false); |
358 | cs.sendRequest(request) << body; |
359 | HTTPResponse response; |
360 | std::string rbody; |
361 | cs.receiveResponse(response) >> rbody; |
362 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
363 | assertTrue (response.getContentType() == "text/plain" ); |
364 | assertTrue (response.getChunkedTransferEncoding()); |
365 | assertTrue (!response.getKeepAlive()); |
366 | assertTrue (rbody == body); |
367 | } |
368 | } |
369 | |
370 | |
371 | void HTTPServerTest::testKeepAliveTimeout() |
372 | { |
373 | ServerSocket svs(0); |
374 | HTTPServerParams* pParams = new HTTPServerParams; |
375 | pParams->setKeepAlive(true); |
376 | pParams->setMaxKeepAliveRequests(4); |
377 | pParams->setKeepAliveTimeout(Poco::Timespan(3, 0)); |
378 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
379 | srv.start(); |
380 | |
381 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
382 | cs.setKeepAlive(true); |
383 | cs.setKeepAliveTimeout(Poco::Timespan(2, 0)); |
384 | HTTPRequest request("POST" , "/echoBody" , HTTPMessage::HTTP_1_1); |
385 | request.setContentType("text/plain" ); |
386 | request.setChunkedTransferEncoding(true); |
387 | std::string body(5000, 'x'); |
388 | for (int i = 0; i < 3; ++i) |
389 | { |
390 | cs.sendRequest(request) << body; |
391 | HTTPResponse response; |
392 | std::string rbody; |
393 | cs.receiveResponse(response) >> rbody; |
394 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
395 | assertTrue (response.getContentType() == "text/plain" ); |
396 | assertTrue (response.getChunkedTransferEncoding()); |
397 | assertTrue (response.getKeepAlive()); |
398 | assertTrue (rbody == body); |
399 | } |
400 | |
401 | Poco::Thread::sleep(4000); |
402 | |
403 | { |
404 | cs.sendRequest(request) << body; |
405 | HTTPResponse response; |
406 | std::string rbody; |
407 | cs.receiveResponse(response) >> rbody; |
408 | assertTrue (response.getContentLength() == HTTPMessage::UNKNOWN_CONTENT_LENGTH); |
409 | assertTrue (response.getContentType() == "text/plain" ); |
410 | assertTrue (response.getChunkedTransferEncoding()); |
411 | assertTrue (response.getKeepAlive()); |
412 | assertTrue (rbody == body); |
413 | } |
414 | } |
415 | |
416 | |
417 | void HTTPServerTest::test100Continue() |
418 | { |
419 | ServerSocket svs(0); |
420 | HTTPServerParams* pParams = new HTTPServerParams; |
421 | pParams->setKeepAlive(false); |
422 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
423 | srv.start(); |
424 | |
425 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
426 | std::string body(5000, 'x'); |
427 | HTTPRequest request("POST" , "/echoBody" ); |
428 | request.setContentLength((int) body.length()); |
429 | request.setContentType("text/plain" ); |
430 | request.set("Expect" , "100-Continue" ); |
431 | cs.sendRequest(request) << body; |
432 | HTTPResponse response; |
433 | std::string rbody; |
434 | cs.receiveResponse(response) >> rbody; |
435 | assertTrue (response.getContentLength() == body.size()); |
436 | assertTrue (response.getContentType() == "text/plain" ); |
437 | assertTrue (rbody == body); |
438 | } |
439 | |
440 | |
441 | void HTTPServerTest::testRedirect() |
442 | { |
443 | ServerSocket svs(0); |
444 | HTTPServerParams* pParams = new HTTPServerParams; |
445 | pParams->setKeepAlive(false); |
446 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
447 | srv.start(); |
448 | |
449 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
450 | HTTPRequest request("GET" , "/redirect" ); |
451 | cs.sendRequest(request); |
452 | HTTPResponse response; |
453 | std::string rbody; |
454 | cs.receiveResponse(response) >> rbody; |
455 | assertTrue (response.getStatus() == HTTPResponse::HTTP_FOUND); |
456 | assertTrue (response.get("Location" ) == "http://www.appinf.com/" ); |
457 | assertTrue (rbody.empty()); |
458 | } |
459 | |
460 | |
461 | void HTTPServerTest::testAuth() |
462 | { |
463 | ServerSocket svs(0); |
464 | HTTPServerParams* pParams = new HTTPServerParams; |
465 | pParams->setKeepAlive(false); |
466 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
467 | srv.start(); |
468 | |
469 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
470 | HTTPRequest request("GET" , "/auth" ); |
471 | cs.sendRequest(request); |
472 | HTTPResponse response; |
473 | std::string rbody; |
474 | cs.receiveResponse(response) >> rbody; |
475 | assertTrue (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED); |
476 | assertTrue (response.get("WWW-Authenticate" ) == "Basic realm=\"/auth\"" ); |
477 | assertTrue (rbody.empty()); |
478 | } |
479 | |
480 | |
481 | void HTTPServerTest::testNotImpl() |
482 | { |
483 | ServerSocket svs(0); |
484 | HTTPServerParams* pParams = new HTTPServerParams; |
485 | pParams->setKeepAlive(false); |
486 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
487 | srv.start(); |
488 | |
489 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
490 | HTTPRequest request("GET" , "/notImpl" ); |
491 | cs.sendRequest(request); |
492 | HTTPResponse response; |
493 | std::string rbody; |
494 | cs.receiveResponse(response) >> rbody; |
495 | assertTrue (response.getStatus() == HTTPResponse::HTTP_NOT_IMPLEMENTED); |
496 | assertTrue (rbody.empty()); |
497 | } |
498 | |
499 | |
500 | void HTTPServerTest::testBuffer() |
501 | { |
502 | ServerSocket svs(0); |
503 | HTTPServerParams* pParams = new HTTPServerParams; |
504 | pParams->setKeepAlive(false); |
505 | HTTPServer srv(new RequestHandlerFactory, svs, pParams); |
506 | srv.start(); |
507 | |
508 | HTTPClientSession cs("127.0.0.1" , svs.address().port()); |
509 | HTTPRequest request("GET" , "/buffer" ); |
510 | cs.sendRequest(request); |
511 | HTTPResponse response; |
512 | std::string rbody; |
513 | cs.receiveResponse(response) >> rbody; |
514 | assertTrue (response.getStatus() == HTTPResponse::HTTP_OK); |
515 | assertTrue (rbody == "xxxxxxxxxx" ); |
516 | } |
517 | |
518 | |
519 | void HTTPServerTest::setUp() |
520 | { |
521 | } |
522 | |
523 | |
524 | void HTTPServerTest::tearDown() |
525 | { |
526 | } |
527 | |
528 | |
529 | CppUnit::Test* HTTPServerTest::suite() |
530 | { |
531 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPServerTest" ); |
532 | |
533 | CppUnit_addTest(pSuite, HTTPServerTest, testIdentityRequest); |
534 | CppUnit_addTest(pSuite, HTTPServerTest, testPutIdentityRequest); |
535 | CppUnit_addTest(pSuite, HTTPServerTest, testChunkedRequest); |
536 | CppUnit_addTest(pSuite, HTTPServerTest, testClosedRequest); |
537 | CppUnit_addTest(pSuite, HTTPServerTest, testIdentityRequestKeepAlive); |
538 | CppUnit_addTest(pSuite, HTTPServerTest, testChunkedRequestKeepAlive); |
539 | CppUnit_addTest(pSuite, HTTPServerTest, testClosedRequestKeepAlive); |
540 | CppUnit_addTest(pSuite, HTTPServerTest, testMaxKeepAlive); |
541 | CppUnit_addTest(pSuite, HTTPServerTest, testKeepAliveTimeout); |
542 | CppUnit_addTest(pSuite, HTTPServerTest, test100Continue); |
543 | CppUnit_addTest(pSuite, HTTPServerTest, testRedirect); |
544 | CppUnit_addTest(pSuite, HTTPServerTest, testAuth); |
545 | CppUnit_addTest(pSuite, HTTPServerTest, testNotImpl); |
546 | CppUnit_addTest(pSuite, HTTPServerTest, testBuffer); |
547 | |
548 | return pSuite; |
549 | } |
550 | |