HappyHTTP is a simple C++ library for issuing HTTP requests and processing responses.
Why reinvent the wheel with yet another HTTP library?
I wanted one that was non-blocking, lightweight, and easy to drop into an
existing project.
Also, I wanted to learn a bit more about HTTP.
Latest Version is 0.1: happyhttp-0.1.tar.gz
The interface is based loosely on Pythons httplib. I've kept the same terminology where possible.
All HappyHTTP code is kept within the happyhttp
namespace
To issue and process a HTTP request, the basic steps are:
Connection( const char* host, int port )
Constructor. Specifies host and port, but connection isn't made until request
is issued or connect() is called.
~Connection()
Destructor. If connection is open, it'll be closed, and any outstanding requests will be discarded.
void setcallbacks( ResponseBegin_CB begincb, ResponseData_CB datacb, ResponseComplete_CB completecb, void* userdata )
Set up the response handling callbacks. These will be invoked during
calls to pump().
begincb
- called when the responses headers have been received
datacb
- called repeatedly to handle body data
completecb
- response is completed
userdata
- passed as a param to all callbacks.
void connect()
Don't need to call connect() explicitly as issuing a request will
call it automatically if needed.
But it could block (for name lookup etc), so you might prefer to
call it in advance.
void close()
// close connection, discarding any pending requests.
void pump()
Update the connection (non-blocking)
Just keep calling this regularly to service outstanding requests.
As responses are received, the callbacks will be invoked.
bool outstanding() const
Returns true if any requests are still outstanding.
void request( const char* method, const char* url, const char* headers[], const unsigned char* body, int bodysize )
High-level request interface. Issues a request.
method
- "GET", "POST" etc...
url
- eg "/index.html"
headers
- array of name/value pairs, terminated by a null-ptr
body, bodysize
- specify body data of request (eg values for a form)
void putrequest( const char* method, const char* url )
(part of low-level request interface)
Begin a request
method is "GET", "POST" etc...
url is only path part: eg "/index.html"
void putheader( const char* header, const char* value )
void putheader( const char* header, int numericvalue )
(part of low-level request interface)
Add a header to the request (call after putrequest() )
void endheaders()
(part of low-level request interface)
Indicate that your are finished adding headers and the request can be issued.
void send( const unsigned char* buf, int numbytes )
(part of low-level request interface)
send body data if any.
To be called after endheaders()
typedef void (*ResponseBegin_CB)( const Response* r, void* userdata )
Invoked when all the headers for a response have been received.
The Response object can be queried to determine status and header values.
userdata
is the same value that was passed in to
Connection::setcallbacks()
.
typedef void (*ResponseData_CB)( const Response* r, void* userdata, const unsigned char* data, int numbytes )
This callback is invoked to pass out data from the body of the response. It may
be called multiple times, or not at all (if there is no body).
typedef void (*ResponseComplete_CB)( const Response* r, void* userdata )
Once a response is completed, this callback is invoked. When the callback
returns, the respsonse object will be destroyed.
const char* getheader( const char* name ) const
retrieve the value of a header (returns 0 if not present)
int getstatus() const
Get the HTTP status code returned by the server
const char* getreason() const
Get the HTTP response reason string returned by the server
If an error occurs, a Wobbly
is thrown.
The Wobbly::what()
method returns a text description.
For more examples, see test.cpp.
static int count=0; // invoked when response headers have been received void OnBegin( const happyhttp::Response* r, void* userdata ) { printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() ); count = 0; } // invoked to process response body data (may be called multiple times) void OnData( const happyhttp::Response* r, void* userdata, const unsigned char* data, int n ) { fwrite( data,1,n, stdout ); count += n; } // invoked when response is complete void OnComplete( const happyhttp::Response* r, void* userdata ) { printf( "COMPLETE (%d bytes)\n", count ); } void TestGET() { happyhttp::Connection conn( "www.scumways.com", 80 ); conn.setcallbacks( OnBegin, OnData, OnComplete, 0 ); conn.request( "GET", "/happyhttp/test.php" ); while( conn.outstanding() ) conn.pump(); }
Priority stuff:
Stuff that'd be nice, but I probably won't get around to doing for a while:
Stuff that I almost certainly won't get around to doing, but would seriously consider if someone sent me a patch :-)
HappyHTTP is licensed under the zlib/libpng license.
The intented spirit is: do whatever you want with it (including using it in commercial products), but if you make improvements, please send me a patch!
If you use it in something cool, let me know!