1 #ifndef SIMGEAR_IO_TEST_HTTP_HXX
2 #define SIMGEAR_IO_TEST_HTTP_HXX
7 #include <simgear/io/sg_netChat.hxx>
8 #include <simgear/misc/strutils.hxx>
13 class TestServerChannel : public NetChat
27 setTerminator("\r\n");
31 virtual ~TestServerChannel()
33 std::cerr << "dtor test server channel" << std::endl;
36 virtual void collectIncomingData(const char* s, int n)
38 buffer += std::string(s, n);
41 virtual void foundTerminator(void)
43 if (state == STATE_IDLE) {
44 state = STATE_HEADERS;
45 string_list line = strutils::split(buffer, NULL, 3);
46 if (line.size() < 3) {
47 std::cerr << "malformed request:" << buffer << std::endl;
54 std::string::size_type queryPos = path.find('?');
55 if (queryPos != std::string::npos) {
56 parseArgs(path.substr(queryPos + 1));
57 path = path.substr(0, queryPos);
60 httpVersion = line[2];
61 requestHeaders.clear();
63 } else if (state == STATE_HEADERS) {
64 std::string s = strutils::simplify(buffer);
67 receivedRequestHeaders();
71 std::string::size_type colonPos = buffer.find(':');
72 if (colonPos == std::string::npos) {
73 std::cerr << "test malformed HTTP response header:" << buffer << std::endl;
78 std::string key = strutils::simplify(buffer.substr(0, colonPos));
79 std::string value = strutils::strip(buffer.substr(colonPos + 1));
80 requestHeaders[key] = value;
82 } else if (state == STATE_REQUEST_BODY) {
84 setTerminator("\r\n");
85 } else if (state == STATE_CLOSING) {
90 void parseArgs(const std::string& argData)
92 string_list argv = strutils::split(argData, "&");
93 for (unsigned int a=0; a<argv.size(); ++a) {
94 std::string::size_type eqPos = argv[a].find('=');
95 if (eqPos == std::string::npos) {
96 std::cerr << "malformed HTTP argument:" << argv[a] << std::endl;
100 std::string key = argv[a].substr(0, eqPos);
101 std::string value = argv[a].substr(eqPos + 1);
106 void receivedRequestHeaders()
109 processRequestHeaders();
112 virtual void processRequestHeaders()
114 sendErrorResponse(404, false, "");
117 void closeAfterSending()
119 state = STATE_CLOSING;
126 if (method == "POST") {
130 processRequestBody();
135 virtual void processRequestBody()
137 sendErrorResponse(404, false, "");
140 void sendErrorResponse(int code, bool close, std::string content)
142 std::cerr << "sending error " << code << " for " << path << std::endl;
143 std::cerr << "\tcontent:" << content << std::endl;
145 std::stringstream headerData;
146 headerData << "HTTP/1.1 " << code << " " << reasonForCode(code) << "\r\n";
147 headerData << "Content-Length:" << content.size() << "\r\n";
148 headerData << "\r\n"; // final CRLF to terminate the headers
149 push(headerData.str().c_str());
150 push(content.c_str());
157 std::string reasonForCode(int code)
160 case 200: return "OK";
161 case 201: return "Created";
162 case 204: return "no content";
163 case 404: return "not found";
164 case 407: return "proxy authentication required";
165 default: return "unknown code";
169 virtual void handleClose (void)
171 std::cerr << "channel close" << std::endl;
172 NetBufferChannel::handleClose();
180 std::string httpVersion;
181 std::map<std::string, std::string> requestHeaders;
182 std::map<std::string, std::string> args;
183 int requestContentLength;
189 bool operator()(simgear::NetChannel* chan) const
191 return chan->isClosed();
196 class TestServer : public NetChannel
198 simgear::NetChannelPoller _poller;
199 std::vector<T*> _channels;
203 Socket::initSockets();
207 bind(NULL, 2000); // localhost, any port
210 _poller.addChannel(this);
213 virtual ~TestServer()
217 virtual bool writable (void) { return false ; }
219 virtual void handleAccept (void)
221 simgear::IPAddress addr ;
222 int handle = accept ( &addr ) ;
224 chan->setHandle(handle);
226 _channels.push_back(chan);
227 _poller.addChannel(chan);
234 typename std::vector<T*>::iterator it;
235 it = std::remove_if(_channels.begin(), _channels.end(), EraseIfClosed());
237 for (typename std::vector<T*>::iterator it2 = it; it2 != _channels.end(); ++it2) {
238 _poller.removeChannel(*it2);
242 _channels.erase(it, _channels.end());
248 return _channels.size();
253 typename std::vector<T*>::iterator it;
254 for (it = _channels.begin(); it != _channels.end(); ++it) {
255 _poller.removeChannel(*it);
263 } // of namespace simgear
265 #endif // of SIMGEAR_IO_TEST_HTTP_HXX