const char* BODY1 = "The quick brown fox jumps over a lazy dog.";
-const int body2Size = 8 * 1024;
+const unsigned int body2Size = 8 * 1024;
char body2[body2Size];
#define COMPARE(a, b) \
{
public:
bool complete;
+ bool failed;
string bodyData;
TestRequest(const std::string& url) :
}
+ std::map<string, string> headers;
protected:
virtual void responseHeadersComplete()
{
complete = true;
}
+ virtual void failure()
+ {
+ failed = true;
+ }
+
virtual void gotBodyData(const char* s, int n)
{
bodyData += string(s, n);
}
+
+ virtual void responseHeader(const string& header, const string& value)
+ {
+ headers[header] = value;
+ }
};
class TestServerChannel : public NetChat
if (state == STATE_IDLE) {
state = STATE_HEADERS;
string_list line = strutils::split(buffer, NULL, 3);
- if (line.size() < 4) {
+ if (line.size() < 3) {
cerr << "malformed request:" << buffer << endl;
exit(-1);
}
method = line[0];
path = line[1];
httpVersion = line[2];
- userAgent = line[3];
requestHeaders.clear();
buffer.clear();
} else if (state == STATE_HEADERS) {
d << contentStr;
push(d.str().c_str());
} else if (path == "/test2") {
+ sendBody2();
+ } else if (path == "/testchunked") {
stringstream d;
d << "HTTP1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
- d << "Content-Length:" << body2Size << "\r\n";
- d << "\r\n"; // final CRLF to terminate the headers
+ d << "Transfer-Encoding:chunked\r\n";
+ d << "\r\n";
+ d << "8\r\n"; // first chunk
+ d << "ABCDEFGH\r\n";
+ d << "6\r\n"; // second chunk
+ d << "ABCDEF\r\n";
+ d << "10\r\n"; // third chunk
+ d << "ABCDSTUVABCDSTUV\r\n";
+ d << "0\r\n"; // start of trailer
+ d << "X-Foobar: wibble\r\n"; // trailer data
+ d << "\r\n";
push(d.str().c_str());
- bufferSend(body2, body2Size);
- cout << "sent body2" << endl;
+ } else if (path == "http://www.google.com/test2") {
+ // proxy test
+ if (requestHeaders["host"] != "www.google.com") {
+ sendErrorResponse(400);
+ }
+
+ if (requestHeaders["proxy-authorization"] != string()) {
+ sendErrorResponse(401); // shouldn't supply auth
+ }
+
+ sendBody2();
+ } else if (path == "http://www.google.com/test3") {
+ // proxy test
+ if (requestHeaders["host"] != "www.google.com") {
+ sendErrorResponse(400);
+ }
+
+ if (requestHeaders["proxy-authorization"] != "ABCDEF") {
+ sendErrorResponse(401); // forbidden
+ }
+
+ sendBody2();
} else {
sendErrorResponse(404);
}
}
+ void sendBody2()
+ {
+ stringstream d;
+ d << "HTTP1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
+ d << "Content-Length:" << body2Size << "\r\n";
+ d << "\r\n"; // final CRLF to terminate the headers
+ push(d.str().c_str());
+ bufferSend(body2, body2Size);
+ }
+
void sendErrorResponse(int code)
{
cerr << "sending error " << code << " for " << path << endl;
string method;
string path;
string httpVersion;
- string userAgent;
std::map<string, string> requestHeaders;
};
{
simgear::IPAddress addr ;
int handle = accept ( &addr ) ;
-
+ cout << "did accept from " << addr.getHost() << ":" << addr.getPort() << endl;
TestServerChannel* chan = new TestServerChannel();
chan->setHandle(handle);
}
cerr << "timed out" << endl;
}
+void waitForFailed(TestRequest* tr)
+{
+ SGTimeStamp start(SGTimeStamp::now());
+ while (start.elapsedMSec() < 1000) {
+ NetChannel::poll(10);
+ if (tr->failed) {
+ return;
+ }
+ }
+
+ cerr << "timed out waiting for failure" << endl;
+}
+
int main(int argc, char* argv[])
{
TestServer s;
HTTP::Client cl;
// test URL parsing
- TestRequest* tr1 = new TestRequest("http://localhost:2000/test1?foo=bar");
+ TestRequest* tr1 = new TestRequest("http://localhost.woo.zar:2000/test1?foo=bar");
COMPARE(tr1->scheme(), "http");
- COMPARE(tr1->host(), "localhost:2000");
+ COMPARE(tr1->hostAndPort(), "localhost.woo.zar:2000");
+ COMPARE(tr1->host(), "localhost.woo.zar");
+ COMPARE(tr1->port(), 2000);
COMPARE(tr1->path(), "/test1");
+ TestRequest* tr2 = new TestRequest("http://192.168.1.1/test1/dir/thing/file.png");
+ COMPARE(tr2->scheme(), "http");
+ COMPARE(tr2->hostAndPort(), "192.168.1.1");
+ COMPARE(tr2->host(), "192.168.1.1");
+ COMPARE(tr2->port(), 80);
+ COMPARE(tr2->path(), "/test1/dir/thing/file.png");
+
// basic get request
{
TestRequest* tr = new TestRequest("http://localhost:2000/test1");
waitForComplete(tr);
COMPARE(tr->responseCode(), 200);
- COMPARE(tr->contentLength(), strlen(BODY1));
+ COMPARE(tr->responseReason(), string("OK"));
+ COMPARE(tr->responseLength(), strlen(BODY1));
+ COMPARE(tr->responseBytesReceived(), strlen(BODY1));
COMPARE(tr->bodyData, string(BODY1));
}
// larger get request
- for (int i=0; i<body2Size; ++i) {
+ for (unsigned int i=0; i<body2Size; ++i) {
body2[i] = (i << 4) | (i >> 2);
}
cl.makeRequest(tr);
waitForComplete(tr);
COMPARE(tr->responseCode(), 200);
- COMPARE(tr->contentLength(), body2Size);
+ COMPARE(tr->responseBytesReceived(), body2Size);
COMPARE(tr->bodyData, string(body2, body2Size));
}
+ {
+ TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
+ HTTP::Request_ptr own(tr);
+ cl.makeRequest(tr);
+
+ waitForComplete(tr);
+ COMPARE(tr->responseCode(), 200);
+ COMPARE(tr->responseReason(), string("OK"));
+ COMPARE(tr->responseBytesReceived(), 30);
+ COMPARE(tr->bodyData, "ABCDEFGHABCDEFABCDSTUVABCDSTUV");
+ // check trailers made it too
+ COMPARE(tr->headers["x-foobar"], string("wibble"));
+ }
+
// test 404
{
TestRequest* tr = new TestRequest("http://localhost:2000/not-found");
cl.makeRequest(tr);
waitForComplete(tr);
COMPARE(tr->responseCode(), 404);
- COMPARE(tr->contentLength(), 0);
+ COMPARE(tr->responseReason(), string("not found"));
+ COMPARE(tr->responseLength(), 0);
+ }
+
+// test connectToHost failure
+/*
+ {
+ TestRequest* tr = new TestRequest("http://not.found/something");
+ HTTP::Request_ptr own(tr);
+ cl.makeRequest(tr);
+ waitForFailed(tr);
+ COMPARE(tr->responseCode(), -1);
+ }
+ */
+// test proxy
+ {
+ cl.setProxy("localhost", 2000);
+ TestRequest* tr = new TestRequest("http://www.google.com/test2");
+ HTTP::Request_ptr own(tr);
+ cl.makeRequest(tr);
+ waitForComplete(tr);
+ COMPARE(tr->responseCode(), 200);
+ COMPARE(tr->responseLength(), body2Size);
+ COMPARE(tr->bodyData, string(body2, body2Size));
+ }
+
+ {
+ cl.setProxy("localhost", 2000, "ABCDEF");
+ TestRequest* tr = new TestRequest("http://www.google.com/test3");
+ HTTP::Request_ptr own(tr);
+ cl.makeRequest(tr);
+ waitForComplete(tr);
+ COMPARE(tr->responseCode(), 200);
+ COMPARE(tr->responseBytesReceived(), body2Size);
+ COMPARE(tr->bodyData, string(body2, body2Size));
}
cout << "all tests passed ok" << endl;