1 /*****************************************************************
2 |
3 | HTTP Server Test Program 1
4 |
5 | (c) 2001-2006 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8 ****************************************************************/
9
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #include "Neptune.h"
14 #include "NptDebug.h"
15
16 #if defined(WIN32) && defined(_DEBUG)
17 #include <crtdbg.h>
18 #endif
19
20 bool KillRequest = false;
21
22 /*----------------------------------------------------------------------
23 | KillHandler
24 +---------------------------------------------------------------------*/
25 class KillHandler : public NPT_HttpRequestHandler
26 {
27 public:
SetupResponse(NPT_HttpRequest &,const NPT_HttpRequestContext &,NPT_HttpResponse & response)28 NPT_Result SetupResponse(NPT_HttpRequest& /*request*/,
29 const NPT_HttpRequestContext& /*context*/,
30 NPT_HttpResponse& response) {
31 NPT_HttpEntity* entity = response.GetEntity();
32 entity->SetContentType("text/html");
33 entity->SetInputStream("<html><body>Bye Bye!</body></html>");
34 KillRequest = true;
35
36 return NPT_SUCCESS;
37 }
38 };
39
40 /*----------------------------------------------------------------------
41 | TestHandler1
42 +---------------------------------------------------------------------*/
43 class TestHandler1 : public NPT_HttpRequestHandler
44 {
45 public:
TestHandler1(bool chunked=false)46 TestHandler1(bool chunked = false) : m_Chunked(chunked) {}
SetupResponse(NPT_HttpRequest & request,const NPT_HttpRequestContext & context,NPT_HttpResponse & response)47 NPT_Result SetupResponse(NPT_HttpRequest& request,
48 const NPT_HttpRequestContext& context,
49 NPT_HttpResponse& response) {
50 NPT_String msg = "<HTML>";
51 msg += "PATH=";
52 msg += request.GetUrl().GetPath();
53 msg += "<P><B>Local Address:</B> ";
54 msg += context.GetLocalAddress().ToString();
55 msg += "<P>";
56 msg += "<B>Remote Address:</B> ";
57 msg += context.GetRemoteAddress().ToString();
58 msg += "<P><UL>";
59 if (request.GetUrl().HasQuery()) {
60 NPT_UrlQuery query(request.GetUrl().GetQuery());
61 for (NPT_List<NPT_UrlQuery::Field>::Iterator it = query.GetFields().GetFirstItem();
62 it;
63 ++it) {
64 NPT_UrlQuery::Field& field = *it;
65 msg += "<LI>";
66 msg += field.m_Name;
67 msg += " = ";
68 msg += field.m_Value;
69 msg += " </LI>";
70
71 // check for a 'delay' field
72 if (field.m_Name == "delay") {
73 NPT_UInt32 delay = 0;
74 field.m_Value.ToInteger(delay);
75 NPT_Debug("DELAY: %d seconds\n", delay);
76 NPT_System::Sleep(NPT_TimeInterval((float)delay));
77 }
78 }
79 }
80 msg += "</UL></HTML>";
81
82
83 if (request.GetMethod() == NPT_HTTP_METHOD_POST) {
84 NPT_DataBuffer request_body;
85 request.GetEntity()->Load(request_body);
86 NPT_Debug("REQUEST: body = %d bytes\n", request_body.GetDataSize());
87 NPT_Debug("REQUEST: content type = %s\n", request.GetEntity()->GetContentType().GetChars());
88 if (request.GetEntity()->GetContentType().StartsWith("text") ||
89 request.GetEntity()->GetContentType() == "application/x-www-form-urlencoded") {
90 NPT_String body_string;
91 body_string.Assign((char*)request_body.GetData(), request_body.GetDataSize());
92 NPT_Debug("%s", body_string.GetChars());
93 }
94 }
95
96 NPT_HttpEntity* entity = response.GetEntity();
97 entity->SetContentType("text/html");
98 entity->SetInputStream(msg);
99
100 if (m_Chunked) {
101 entity->SetTransferEncoding(NPT_HTTP_TRANSFER_ENCODING_CHUNKED);
102 entity->SetContentLength(0);
103 }
104
105 return NPT_SUCCESS;
106 }
107
108 bool m_Chunked;
109 };
110
111 /*----------------------------------------------------------------------
112 | TestHandler2
113 +---------------------------------------------------------------------*/
114 class TestHandler2 : public NPT_HttpRequestHandler
115 {
116 public:
SetupResponse(NPT_HttpRequest &,const NPT_HttpRequestContext &,NPT_HttpResponse & response)117 NPT_Result SetupResponse(NPT_HttpRequest& /*request*/,
118 const NPT_HttpRequestContext& /*context*/,
119 NPT_HttpResponse& response) {
120 NPT_HttpEntity* entity = response.GetEntity();
121 entity->SetContentType("text/html");
122 return NPT_SUCCESS;
123 }
124
SendResponseBody(const NPT_HttpRequestContext &,NPT_HttpResponse &,NPT_OutputStream & output)125 NPT_Result SendResponseBody(const NPT_HttpRequestContext& /*context*/,
126 NPT_HttpResponse& /*response*/,
127 NPT_OutputStream& output) {
128 output.WriteString("<html><body>\r\n");
129 for (unsigned int i=0; i<30; i++) {
130 output.WriteString("Line ");
131 output.WriteString(NPT_String::FromInteger(i).GetChars());
132 output.WriteString("\r\n");
133 output.Flush();
134 NPT_System::Sleep(NPT_TimeInterval(0.2f));
135 }
136 output.WriteString("</body></html>\r\n");
137 return NPT_SUCCESS;
138 }
139 };
140
141 /*----------------------------------------------------------------------
142 | ChunkedHandler
143 +---------------------------------------------------------------------*/
144 class ChunkedHandler : public NPT_HttpRequestHandler
145 {
146 public:
SetupResponse(NPT_HttpRequest &,const NPT_HttpRequestContext &,NPT_HttpResponse & response)147 NPT_Result SetupResponse(NPT_HttpRequest& /*request*/,
148 const NPT_HttpRequestContext& /*context*/,
149 NPT_HttpResponse& response) {
150 NPT_HttpEntity* entity = response.GetEntity();
151 entity->SetContentType("text/html");
152 entity->SetTransferEncoding("chunked");
153 response.SetProtocol(NPT_HTTP_PROTOCOL_1_1);
154 return NPT_SUCCESS;
155 }
156
SendResponseBody(const NPT_HttpRequestContext &,NPT_HttpResponse &,NPT_OutputStream & output)157 NPT_Result SendResponseBody(const NPT_HttpRequestContext& /*context*/,
158 NPT_HttpResponse& /*response*/,
159 NPT_OutputStream& output) {
160 NPT_HttpChunkedOutputStream chunker(output);
161 chunker.WriteString("<html><body>\r\n");
162 for (unsigned int i=0; i<30; i++) {
163 NPT_String line = "Line ";
164 line += NPT_String::FromInteger(i).GetChars();
165 chunker.WriteString(line.GetChars());
166 chunker.Flush();
167 NPT_System::Sleep(NPT_TimeInterval(0.2f));
168 }
169 chunker.WriteString("</body></html>\r\n");
170 return NPT_SUCCESS;
171 }
172 };
173
174 /*----------------------------------------------------------------------
175 | TestHttp
176 +---------------------------------------------------------------------*/
177 static NPT_Result
TestHttp()178 TestHttp()
179 {
180 NPT_HttpServer server(1234);
181 NPT_InputStreamReference input;
182 NPT_OutputStreamReference output;
183 NPT_HttpRequestContext context;
184
185 NPT_HttpStaticRequestHandler* static_handler = new NPT_HttpStaticRequestHandler(
186 "<html><body>"
187 "<h1>Neptune HTTP Server Test 1</h1>"
188 "<a href='/files-autodir'>List files working directory (autodir)</a><br>"
189 "<a href='/files'>List files working directory (no autodir)</a><br>"
190 "<a href='/test1'>Test 1</a><br>"
191 "<a href='/test2'>Test 2</a><br>"
192 "<a href='/chunked1'>Chunked 1</a><br>"
193 "<a href='/chunked2'>Chunked 2</a><br>"
194 "<a href='/kill'>Kill Test Server</a><br>"
195 "</body></html>",
196 "text/html");
197 server.AddRequestHandler(static_handler, "/", false);
198
199 KillHandler* kill_handler = new KillHandler();
200 server.AddRequestHandler(kill_handler, "/kill", false);
201
202 TestHandler1* test_handler1 = new TestHandler1();
203 server.AddRequestHandler(test_handler1, "/test1", false);
204
205 TestHandler2* test_handler2 = new TestHandler2();
206 server.AddRequestHandler(test_handler2, "/test2", false);
207
208 ChunkedHandler* chunked_handler1 = new ChunkedHandler();
209 server.AddRequestHandler(chunked_handler1, "/chunked1", false);
210
211 TestHandler1* chunked_handler2 = new TestHandler1(true);
212 server.AddRequestHandler(chunked_handler2, "/chunked2", false);
213
214 NPT_String cwd;
215 NPT_File::GetWorkingDir(cwd);
216 NPT_HttpFileRequestHandler* file_handler_autodir = new NPT_HttpFileRequestHandler("/files-autodir", cwd.GetChars(), true);
217 server.AddRequestHandler(file_handler_autodir, "/files-autodir", true);
218 NPT_HttpFileRequestHandler* file_handler_noautodir = new NPT_HttpFileRequestHandler("/files", cwd.GetChars(), false);
219 server.AddRequestHandler(file_handler_noautodir, "/files", true);
220
221 do {
222 NPT_Console::Output("Test HTTP server waiting for connection on port 1234...\n");
223 NPT_Result result = server.WaitForNewClient(input,
224 output,
225 &context);
226 NPT_Console::OutputF("WaitForNewClient returned %d (%s)\n", result, NPT_ResultText(result));
227 if (NPT_FAILED(result)) return result;
228
229 result = server.RespondToClient(input, output, context);
230 NPT_Console::OutputF("RespondToClient returned %d (%s)\n", result, NPT_ResultText(result));
231
232 input = NULL;
233 output = NULL;
234 } while (!KillRequest);
235
236 NPT_Console::OutputF("Killing Server\n");
237
238 delete static_handler;
239 delete test_handler1;
240 delete test_handler2;
241 delete file_handler_autodir;
242 delete file_handler_noautodir;
243
244 return NPT_SUCCESS;
245 }
246
247 /*----------------------------------------------------------------------
248 | main
249 +---------------------------------------------------------------------*/
250 int
main(int,char **)251 main(int /*argc*/, char** /*argv*/)
252 {
253 // setup debugging
254 #if defined(WIN32) && defined(_DEBUG)
255 int flags = _crtDbgFlag |
256 _CRTDBG_ALLOC_MEM_DF |
257 _CRTDBG_DELAY_FREE_MEM_DF |
258 _CRTDBG_CHECK_ALWAYS_DF;
259
260 _CrtSetDbgFlag(flags);
261 //AllocConsole();
262 //freopen("CONOUT$", "w", stdout);
263 #endif
264
265 TestHttp();
266
267 #if defined(WIN32) && defined(_DEBUG)
268 _CrtDumpMemoryLeaks();
269 #endif
270
271 return 0;
272 }
273