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