1/*
2 * Copyright 2010-2013 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _B_URL_PROTOCOL_HTTP_H_
6#define _B_URL_PROTOCOL_HTTP_H_
7
8
9#include <deque>
10
11#include <Certificate.h>
12#include <HttpForm.h>
13#include <HttpHeaders.h>
14#include <HttpResult.h>
15#include <NetworkAddress.h>
16#include <NetworkRequest.h>
17
18
19namespace BPrivate {
20	class CheckedSecureSocket;
21	class CheckedProxySecureSocket;
22};
23
24
25class BHttpRequest : public BNetworkRequest {
26public:
27								BHttpRequest(const BUrl& url,
28									bool ssl = false,
29									const char* protocolName = "HTTP",
30									BUrlProtocolListener* listener = NULL,
31									BUrlContext* context = NULL);
32								BHttpRequest(const BHttpRequest& other);
33	virtual						~BHttpRequest();
34
35			void				SetMethod(const char* const method);
36			void				SetFollowLocation(bool follow);
37			void				SetMaxRedirections(int8 maxRedirections);
38			void				SetReferrer(const BString& referrer);
39			void				SetUserAgent(const BString& agent);
40			void				SetDiscardData(bool discard);
41			void				SetDisableListener(bool disable);
42			void				SetAutoReferrer(bool enable);
43			void				SetUserName(const BString& name);
44			void				SetPassword(const BString& password);
45			void				SetRangeStart(off_t position);
46			void				SetRangeEnd(off_t position);
47
48			void				SetPostFields(const BHttpForm& fields);
49			void				SetHeaders(const BHttpHeaders& headers);
50
51			void				AdoptPostFields(BHttpForm* const fields);
52			void				AdoptInputData(BDataIO* const data,
53									const ssize_t size = -1);
54			void				AdoptHeaders(BHttpHeaders* const headers);
55
56			status_t			Stop();
57			const BUrlResult&	Result() const;
58
59	static	bool				IsInformationalStatusCode(int16 code);
60	static	bool				IsSuccessStatusCode(int16 code);
61	static	bool				IsRedirectionStatusCode(int16 code);
62	static	bool				IsClientErrorStatusCode(int16 code);
63	static	bool				IsServerErrorStatusCode(int16 code);
64	static	int16				StatusCodeClass(int16 code);
65
66private:
67			void				_ResetOptions();
68			status_t			_ProtocolLoop();
69			status_t			_MakeRequest();
70
71			BString				_SerializeRequest();
72			BString				_SerializeHeaders();
73			void				_SendPostData();
74
75			void				_ParseStatus();
76			void				_ParseHeaders();
77
78	// URL result parameters access
79			BPositionIO*		_ResultRawData();
80			BHttpHeaders&		_ResultHeaders();
81			void				_SetResultStatusCode(int32 statusCode);
82			BString&			_ResultStatusText();
83
84	// SSL failure management
85	friend	class				BPrivate::CheckedSecureSocket;
86	friend	class				BPrivate::CheckedProxySecureSocket;
87			bool				_CertificateVerificationFailed(
88									BCertificate& certificate,
89									const char* message);
90
91	// Utility methods
92			bool				_IsDefaultPort();
93
94private:
95			bool				fSSL;
96
97			BString				fRequestMethod;
98			int8				fHttpVersion;
99
100			BHttpHeaders		fHeaders;
101
102	// Request status
103
104			BHttpResult			fResult;
105
106			// Request state/events
107			enum {
108				kRequestInitialState,
109				kRequestStatusReceived,
110				kRequestHeadersReceived,
111				kRequestContentReceived,
112				kRequestTrailingHeadersReceived
113			}					fRequestStatus;
114
115
116	// Protocol options
117			uint8				fOptMaxRedirs;
118			BString				fOptReferer;
119			BString				fOptUserAgent;
120			BString				fOptUsername;
121			BString				fOptPassword;
122			uint32				fOptAuthMethods;
123			BHttpHeaders*		fOptHeaders;
124			BHttpForm*			fOptPostFields;
125			BDataIO*			fOptInputData;
126			ssize_t				fOptInputDataSize;
127			off_t				fOptRangeStart;
128			off_t				fOptRangeEnd;
129			bool				fOptSetCookies : 1;
130			bool				fOptFollowLocation : 1;
131			bool				fOptDiscardData : 1;
132			bool				fOptDisableListener : 1;
133			bool				fOptAutoReferer : 1;
134};
135
136// Request method
137const char* const B_HTTP_GET = "GET";
138const char* const B_HTTP_POST = "POST";
139const char* const B_HTTP_PUT = "PUT";
140const char* const B_HTTP_HEAD = "HEAD";
141const char* const B_HTTP_DELETE = "DELETE";
142const char* const B_HTTP_OPTIONS = "OPTIONS";
143const char* const B_HTTP_TRACE = "TRACE";
144const char* const B_HTTP_CONNECT = "CONNECT";
145
146
147// HTTP Version
148enum {
149	B_HTTP_10 = 1,
150	B_HTTP_11
151};
152
153
154// HTTP status classes
155enum http_status_code_class {
156	B_HTTP_STATUS_CLASS_INVALID			= 000,
157	B_HTTP_STATUS_CLASS_INFORMATIONAL 	= 100,
158	B_HTTP_STATUS_CLASS_SUCCESS			= 200,
159	B_HTTP_STATUS_CLASS_REDIRECTION		= 300,
160	B_HTTP_STATUS_CLASS_CLIENT_ERROR	= 400,
161	B_HTTP_STATUS_CLASS_SERVER_ERROR	= 500
162};
163
164
165// Known HTTP status codes
166enum http_status_code {
167	// Informational status codes
168	B_HTTP_STATUS__INFORMATIONAL_BASE	= 100,
169	B_HTTP_STATUS_CONTINUE = B_HTTP_STATUS__INFORMATIONAL_BASE,
170	B_HTTP_STATUS_SWITCHING_PROTOCOLS,
171	B_HTTP_STATUS__INFORMATIONAL_END,
172
173	// Success status codes
174	B_HTTP_STATUS__SUCCESS_BASE			= 200,
175	B_HTTP_STATUS_OK = B_HTTP_STATUS__SUCCESS_BASE,
176	B_HTTP_STATUS_CREATED,
177	B_HTTP_STATUS_ACCEPTED,
178	B_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION,
179	B_HTTP_STATUS_NO_CONTENT,
180	B_HTTP_STATUS_RESET_CONTENT,
181	B_HTTP_STATUS_PARTIAL_CONTENT,
182	B_HTTP_STATUS__SUCCESS_END,
183
184	// Redirection status codes
185	B_HTTP_STATUS__REDIRECTION_BASE		= 300,
186	B_HTTP_STATUS_MULTIPLE_CHOICE = B_HTTP_STATUS__REDIRECTION_BASE,
187	B_HTTP_STATUS_MOVED_PERMANENTLY,
188	B_HTTP_STATUS_FOUND,
189	B_HTTP_STATUS_SEE_OTHER,
190	B_HTTP_STATUS_NOT_MODIFIED,
191	B_HTTP_STATUS_USE_PROXY,
192	B_HTTP_STATUS_TEMPORARY_REDIRECT,
193	B_HTTP_STATUS__REDIRECTION_END,
194
195	// Client error status codes
196	B_HTTP_STATUS__CLIENT_ERROR_BASE	= 400,
197	B_HTTP_STATUS_BAD_REQUEST = B_HTTP_STATUS__CLIENT_ERROR_BASE,
198	B_HTTP_STATUS_UNAUTHORIZED,
199	B_HTTP_STATUS_PAYMENT_REQUIRED,
200	B_HTTP_STATUS_FORBIDDEN,
201	B_HTTP_STATUS_NOT_FOUND,
202	B_HTTP_STATUS_METHOD_NOT_ALLOWED,
203	B_HTTP_STATUS_NOT_ACCEPTABLE,
204	B_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED,
205	B_HTTP_STATUS_REQUEST_TIMEOUT,
206	B_HTTP_STATUS_CONFLICT,
207	B_HTTP_STATUS_GONE,
208	B_HTTP_STATUS_LENGTH_REQUIRED,
209	B_HTTP_STATUS_PRECONDITION_FAILED,
210	B_HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE,
211	B_HTTP_STATUS_REQUEST_URI_TOO_LARGE,
212	B_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE,
213	B_HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE,
214	B_HTTP_STATUS_EXPECTATION_FAILED,
215	B_HTTP_STATUS__CLIENT_ERROR_END,
216
217	// Server error status codes
218	B_HTTP_STATUS__SERVER_ERROR_BASE 	= 500,
219	B_HTTP_STATUS_INTERNAL_SERVER_ERROR = B_HTTP_STATUS__SERVER_ERROR_BASE,
220	B_HTTP_STATUS_NOT_IMPLEMENTED,
221	B_HTTP_STATUS_BAD_GATEWAY,
222	B_HTTP_STATUS_SERVICE_UNAVAILABLE,
223	B_HTTP_STATUS_GATEWAY_TIMEOUT,
224	B_HTTP_STATUS__SERVER_ERROR_END
225};
226
227
228// HTTP default User-Agent
229#define B_HTTP_PROTOCOL_USER_AGENT_FORMAT "ServicesKit (%s)"
230
231#endif // _B_URL_PROTOCOL_HTTP_H_
232