2 * HappyHTTP - a simple HTTP library
5 * Copyright (c) 2006 Ben Campbell
7 * This software is provided 'as-is', without any express or implied
8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software.
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software. If you use this software in a
17 * product, an acknowledgment in the product documentation would be
18 * appreciated but is not required.
20 * 2. Altered source versions must be plainly marked as such, and must not
21 * be misrepresented as being the original software.
23 * 3. This notice may not be removed or altered from any source distribution.
50 void BailOnSocketError( const char* context
);
51 struct in_addr
*atoaddr( const char* address
);
54 typedef void (*ResponseBegin_CB
)( const Response
* r
, void* userdata
);
55 typedef void (*ResponseData_CB
)( const Response
* r
, void* userdata
, const unsigned char* data
, int numbytes
);
56 typedef void (*ResponseComplete_CB
)( const Response
* r
, void* userdata
);
63 SWITCHING_PROTOCOLS
= 101,
70 NON_AUTHORITATIVE_INFORMATION
= 203,
73 PARTIAL_CONTENT
= 206,
78 MULTIPLE_CHOICES
= 300,
79 MOVED_PERMANENTLY
= 301,
84 TEMPORARY_REDIRECT
= 307,
89 PAYMENT_REQUIRED
= 402,
92 METHOD_NOT_ALLOWED
= 405,
94 PROXY_AUTHENTICATION_REQUIRED
= 407,
95 REQUEST_TIMEOUT
= 408,
98 LENGTH_REQUIRED
= 411,
99 PRECONDITION_FAILED
= 412,
100 REQUEST_ENTITY_TOO_LARGE
= 413,
101 REQUEST_URI_TOO_LONG
= 414,
102 UNSUPPORTED_MEDIA_TYPE
= 415,
103 REQUESTED_RANGE_NOT_SATISFIABLE
= 416,
104 EXPECTATION_FAILED
= 417,
105 UNPROCESSABLE_ENTITY
= 422,
107 FAILED_DEPENDENCY
= 424,
108 UPGRADE_REQUIRED
= 426,
111 INTERNAL_SERVER_ERROR
= 500,
112 NOT_IMPLEMENTED
= 501,
114 SERVICE_UNAVAILABLE
= 503,
115 GATEWAY_TIMEOUT
= 504,
116 HTTP_VERSION_NOT_SUPPORTED
= 505,
117 INSUFFICIENT_STORAGE
= 507,
128 Wobbly( const char* fmt
, ... );
129 const char* what() const
130 { return m_Message
; }
133 char m_Message
[ MAXLEN
];
138 //-------------------------------------------------
141 // Handles the socket connection, issuing of requests and managing
143 // ------------------------------------------------
147 friend class Response
;
149 // doesn't connect immediately
150 Connection( const char* host
, int port
);
153 // Set up the response handling callbacks. These will be invoked during
155 // begincb - called when the responses headers have been received
156 // datacb - called repeatedly to handle body data
157 // completecb - response is completed
158 // userdata is passed as a param to all callbacks.
160 ResponseBegin_CB begincb
,
161 ResponseData_CB datacb
,
162 ResponseComplete_CB completecb
,
165 // Don't need to call connect() explicitly as issuing a request will
166 // call it automatically if needed.
167 // But it could block (for name lookup etc), so you might prefer to
168 // call it in advance.
171 // close connection, discarding any pending requests.
174 // Update the connection (non-blocking)
175 // Just keep calling this regularly to service outstanding requests.
178 // any requests still outstanding?
179 bool outstanding() const
180 { return !m_Outstanding
.empty(); }
182 // ---------------------------
183 // high-level request interface
184 // ---------------------------
186 // method is "GET", "POST" etc...
187 // url is only path part: eg "/index.html"
188 // headers is array of name/value pairs, terminated by a null-ptr
189 // body & bodysize specify body data of request (eg values for a form)
190 void request( const char* method
, const char* url
, const char* headers
[]=0,
191 const unsigned char* body
=0, int bodysize
=0 );
193 // ---------------------------
194 // low-level request interface
195 // ---------------------------
198 // method is "GET", "POST" etc...
199 // url is only path part: eg "/index.html"
200 void putrequest( const char* method
, const char* url
);
202 // Add a header to the request (call after putrequest() )
203 void putheader( const char* header
, const char* value
);
204 void putheader( const char* header
, int numericvalue
); // alternate version
206 // Finished adding headers, issue the request.
209 // send body data if any.
210 // To be called after endheaders()
211 void send( const unsigned char* buf
, int numbytes
);
214 // some bits of implementation exposed to Response class
217 ResponseBegin_CB m_ResponseBeginCB
;
218 ResponseData_CB m_ResponseDataCB
;
219 ResponseComplete_CB m_ResponseCompleteCB
;
223 enum { IDLE
, REQ_STARTED
, REQ_SENT
} m_State
;
227 std::vector
< std::string
> m_Buffer
; // lines of request
229 std::deque
< Response
* > m_Outstanding
; // responses for outstanding requests
237 //-------------------------------------------------
240 // Handles parsing of response data.
241 // ------------------------------------------------
246 friend class Connection
;
249 // retrieve a header (returns 0 if not present)
250 const char* getheader( const char* name
) const;
252 bool completed() const
253 { return m_State
== COMPLETE
; }
256 // get the HTTP status code
257 int getstatus() const;
259 // get the HTTP response reason string
260 const char* getreason() const;
262 // true if connection is expected to close after this response.
263 bool willclose() const
264 { return m_WillClose
; }
266 // interface used by Connection
268 // only Connection creates Responses.
269 Response( const char* method
, Connection
& conn
);
271 // pump some data in for processing.
272 // Returns the number of bytes used.
273 // Will always return 0 when response is complete.
274 int pump( const unsigned char* data
, int datasize
);
276 // tell response that connection has closed
277 void notifyconnectionclosed();
281 STATUSLINE
, // start here. status line is first line of response.
282 HEADERS
, // reading in header lines
283 BODY
, // waiting for some body data (all or a chunk)
284 CHUNKLEN
, // expecting a chunk length indicator (in hex)
285 CHUNKEND
, // got the chunk, now expecting a trailing blank line
286 TRAILERS
, // reading trailers after body.
287 COMPLETE
, // response is complete!
290 Connection
& m_Connection
; // to access callback ptrs
291 std::string m_Method
; // req method: "GET", "POST" etc...
294 std::string m_VersionString
; // HTTP-Version
295 int m_Version
; // 10: HTTP/1.0 11: HTTP/1.x (where x>=1)
296 int m_Status
; // Status-Code
297 std::string m_Reason
; // Reason-Phrase
299 // header/value pairs
300 std::map
<std::string
,std::string
> m_Headers
;
302 int m_BytesRead
; // body bytes read so far
303 bool m_Chunked
; // response is chunked?
304 int m_ChunkLeft
; // bytes left in current chunk
305 int m_Length
; // -1 if unknown
306 bool m_WillClose
; // connection will close at response end?
308 std::string m_LineBuf
; // line accumulation for states that want it
309 std::string m_HeaderAccum
; // accumulation buffer for headers
313 void ProcessStatusLine( std::string
const& line
);
314 void ProcessHeaderLine( std::string
const& line
);
315 void ProcessTrailerLine( std::string
const& line
);
316 void ProcessChunkLenLine( std::string
const& line
);
318 int ProcessDataChunked( const unsigned char* data
, int count
);
319 int ProcessDataNonChunked( const unsigned char* data
, int count
);
328 } // end namespace happyhttp
331 #endif // HAPPYHTTP_H