Socket mutexes are no longer really required, and so have been removed. Added more tests for network encoding functions, and the URL parser. The URL parser now returns a path preceeded with a '/' instead of cutting it out. Added get_uri() to URL, for getting the whole URI, so users don't have to concat it themselves from the more specialised functions. Fixed default socket connect timeout checking for the wrong value. Fixed request_type_strings not containing all of the possible request types. Fixed README using old socket close syntax. Cleaned up the examples a bit.
331 lines
9.5 KiB
C++
331 lines
9.5 KiB
C++
//
|
|
// Created by fred on 11/12/16.
|
|
//
|
|
|
|
#ifndef FRNETLIB_HTTP_H
|
|
#define FRNETLIB_HTTP_H
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include "Socket.h"
|
|
#include "Sendable.h"
|
|
|
|
namespace fr
|
|
{
|
|
class Http : public Sendable
|
|
{
|
|
public:
|
|
enum RequestType
|
|
{
|
|
Unknown = 0,
|
|
Get = 1,
|
|
Post = 2,
|
|
Put = 3,
|
|
Delete = 4,
|
|
Patch = 5,
|
|
RequestTypeCount = 6, //Keep me at the end and updated
|
|
};
|
|
enum RequestStatus
|
|
{
|
|
Continue = 100,
|
|
SwitchingProtocols = 101,
|
|
Ok = 200,
|
|
Created = 201,
|
|
Accepted = 202,
|
|
NonAuthorativeInformation = 203,
|
|
NoContent = 204,
|
|
ResetContent = 205,
|
|
PartialContent = 206,
|
|
IMUsed = 226,
|
|
MultipleChoices = 300,
|
|
MovedPermanently = 301,
|
|
Found = 302,
|
|
SeeOther = 303,
|
|
NotModified = 304,
|
|
UseProxy = 305,
|
|
TemporaryRedirect = 307,
|
|
PermanentRedirect = 308,
|
|
BadRequest = 400,
|
|
Unauthorised = 401,
|
|
PaymentRequired = 402,
|
|
Forbidden = 403,
|
|
NotFound = 404,
|
|
MethodNotAllowed = 405,
|
|
NotAcceptable = 406,
|
|
ProxyAuthenticationRequired = 407,
|
|
RequestTimeout = 408,
|
|
Conflict = 409,
|
|
Gone = 410,
|
|
LengthRequired = 411,
|
|
PreconditionFailed = 412,
|
|
RequestEntityTooLarge = 413,
|
|
RequestURITooLong = 414,
|
|
UnsupportedMediaType = 415,
|
|
RequestedRangeNotSatisfiable = 416,
|
|
ExpectationFailed = 417,
|
|
ImATeapot = 418,
|
|
UnprocessableEntity = 422,
|
|
UpgradeRequired = 426,
|
|
PreconditionRequired = 428,
|
|
TooManyRequests = 429,
|
|
RequestHeaderFieldTooLarge = 431,
|
|
UnvailableForLegalReasons = 451,
|
|
InternalServerError = 500,
|
|
NotImplemented = 501,
|
|
BadGateway = 502,
|
|
ServiceUnavailable = 503,
|
|
GatewayTimeout = 504,
|
|
HTTPVersionNotSupported = 505,
|
|
VariantAlsoNegotiates = 506,
|
|
NotExtended = 510,
|
|
NetworkAuthenticationRequired = 511,
|
|
NetworkReadTimeoutError = 598,
|
|
NetworkConnectTimeoutError = 599,
|
|
};
|
|
|
|
Http();
|
|
Http(Http&&)=default;
|
|
Http(const Http&)= default;
|
|
Http &operator=(const Http &)=default;
|
|
Http &operator=(Http &&)=default;
|
|
virtual ~Http() = default;
|
|
|
|
|
|
/*!
|
|
* Parse a raw request or response from a string
|
|
* into the object.
|
|
*
|
|
* @param data The request/response to parse
|
|
* @param datasz The length of data in bytes
|
|
* @return NotEnoughData if parse needs to be called again. Success on success, other on error.
|
|
*/
|
|
virtual fr::Socket::Status parse(const char *data, size_t datasz)=0;
|
|
|
|
/*!
|
|
* Constructs a HTTP request/response to send.
|
|
*
|
|
* @param host The host that we're connected to.
|
|
* @return The HTTP request
|
|
*/
|
|
virtual std::string construct(const std::string &host) const=0;
|
|
|
|
/*!
|
|
* Gets the request type (post, get etc)
|
|
*
|
|
* @return The request type
|
|
*/
|
|
RequestType get_type() const;
|
|
|
|
/*!
|
|
* Sets the request type (post, get etc)
|
|
*
|
|
* @param type The type of request to set it to
|
|
*/
|
|
void set_type(RequestType type);
|
|
|
|
/*!
|
|
* Sets the request body
|
|
*
|
|
* @param body_ The request body
|
|
*/
|
|
void set_body(const std::string &body_);
|
|
|
|
/*!
|
|
* Returns a reference to a get variable.
|
|
* Can be used to either set/get the value.
|
|
* If the key does not exist, then it will be
|
|
* created and an empty value will be returned.
|
|
*
|
|
* @param key The name of the GET variable
|
|
* @return A reference to the GET variable
|
|
*/
|
|
std::string &get(std::string key);
|
|
|
|
/*!
|
|
* Returns a reference to a POST variable.
|
|
* Can be used to either set/get the value.
|
|
* If the key does not exist, then it will be
|
|
* created and an empty value will be returned.
|
|
*
|
|
* @param key The name of the POST variable
|
|
* @return A reference to the POST variable
|
|
*/
|
|
std::string &post(std::string key);
|
|
|
|
/*!
|
|
* Returns a reference to a header.
|
|
* Can be used to either set/get the value.
|
|
* If the key does not exist, then it will be
|
|
* created and an empty value will be returned.
|
|
*
|
|
* @param key The name of the header
|
|
* @return A reference to the header
|
|
*/
|
|
std::string &header(std::string key);
|
|
|
|
|
|
/*!
|
|
* Checks to see if a given GET variable exists
|
|
*
|
|
* @param key The name of the GET variable
|
|
* @return True if it does. False otherwise.
|
|
*/
|
|
bool get_exists(std::string key) const;
|
|
|
|
/*!
|
|
* Checks to see if a given POST variable exists
|
|
*
|
|
* @param key The name of the POST variable
|
|
* @return True if it does. False otherwise.
|
|
*/
|
|
bool post_exists(std::string key) const;
|
|
|
|
/*!
|
|
* Checks to see if a given header exists.
|
|
*
|
|
* @param key The name of the header
|
|
* @return True if it does. False otherwise.
|
|
*/
|
|
bool header_exists(std::string key) const;
|
|
|
|
/*!
|
|
* Returns the requested URI
|
|
*
|
|
* @return The URI
|
|
*/
|
|
const std::string &get_uri() const;
|
|
|
|
/*!
|
|
* Sets the response status (400, 200, etc)
|
|
*
|
|
* @param status The status to send back
|
|
*/
|
|
void set_status(RequestStatus status);
|
|
|
|
/*!
|
|
* Gets the reponse status
|
|
*
|
|
* @return The status
|
|
*/
|
|
RequestStatus get_status() const;
|
|
|
|
/*!
|
|
* Sets the request URI.
|
|
*
|
|
* @param str What to set the URI to.
|
|
*/
|
|
void set_uri(const std::string &str);
|
|
|
|
/*!
|
|
* Gets the body of the HTTP request
|
|
*
|
|
* @return The request body
|
|
*/
|
|
const std::string &get_body() const;
|
|
|
|
/*!
|
|
* URL Encodes a given string
|
|
*
|
|
* @param str The string to URL encode
|
|
* @return The URL encoded string
|
|
*/
|
|
static std::string url_encode(const std::string &str);
|
|
|
|
/*!
|
|
* Decodes a URL encoded string.
|
|
*
|
|
* @param str The string to decode
|
|
* @return The decoded string
|
|
*/
|
|
static std::string url_decode(const std::string &str);
|
|
|
|
/*!
|
|
* Gets the mimetype of a given filename, or file extention.
|
|
*
|
|
* @param filename The filename, or file extention to find the mime type of
|
|
* @return The mime type. Returns 'application/octet-stream' if it couldn't be found.
|
|
*/
|
|
const static std::string &get_mimetype(const std::string &filename);
|
|
|
|
protected:
|
|
/*!
|
|
* Splits a string by new line. Ignores escaped \n's
|
|
*
|
|
* @return The split string
|
|
*/
|
|
std::vector<std::string> split_string(const std::string &str);
|
|
|
|
/*!
|
|
* Converts a 'RequestType' enum value to
|
|
* a printable string.
|
|
*
|
|
* @param type The RequestType to convert
|
|
* @return The printable version of the enum value
|
|
*/
|
|
std::string request_type_to_string(RequestType type) const;
|
|
|
|
/*!
|
|
* Converts hexadecimal to an integer.
|
|
*
|
|
* @param hex The hex value to convert
|
|
* @return The decimal equivilent of the hexadecimal value.
|
|
*/
|
|
static inline int dectohex(const std::string &hex)
|
|
{
|
|
return (int)strtol(&hex[0], nullptr, 16);
|
|
}
|
|
|
|
/*!
|
|
* Converts a parameter list to a vector pair.
|
|
* i.e: ?bob=10&fish=hey
|
|
* to: <bob, 10>, <fish, hey>
|
|
*
|
|
* @param str The string to parse
|
|
* @return The vector containing the results pairs
|
|
*/
|
|
std::vector<std::pair<std::string, std::string>> parse_argument_list(const std::string &str);
|
|
|
|
/*!
|
|
* Parses a header line in a HTTP request/response
|
|
*
|
|
* @param str The header. E.g: header: value
|
|
*/
|
|
void parse_header_line(const std::string &str);
|
|
|
|
/*!
|
|
* Overridable send, to allow
|
|
* custom types to be directly sent through
|
|
* sockets.
|
|
*
|
|
* @param socket The socket to send through
|
|
* @return Status indicating if the send succeeded or not.
|
|
*/
|
|
virtual Socket::Status send(Socket *socket) override;
|
|
|
|
/*!
|
|
* Overrideable receive, to allow
|
|
* custom types to be directly received through
|
|
* sockets.
|
|
*
|
|
* @param socket The socket to send through
|
|
* @return Status indicating if the send succeeded or not.
|
|
*/
|
|
virtual Socket::Status receive(Socket *socket) override;
|
|
|
|
//Other request info
|
|
std::unordered_map<std::string, std::string> header_data;
|
|
std::unordered_map<std::string, std::string> post_data;
|
|
std::unordered_map<std::string, std::string> get_data;
|
|
std::string body;
|
|
RequestType request_type;
|
|
std::string uri;
|
|
RequestStatus status;
|
|
|
|
private:
|
|
|
|
};
|
|
}
|
|
|
|
|
|
#endif //FRNETLIB_HTTP_H
|