/* * Copyright 2010-2021 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _B_URL_PROTOCOL_HTTP_H_ #define _B_URL_PROTOCOL_HTTP_H_ #include #include #include #include #include #include #include #include namespace BPrivate { class CheckedSecureSocket; class CheckedProxySecureSocket; }; namespace BPrivate { namespace Network { class BHttpRequest : public BNetworkRequest { public: virtual ~BHttpRequest(); void SetMethod(const char* const method); void SetFollowLocation(bool follow); void SetMaxRedirections(int8 maxRedirections); void SetReferrer(const BString& referrer); void SetUserAgent(const BString& agent); void SetDiscardData(bool discard); void SetDisableListener(bool disable); void SetAutoReferrer(bool enable); void SetStopOnError(bool stop); void SetUserName(const BString& name); void SetPassword(const BString& password); void SetRangeStart(off_t position); void SetRangeEnd(off_t position); void SetPostFields(const BHttpForm& fields); void SetHeaders(const BHttpHeaders& headers); void AdoptPostFields(BHttpForm* const fields); void AdoptInputData(BDataIO* const data, const ssize_t size = -1); void AdoptHeaders(BHttpHeaders* const headers); status_t Stop(); const BUrlResult& Result() const; static bool IsInformationalStatusCode(int16 code); static bool IsSuccessStatusCode(int16 code); static bool IsRedirectionStatusCode(int16 code); static bool IsClientErrorStatusCode(int16 code); static bool IsServerErrorStatusCode(int16 code); static int16 StatusCodeClass(int16 code); private: friend class BUrlProtocolRoster; BHttpRequest(const BUrl& url, BDataIO* output, bool ssl = false, const char* protocolName = "HTTP", BUrlProtocolListener* listener = NULL, BUrlContext* context = NULL); BHttpRequest(const BHttpRequest& other); void _ResetOptions(); status_t _ProtocolLoop(); status_t _MakeRequest(); BString _SerializeRequest(); BString _SerializeHeaders(); void _SendPostData(); void _ParseStatus(); void _ParseHeaders(); // URL result parameters access BPositionIO* _ResultRawData(); BHttpHeaders& _ResultHeaders(); void _SetResultStatusCode(int32 statusCode); BString& _ResultStatusText(); // SSL failure management friend class BPrivate::CheckedSecureSocket; friend class BPrivate::CheckedProxySecureSocket; bool _CertificateVerificationFailed( BCertificate& certificate, const char* message); // Utility methods bool _IsDefaultPort(); private: bool fSSL; BString fRequestMethod; int8 fHttpVersion; BHttpHeaders fHeaders; // Request status BHttpResult fResult; // Request state/events enum { kRequestInitialState, kRequestStatusReceived, kRequestHeadersReceived, kRequestContentReceived, kRequestTrailingHeadersReceived } fRequestStatus; // Protocol options uint8 fOptMaxRedirs; BString fOptReferer; BString fOptUserAgent; BString fOptUsername; BString fOptPassword; uint32 fOptAuthMethods; BHttpHeaders* fOptHeaders; BHttpForm* fOptPostFields; BDataIO* fOptInputData; ssize_t fOptInputDataSize; off_t fOptRangeStart; off_t fOptRangeEnd; bool fOptSetCookies : 1; bool fOptFollowLocation : 1; bool fOptDiscardData : 1; bool fOptDisableListener : 1; bool fOptAutoReferer : 1; bool fOptStopOnError : 1; }; // Request method const char* const B_HTTP_GET = "GET"; const char* const B_HTTP_POST = "POST"; const char* const B_HTTP_PUT = "PUT"; const char* const B_HTTP_HEAD = "HEAD"; const char* const B_HTTP_DELETE = "DELETE"; const char* const B_HTTP_OPTIONS = "OPTIONS"; const char* const B_HTTP_TRACE = "TRACE"; const char* const B_HTTP_CONNECT = "CONNECT"; // HTTP Version enum { B_HTTP_10 = 1, B_HTTP_11 }; // HTTP status classes enum http_status_code_class { B_HTTP_STATUS_CLASS_INVALID = 000, B_HTTP_STATUS_CLASS_INFORMATIONAL = 100, B_HTTP_STATUS_CLASS_SUCCESS = 200, B_HTTP_STATUS_CLASS_REDIRECTION = 300, B_HTTP_STATUS_CLASS_CLIENT_ERROR = 400, B_HTTP_STATUS_CLASS_SERVER_ERROR = 500 }; // Known HTTP status codes enum http_status_code { // Informational status codes B_HTTP_STATUS__INFORMATIONAL_BASE = 100, B_HTTP_STATUS_CONTINUE = B_HTTP_STATUS__INFORMATIONAL_BASE, B_HTTP_STATUS_SWITCHING_PROTOCOLS, B_HTTP_STATUS__INFORMATIONAL_END, // Success status codes B_HTTP_STATUS__SUCCESS_BASE = 200, B_HTTP_STATUS_OK = B_HTTP_STATUS__SUCCESS_BASE, B_HTTP_STATUS_CREATED, B_HTTP_STATUS_ACCEPTED, B_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION, B_HTTP_STATUS_NO_CONTENT, B_HTTP_STATUS_RESET_CONTENT, B_HTTP_STATUS_PARTIAL_CONTENT, B_HTTP_STATUS__SUCCESS_END, // Redirection status codes B_HTTP_STATUS__REDIRECTION_BASE = 300, B_HTTP_STATUS_MULTIPLE_CHOICE = B_HTTP_STATUS__REDIRECTION_BASE, B_HTTP_STATUS_MOVED_PERMANENTLY, B_HTTP_STATUS_FOUND, B_HTTP_STATUS_SEE_OTHER, B_HTTP_STATUS_NOT_MODIFIED, B_HTTP_STATUS_USE_PROXY, B_HTTP_STATUS_TEMPORARY_REDIRECT, B_HTTP_STATUS__REDIRECTION_END, // Client error status codes B_HTTP_STATUS__CLIENT_ERROR_BASE = 400, B_HTTP_STATUS_BAD_REQUEST = B_HTTP_STATUS__CLIENT_ERROR_BASE, B_HTTP_STATUS_UNAUTHORIZED, B_HTTP_STATUS_PAYMENT_REQUIRED, B_HTTP_STATUS_FORBIDDEN, B_HTTP_STATUS_NOT_FOUND, B_HTTP_STATUS_METHOD_NOT_ALLOWED, B_HTTP_STATUS_NOT_ACCEPTABLE, B_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED, B_HTTP_STATUS_REQUEST_TIMEOUT, B_HTTP_STATUS_CONFLICT, B_HTTP_STATUS_GONE, B_HTTP_STATUS_LENGTH_REQUIRED, B_HTTP_STATUS_PRECONDITION_FAILED, B_HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE, B_HTTP_STATUS_REQUEST_URI_TOO_LARGE, B_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, B_HTTP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, B_HTTP_STATUS_EXPECTATION_FAILED, B_HTTP_STATUS__CLIENT_ERROR_END, // Server error status codes B_HTTP_STATUS__SERVER_ERROR_BASE = 500, B_HTTP_STATUS_INTERNAL_SERVER_ERROR = B_HTTP_STATUS__SERVER_ERROR_BASE, B_HTTP_STATUS_NOT_IMPLEMENTED, B_HTTP_STATUS_BAD_GATEWAY, B_HTTP_STATUS_SERVICE_UNAVAILABLE, B_HTTP_STATUS_GATEWAY_TIMEOUT, B_HTTP_STATUS__SERVER_ERROR_END }; // HTTP default User-Agent #define B_HTTP_PROTOCOL_USER_AGENT_FORMAT "ServicesKit (%s)" } // namespace Network } // namespace BPrivate #endif // _B_URL_PROTOCOL_HTTP_H_