]> git.mxchange.org Git - simgear.git/commitdiff
Further HTTP improvements, wget-alike test program to check it all behaves!
authorJames Turner <zakalawe@mac.com>
Mon, 1 Aug 2011 08:03:12 +0000 (09:03 +0100)
committerJames Turner <zakalawe@mac.com>
Mon, 1 Aug 2011 08:03:12 +0000 (09:03 +0100)
simgear/io/CMakeLists.txt
simgear/io/HTTPRequest.cxx
simgear/io/HTTPRequest.hxx
simgear/io/httpget.cxx [new file with mode: 0644]
simgear/io/iochannel.hxx
simgear/io/sg_file.cxx
simgear/io/sg_file.hxx
simgear/io/sg_socket.cxx
simgear/io/sg_socket_udp.cxx
simgear/io/sg_socket_udp.hxx
simgear/io/test_HTTP.cxx

index 136b6e22fc34de3b5678371b6c7a1247d820ae85..a2638e1bee9ef61a42051cef156a9f8e620fbc6f 100644 (file)
@@ -44,4 +44,10 @@ target_link_libraries(test_http
     sgio sgstructure sgtiming sgmisc sgdebug
     ${RT_LIBRARY})
 
-add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http)
\ No newline at end of file
+add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http)
+
+add_executable(httpget httpget.cxx)
+target_link_libraries(httpget 
+    sgio sgstructure sgtiming sgmisc sgdebug
+    ${RT_LIBRARY})
+    
\ No newline at end of file
index 50d059e6e2ffcfbebc55a932342a204107f1dad6..68d69d3cc270c2f41f5f55c3cdef83045d4e7aaa 100644 (file)
@@ -7,12 +7,6 @@
 using std::string;
 using std::map;
 
-#include <iostream>
-
-using std::cout;
-using std::cerr;
-using std::endl;
-
 namespace simgear
 {
 
@@ -51,8 +45,15 @@ string Request::header(const std::string& name) const
 
 void Request::responseStart(const string& r)
 {
-    const int maxSplit = 2; // HTTP/1.1 nnn status code
+    const int maxSplit = 2; // HTTP/1.1 nnn reason-string
     string_list parts = strutils::split(r, NULL, maxSplit);
+    if (parts.size() != 3) {
+        SG_LOG(SG_IO, SG_WARN, "HTTP::Request: malformed response start:" << r);
+        _responseStatus = 400;
+        _responseReason = "bad HTTP response header";
+        return;
+    }
+    
     _responseStatus = strutils::to_int(parts[1]);
     _responseReason = parts[2];
 }
index 7cf498cd58e9d501c571c77e5809281f5ca070ea..8c0fcbac13895de02456e848e9ad435e98065c07 100644 (file)
@@ -37,14 +37,14 @@ public:
     virtual int responseCode() const
         { return _responseStatus; }
         
-    virtual std::string resposeReason() const
+    virtual std::string responseReason() const
         { return _responseReason; }
         
     virtual unsigned int contentLength() const;
 protected:
     friend class Connection;
     
-    Request(const std::string& url, const std::string method = "get");
+    Request(const std::string& url, const std::string method = "GET");
 
     virtual void responseStart(const std::string& r);
     virtual void responseHeader(const std::string& key, const std::string& value);
diff --git a/simgear/io/httpget.cxx b/simgear/io/httpget.cxx
new file mode 100644 (file)
index 0000000..513bb4b
--- /dev/null
@@ -0,0 +1,153 @@
+
+#include <cstdio>
+#include <cstring>
+
+#include <unistd.h> // for STDOUT_FILENO
+#include <iostream>
+#include <boost/foreach.hpp>
+
+#include <simgear/io/sg_file.hxx>
+#include <simgear/io/HTTPClient.hxx>
+#include <simgear/io/HTTPRequest.hxx>
+#include <simgear/io/sg_netChannel.hxx>
+
+using namespace simgear;
+using std::cout;
+using std::endl;
+using std::cerr;
+using std::string;
+
+class ARequest : public HTTP::Request
+{
+public:
+    ARequest(string& url) :
+        Request(url),
+        _complete(false),
+        _file(NULL)
+    {
+        
+    }
+    
+    void setFile(SGFile* f)
+    {
+        _file = f;
+    }
+    
+    bool complete() const
+        { return _complete; }
+        
+    void addHeader(const string& h)
+    {
+        int colonPos = h.find(':');
+        if (colonPos < 0) {
+            cerr << "malformed header: " << h << endl;
+            return;
+        }
+        
+        string key = h.substr(0, colonPos);
+        _headers[key] = h.substr(colonPos + 1);
+    }
+    
+    virtual string_list requestHeaders() const
+    {
+        string_list r;
+        std::map<string, string>::const_iterator it;
+        for (it = _headers.begin(); it != _headers.end(); ++it) {
+            r.push_back(it->first);
+        }
+        
+        return r;
+    }
+    
+    virtual string header(const string& name) const
+    {
+        std::map<string, string>::const_iterator it = _headers.find(name);
+        if (it == _headers.end()) {
+            return string();
+        }
+        
+        return it->second;
+    }
+protected:
+    virtual void responseHeadersComplete()
+    {
+    }
+
+    virtual void responseComplete()
+    {
+        _complete = true;
+    }  
+
+    virtual void gotBodyData(const char* s, int n)
+    {
+        _file->write(s, n);
+    }
+private:    
+    bool _complete;
+    SGFile* _file;
+    std::map<string, string> _headers;
+};
+
+int main(int argc, char* argv[])
+{
+    HTTP::Client cl;
+    SGFile* outFile;
+    string proxy, proxyAuth;
+    string_list headers;
+    string url;
+    
+    for (int a=0; a<argc;++a) {
+        if (argv[a][0] == '-') {
+            if (!strcmp(argv[a], "--user-agent")) {
+                cl.setUserAgent(argv[++a]);
+            } else if (!strcmp(argv[a], "--proxy")) {
+                proxy = argv[++a];
+            } else if (!strcmp(argv[a], "--auth")) {
+                proxyAuth = argv[++a];
+            } else if (!strcmp(argv[a], "-f") || !strcmp(argv[a], "--file")) {
+                outFile = new SGFile(argv[++a]);
+                if (!outFile->open(SG_IO_OUT)) {
+                    cerr << "failed to open output for writing:" << outFile->get_file_name() << endl;
+                    return EXIT_FAILURE;
+                }
+            } else if (!strcmp(argv[a], "--header")) {
+                headers.push_back(argv[++a]);
+            }
+        } else { // of argument starts with a hyphen
+            url = argv[a];
+        }
+    } // of arguments iteration
+
+    if (!proxy.empty()) {
+        cl.setProxy(proxy, proxyAuth);
+    }
+
+    if (!outFile) {
+        outFile = new SGFile(STDOUT_FILENO);
+    }
+
+    if (url.empty()) {
+        cerr << "no URL argument specificed" << endl;
+        return EXIT_FAILURE;
+    }
+
+    ARequest* req = new ARequest(url);
+    BOOST_FOREACH(string h, headers) {
+        req->addHeader(h);
+    }
+    
+    req->setFile(outFile);
+    cl.makeRequest(req);
+    
+    while (!req->complete()) {
+        NetChannel::poll(100);
+    }
+    
+    if (req->responseCode() != 200) {
+        cerr << "got response:" << req->responseCode() << endl;
+        cerr << "\treason:" << req->responseReason() << endl;
+        return EXIT_FAILURE;
+    }
+    
+    return EXIT_SUCCESS;
+}
index d8a29608db20b2dbef3e6b2974bcce3881ab709a..ea1b00773b0327d08cad8120db1fc8f079bcf96c 100644 (file)
 
 #include <simgear/compiler.h>
 
-// #include "protocol.hxx"
-
-#include <string>
-#include <vector>
-
-using std::vector;
-using std::string;
-
-
 #define SG_IO_MAX_MSG_SIZE 16384
 
 /**
index 67fbda3eb9547f107a768cfaf64791a228a94742..250518d847f5f99f6d26d7070c4521b2d5f10290 100644 (file)
 
 #include <cstring>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if !defined(_MSC_VER)
+# include <unistd.h>
+#endif
+
 #include <simgear/misc/stdint.hxx>
 #include <simgear/debug/logstream.hxx>
 
 
 using std::string;
 
-
 SGFile::SGFile(const string &file, int repeat_)
     : file_name(file), fp(-1), eof_flag(true), repeat(repeat_), iteration(0)
 {
     set_type( sgFileType );
 }
 
+SGFile::SGFile( int existingFd ) :
+    fp(existingFd),
+    eof_flag(false),
+    repeat(1),
+    iteration(0)
+{
+    set_type( sgFileType );
+}
 
 SGFile::~SGFile() {
 }
index 1bf3800de6fcfafd252556b878795982d175d5fa..7e5854c14ac9008bbd9be46d2f9de231cafe729c 100644 (file)
 #ifndef _SG_FILE_HXX
 #define _SG_FILE_HXX
 
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
 #include <simgear/compiler.h>
 
 #include <string>
 
-#include <sys/types.h>         // for open(), read(), write(), close()
-#include <sys/stat.h>          // for open(), read(), write(), close()
-#include <fcntl.h>             // for open(), read(), write(), close()
-#if !defined( _MSC_VER )
-#  include <unistd.h>          // for open(), read(), write(), close()
-#endif
-
 #include "iochannel.hxx"
 
-using std::string;
-
 
 /**
  * A file I/O class based on SGIOChannel.
  */
 class SGFile : public SGIOChannel {
 
-    string file_name;
+    std::string file_name;
     int fp;
     bool eof_flag;
     // Number of repetitions to play. -1 means loop infinitely.
@@ -70,7 +56,12 @@ public:
      * @param file name of file to open
      * @param repeat On eof restart at the beginning of the file
      */
-    SGFile( const string& file, int repeat_ = 1 );
+    SGFile( const std::string& file, int repeat_ = 1 );
+
+    /**
+     * Create an SGFile from an existing, open file-descriptor
+     */
+    SGFile( int existingFd );
 
     /** Destructor */
     ~SGFile();
@@ -94,7 +85,7 @@ public:
     bool close();
 
     /** @return the name of the file being manipulated. */
-    inline string get_file_name() const { return file_name; }
+    inline std::string get_file_name() const { return file_name; }
 
     /** @return true of eof conditions exists */
     inline bool eof() const { return eof_flag; };
index 4af401de65e98dc356ea2410ad82a02a1b1bda50..4ca13150170e6bfba5eb052c8115ce6e85b1f668 100644 (file)
@@ -36,6 +36,7 @@
 #include "sg_socket.hxx"
 
 bool SGSocket::init = false;
+using std::string;
 
 SGSocket::SGSocket( const string& host, const string& port_, 
                    const string& style ) :
index 2d2971540f3b698538347154759044a7930995fb..82b23757c631291332258fbd146a8aaad41c6e8e 100644 (file)
@@ -33,6 +33,8 @@
 #include <cstring>
 #include <cstdlib> // for atoi
 
+using std::string;
+
 SGSocketUDP::SGSocketUDP( const string& host, const string& port ) :
     hostname(host),
     port_str(port),
index 69a5b0274cb423ba9e1ddc61212db19d33d5f948..9234c413820b87edc38fb8a633fe4eed93278784 100644 (file)
@@ -89,7 +89,7 @@ public:
      * @param host name of host if direction is SG_IO_OUT or SG_IO_BI
      * @param port port number if we care to choose one.
      * @param style specify "udp" or "tcp" */
-    SGSocketUDP( const string& host, const string& port );
+    SGSocketUDP( const std::string& host, const std::string& port );
 
     /** Destructor */
     ~SGSocketUDP();
index 1dce8d29e355f59451811a31e9c7ec5fcd7f7e8b..8aafef2d59cd46b5d3d811d03888a553415c8f8c 100644 (file)
@@ -275,6 +275,7 @@ int main(int argc, char* argv[])
 
         waitForComplete(tr);
         COMPARE(tr->responseCode(), 200);
+        COMPARE(tr->responseReason(), string("OK"));
         COMPARE(tr->contentLength(), strlen(BODY1));
         COMPARE(tr->bodyData, string(BODY1));
     }
@@ -301,6 +302,7 @@ int main(int argc, char* argv[])
         cl.makeRequest(tr);
         waitForComplete(tr);
         COMPARE(tr->responseCode(), 404);
+        COMPARE(tr->responseReason(), string("not found"));
         COMPARE(tr->contentLength(), 0);
     }