]> git.mxchange.org Git - simgear.git/blobdiff - simgear/io/test_HTTP.cxx
Fixes to Random Buildings:
[simgear.git] / simgear / io / test_HTTP.cxx
index 048cbb41909186e66e00a5c5c1bfcf19f1e89be9..fc2fe869bf91e7da3909a4af6fd8efbba18c43d3 100644 (file)
@@ -12,7 +12,6 @@
 #include <simgear/io/sg_netChat.hxx>
 #include <simgear/misc/strutils.hxx>
 #include <simgear/timing/timestamp.hxx>
-#include <simgear/misc/sg_sleep.hxx>
 
 using std::cout;
 using std::cerr;
@@ -47,8 +46,8 @@ public:
     bool failed;
     string bodyData;
     
-    TestRequest(const std::string& url) : 
-        HTTP::Request(url),
+    TestRequest(const std::string& url, const std::string method = "GET") : 
+        HTTP::Request(url, method),
         complete(false)
     {
     }
@@ -134,6 +133,13 @@ public:
             
             method = line[0];
             path = line[1];
+            
+            int queryPos = path.find('?'); 
+            if (queryPos != string::npos) {
+                parseArgs(path.substr(queryPos + 1));
+                path = path.substr(0, queryPos);
+            }
+            
             httpVersion = line[2];
             requestHeaders.clear();
             buffer.clear();
@@ -157,10 +163,28 @@ public:
             requestHeaders[key] = value;
             buffer.clear();
         } else if (state == STATE_REQUEST_BODY) {
-            
+            cerr << "done getting requst body";
+            receivedBody();
+            setTerminator("\r\n");
         }
     }  
     
+    void parseArgs(const string& argData)
+    {
+        string_list argv = strutils::split(argData, "&");
+        for (unsigned int a=0; a<argv.size(); ++a) {
+            int eqPos = argv[a].find('=');
+            if (eqPos < 0) {
+                cerr << "malformed HTTP argument:" << argv[a] << endl;
+                continue;
+            }
+
+            string key = argv[a].substr(0, eqPos);
+            string value = argv[a].substr(eqPos + 1);
+            args[key] = value;
+        }
+    }
+    
     void receivedRequestHeaders()
     {
         state = STATE_IDLE;
@@ -173,6 +197,14 @@ public:
             d << "\r\n"; // final CRLF to terminate the headers
             d << contentStr;
             push(d.str().c_str());
+        } else if (path == "/test_zero_length_content") {
+            string contentStr;
+            stringstream d;
+            d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
+            d << "Content-Length:" << contentStr.size() << "\r\n";
+            d << "\r\n"; // final CRLF to terminate the headers
+            d << contentStr;
+            push(d.str().c_str());
         } else if (path == "/test_headers") {
             COMPARE(requestHeaders["X-Foo"], string("Bar"));
             COMPARE(requestHeaders["X-AnotherHeader"], string("A longer value"));
@@ -240,8 +272,53 @@ public:
             d << contentStr;
             push(d.str().c_str());
             closeWhenDone();
+        } else if (path == "/test_args") {
+            if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
+                sendErrorResponse(400, true, "bad arguments");
+                return;
+            }
+
+            string contentStr(BODY1);
+            stringstream d;
+            d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
+            d << "Content-Length:" << contentStr.size() << "\r\n";
+            d << "\r\n"; // final CRLF to terminate the headers
+            d << contentStr;
+            push(d.str().c_str());
+        } else if (path == "/test_post") {
+            if (requestHeaders["Content-Type"] != "application/x-www-form-urlencoded") {
+                cerr << "bad content type: '" << requestHeaders["Content-Type"] << "'" << endl;
+                 sendErrorResponse(400, true, "bad content type");
+                 return;
+            }
+            
+            requestContentLength = strutils::to_int(requestHeaders["Content-Length"]);
+            setByteCount(requestContentLength);
+            state = STATE_REQUEST_BODY;
         } else {
-            sendErrorResponse(404, true, "");
+            sendErrorResponse(404, false, "");
+        }
+    }
+    
+    void receivedBody()
+    {
+        state = STATE_IDLE;
+        if (method == "POST") {
+            parseArgs(buffer);
+        }
+        
+        if (path == "/test_post") {
+            if ((args["foo"] != "abc") || (args["bar"] != "1234") || (args["username"] != "johndoe")) {
+                sendErrorResponse(400, true, "bad arguments");
+                return;
+            }
+            
+            stringstream d;
+            d << "HTTP/1.1 " << 204 << " " << reasonForCode(204) << "\r\n";
+            d << "\r\n"; // final CRLF to terminate the headers
+            push(d.str().c_str());
+            
+            cerr << "sent 204 response ok" << endl;
         }
     }
     
@@ -274,6 +351,7 @@ public:
     {
         switch (code) {
             case 200: return "OK";
+            case 204: return "no content";
             case 404: return "not found";
             default: return "unknown code";
         }
@@ -285,6 +363,8 @@ public:
     string path;
     string httpVersion;
     std::map<string, string> requestHeaders;
+    std::map<string, string> args;
+    int requestContentLength;
 };
 
 class TestServer : public NetChannel
@@ -321,7 +401,7 @@ void waitForComplete(HTTP::Client* cl, TestRequest* tr)
         if (tr->complete) {
             return;
         }
-        sleepForMSec(1);
+        SGTimeStamp::sleepForMSec(1);
     }
     
     cerr << "timed out" << endl;
@@ -335,7 +415,7 @@ void waitForFailed(HTTP::Client* cl, TestRequest* tr)
         if (tr->failed) {
             return;
         }
-        sleepForMSec(1);
+        SGTimeStamp::sleepForMSec(1);
     }
     
     cerr << "timed out waiting for failure" << endl;
@@ -375,7 +455,17 @@ int main(int argc, char* argv[])
         COMPARE(tr->responseBytesReceived(), strlen(BODY1));
         COMPARE(tr->bodyData, string(BODY1));
     }
-
+    
+    {
+        TestRequest* tr = new TestRequest("http://localhost:2000/test_args?foo=abc&bar=1234&username=johndoe");
+        HTTP::Request_ptr own(tr);
+        cl.makeRequest(tr);
+        waitForComplete(&cl, tr);
+        COMPARE(tr->responseCode(), 200);
+    }
+    
+    cerr << "done args" << endl;
+    
     {
         TestRequest* tr = new TestRequest("http://localhost:2000/test_headers");
         HTTP::Request_ptr own(tr);
@@ -406,6 +496,7 @@ int main(int argc, char* argv[])
         COMPARE(tr->bodyData, string(body2, body2Size));
     }
     
+    cerr << "testing chunked" << endl;
     {
         TestRequest* tr = new TestRequest("http://localhost:2000/testchunked");
         HTTP::Request_ptr own(tr);
@@ -431,6 +522,16 @@ int main(int argc, char* argv[])
         COMPARE(tr->responseLength(), 0);
     }
 
+    cout << "done 404 test" << endl;
+
+    {
+        TestRequest* tr = new TestRequest("http://localhost:2000/test_args?foo=abc&bar=1234&username=johndoe");
+        HTTP::Request_ptr own(tr);
+        cl.makeRequest(tr);
+        waitForComplete(&cl, tr);
+        COMPARE(tr->responseCode(), 200);
+    }
+
     cout << "done1" << endl;
 // test HTTP/1.0
     {
@@ -537,6 +638,29 @@ int main(int argc, char* argv[])
         COMPARE(tr3->bodyData, string(BODY1));
     }
     
+// POST
+    {
+        cout << "POST" << endl;
+        TestRequest* tr = new TestRequest("http://localhost:2000/test_post?foo=abc&bar=1234&username=johndoe", "POST");
+        HTTP::Request_ptr own(tr);
+        cl.makeRequest(tr);
+        waitForComplete(&cl, tr);
+        COMPARE(tr->responseCode(), 204);
+    }
+    
+    // test_zero_length_content
+    {
+        cout << "zero-length-content-response" << endl;
+        TestRequest* tr = new TestRequest("http://localhost:2000/test_zero_length_content");
+        HTTP::Request_ptr own(tr);
+        cl.makeRequest(tr);
+        waitForComplete(&cl, tr);
+        COMPARE(tr->responseCode(), 200);
+        COMPARE(tr->bodyData, string());
+        COMPARE(tr->responseBytesReceived(), 0);
+    }
+    
+    
     cout << "all tests passed ok" << endl;
     return EXIT_SUCCESS;
 }