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
using std::string;
using std::map;
-#include <iostream>
-
-using std::cout;
-using std::cerr;
-using std::endl;
-
namespace simgear
{
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];
}
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);
--- /dev/null
+
+#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;
+}
#include <simgear/compiler.h>
-// #include "protocol.hxx"
-
-#include <string>
-#include <vector>
-
-using std::vector;
-using std::string;
-
-
#define SG_IO_MAX_MSG_SIZE 16384
/**
#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() {
}
#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.
* @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();
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; };
#include "sg_socket.hxx"
bool SGSocket::init = false;
+using std::string;
SGSocket::SGSocket( const string& host, const string& port_,
const string& style ) :
#include <cstring>
#include <cstdlib> // for atoi
+using std::string;
+
SGSocketUDP::SGSocketUDP( const string& host, const string& port ) :
hostname(host),
port_str(port),
* @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();
waitForComplete(tr);
COMPARE(tr->responseCode(), 200);
+ COMPARE(tr->responseReason(), string("OK"));
COMPARE(tr->contentLength(), strlen(BODY1));
COMPARE(tr->bodyData, string(BODY1));
}
cl.makeRequest(tr);
waitForComplete(tr);
COMPARE(tr->responseCode(), 404);
+ COMPARE(tr->responseReason(), string("not found"));
COMPARE(tr->contentLength(), 0);
}