7 #include <boost/algorithm/string/case_conv.hpp>
9 #include "HTTPClient.hxx"
10 #include "HTTPRequest.hxx"
12 #include <simgear/io/sg_netChat.hxx>
13 #include <simgear/misc/strutils.hxx>
14 #include <simgear/timing/timestamp.hxx>
20 using std::stringstream;
22 using namespace simgear;
24 const char* BODY1 = "The quick brown fox jumps over a lazy dog.";
26 const int body2Size = 8 * 1024;
27 char body2[body2Size];
29 #define COMPARE(a, b) \
31 cerr << "failed:" << #a << " != " << #b << endl; \
32 cerr << "\tgot:" << a << endl; \
38 cerr << "failed:" << #a << endl; \
42 class TestRequest : public HTTP::Request
48 TestRequest(const std::string& url) :
56 virtual void responseHeadersComplete()
60 virtual void responseComplete()
65 virtual void gotBodyData(const char* s, int n)
67 bodyData += string(s, n);
71 class TestServerChannel : public NetChat
84 setTerminator("\r\n");
87 virtual void collectIncomingData(const char* s, int n)
89 buffer += string(s, n);
92 virtual void foundTerminator(void)
94 if (state == STATE_IDLE) {
95 state = STATE_HEADERS;
96 string_list line = strutils::split(buffer, NULL, 3);
97 if (line.size() < 4) {
98 cerr << "malformed request:" << buffer << endl;
104 httpVersion = line[2];
106 requestHeaders.clear();
108 } else if (state == STATE_HEADERS) {
109 string s = strutils::simplify(buffer);
112 receivedRequestHeaders();
116 int colonPos = buffer.find(':');
118 cerr << "malformed HTTP response header:" << buffer << endl;
123 string key = strutils::simplify(buffer.substr(0, colonPos));
124 string lkey = boost::to_lower_copy(key);
125 string value = strutils::strip(buffer.substr(colonPos + 1));
126 requestHeaders[lkey] = value;
128 } else if (state == STATE_REQUEST_BODY) {
133 void receivedRequestHeaders()
136 if (path == "/test1") {
137 string contentStr(BODY1);
139 d << "HTTP1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
140 d << "Content-Length:" << contentStr.size() << "\r\n";
141 d << "\r\n"; // final CRLF to terminate the headers
143 push(d.str().c_str());
144 } else if (path == "/test2") {
146 d << "HTTP1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
147 d << "Content-Length:" << body2Size << "\r\n";
148 d << "\r\n"; // final CRLF to terminate the headers
149 push(d.str().c_str());
150 bufferSend(body2, body2Size);
151 cout << "sent body2" << endl;
153 sendErrorResponse(404);
157 void sendErrorResponse(int code)
159 cerr << "sending error " << code << " for " << path << endl;
160 stringstream headerData;
161 headerData << "HTTP1.1 " << code << " " << reasonForCode(code) << "\r\n";
162 headerData << "\r\n"; // final CRLF to terminate the headers
163 push(headerData.str().c_str());
166 string reasonForCode(int code)
169 case 200: return "OK";
170 case 404: return "not found";
171 default: return "unknown code";
181 std::map<string, string> requestHeaders;
184 class TestServer : public NetChannel
190 bind(NULL, 2000); // localhost, any port
194 virtual ~TestServer()
198 virtual bool writable (void) { return false ; }
200 virtual void handleAccept (void)
202 simgear::IPAddress addr ;
203 int handle = accept ( &addr ) ;
205 TestServerChannel* chan = new TestServerChannel();
206 chan->setHandle(handle);
210 void waitForComplete(TestRequest* tr)
212 SGTimeStamp start(SGTimeStamp::now());
213 while (start.elapsedMSec() < 1000) {
214 NetChannel::poll(10);
220 cerr << "timed out" << endl;
223 int main(int argc, char* argv[])
230 TestRequest* tr1 = new TestRequest("http://localhost:2000/test1?foo=bar");
231 COMPARE(tr1->scheme(), "http");
232 COMPARE(tr1->host(), "localhost:2000");
233 COMPARE(tr1->path(), "/test1");
237 TestRequest* tr = new TestRequest("http://localhost:2000/test1");
238 HTTP::Request_ptr own(tr);
242 COMPARE(tr->responseCode(), 200);
243 COMPARE(tr->contentLength(), strlen(BODY1));
244 COMPARE(tr->bodyData, string(BODY1));
247 // larger get request
248 for (int i=0; i<body2Size; ++i) {
249 body2[i] = (i << 4) | (i >> 2);
253 TestRequest* tr = new TestRequest("http://localhost:2000/test2");
254 HTTP::Request_ptr own(tr);
257 COMPARE(tr->responseCode(), 200);
258 COMPARE(tr->contentLength(), body2Size);
259 COMPARE(tr->bodyData, string(body2, body2Size));
264 TestRequest* tr = new TestRequest("http://localhost:2000/not-found");
265 HTTP::Request_ptr own(tr);
268 COMPARE(tr->responseCode(), 404);
269 COMPARE(tr->contentLength(), 0);
272 cout << "all tests passed ok" << endl;