1 #ifndef SIMGEAR_IO_TEST_HTTP_HXX
2 #define SIMGEAR_IO_TEST_HTTP_HXX
6 #include <simgear/io/sg_netChat.hxx>
7 #include <simgear/misc/strutils.hxx>
12 class TestServerChannel : public NetChat
26 setTerminator("\r\n");
30 virtual void collectIncomingData(const char* s, int n)
32 buffer += std::string(s, n);
35 virtual void foundTerminator(void)
37 if (state == STATE_IDLE) {
38 state = STATE_HEADERS;
39 string_list line = strutils::split(buffer, NULL, 3);
40 if (line.size() < 3) {
41 std::cerr << "malformed request:" << buffer << std::endl;
48 std::string::size_type queryPos = path.find('?');
49 if (queryPos != std::string::npos) {
50 parseArgs(path.substr(queryPos + 1));
51 path = path.substr(0, queryPos);
54 httpVersion = line[2];
55 requestHeaders.clear();
57 } else if (state == STATE_HEADERS) {
58 std::string s = strutils::simplify(buffer);
61 receivedRequestHeaders();
65 std::string::size_type colonPos = buffer.find(':');
66 if (colonPos == std::string::npos) {
67 std::cerr << "test malformed HTTP response header:" << buffer << std::endl;
72 std::string key = strutils::simplify(buffer.substr(0, colonPos));
73 std::string value = strutils::strip(buffer.substr(colonPos + 1));
74 requestHeaders[key] = value;
76 } else if (state == STATE_REQUEST_BODY) {
78 setTerminator("\r\n");
79 } else if (state == STATE_CLOSING) {
84 void parseArgs(const std::string& argData)
86 string_list argv = strutils::split(argData, "&");
87 for (unsigned int a=0; a<argv.size(); ++a) {
88 std::string::size_type eqPos = argv[a].find('=');
89 if (eqPos == std::string::npos) {
90 std::cerr << "malformed HTTP argument:" << argv[a] << std::endl;
94 std::string key = argv[a].substr(0, eqPos);
95 std::string value = argv[a].substr(eqPos + 1);
100 void receivedRequestHeaders()
103 processRequestHeaders();
106 virtual void processRequestHeaders()
108 sendErrorResponse(404, false, "");
111 void closeAfterSending()
113 state = STATE_CLOSING;
120 if (method == "POST") {
124 processRequestBody();
129 virtual void processRequestBody()
131 sendErrorResponse(404, false, "");
134 void sendErrorResponse(int code, bool close, std::string content)
136 std::cerr << "sending error " << code << " for " << path << std::endl;
137 std::cerr << "\tcontent:" << content << std::endl;
139 std::stringstream headerData;
140 headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
141 headerData << "Content-Length:" << content.size() << "\r\n";
142 headerData << "\r\n"; // final CRLF to terminate the headers
143 push(headerData.str().c_str());
144 push(content.c_str());
151 std::string reasonForCode(int code)
154 case 200: return "OK";
155 case 201: return "Created";
156 case 204: return "no content";
157 case 404: return "not found";
158 case 407: return "proxy authentication required";
159 default: return "unknown code";
167 std::string httpVersion;
168 std::map<std::string, std::string> requestHeaders;
169 std::map<std::string, std::string> args;
170 int requestContentLength;
174 class TestServer : public NetChannel
176 simgear::NetChannelPoller _poller;
180 Socket::initSockets();
183 bind(NULL, 2000); // localhost, any port
186 _poller.addChannel(this);
189 virtual ~TestServer()
193 virtual bool writable (void) { return false ; }
195 virtual void handleAccept (void)
197 simgear::IPAddress addr ;
198 int handle = accept ( &addr ) ;
199 TestServerChannel* chan = new T();
200 chan->setHandle(handle);
202 _poller.addChannel(chan);
211 } // of namespace simgear
213 #endif // of SIMGEAR_IO_TEST_HTTP_HXX