Cleaned up HTTP socket/request code.
This commit is contained in:
parent
fdee42e300
commit
98897dec02
@ -4,5 +4,5 @@ project(frnetlib)
|
||||
include_directories(include)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -m64 -fPIC -pthread")
|
||||
|
||||
set(SOURCE_FILES main.cpp src/TcpSocket.cpp include/TcpSocket.h src/TcpListener.cpp include/TcpListener.h src/Socket.cpp include/Socket.h src/Packet.cpp include/Packet.h include/NetworkEncoding.h src/SocketSelector.cpp include/SocketSelector.h src/HttpSocket.cpp include/HttpSocket.h src/HttpRequest.cpp include/HttpRequest.h src/HttpResponse.cpp include/HttpResponse.h)
|
||||
set(SOURCE_FILES main.cpp src/TcpSocket.cpp include/TcpSocket.h src/TcpListener.cpp include/TcpListener.h src/Socket.cpp include/Socket.h src/Packet.cpp include/Packet.h include/NetworkEncoding.h src/SocketSelector.cpp include/SocketSelector.h src/HttpSocket.cpp include/HttpSocket.h src/HttpRequest.cpp include/HttpRequest.h src/HttpResponse.cpp include/HttpResponse.h src/Http.cpp include/Http.h)
|
||||
add_executable(frnetlib ${SOURCE_FILES})
|
||||
178
include/Http.h
Normal file
178
include/Http.h
Normal file
@ -0,0 +1,178 @@
|
||||
//
|
||||
// Created by fred on 11/12/16.
|
||||
//
|
||||
|
||||
#ifndef FRNETLIB_HTTP_H
|
||||
#define FRNETLIB_HTTP_H
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace fr
|
||||
{
|
||||
class Http
|
||||
{
|
||||
public:
|
||||
enum RequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
Get = 1,
|
||||
Post = 2,
|
||||
RequestTypeCount = 3,
|
||||
};
|
||||
enum RequestStatus
|
||||
{
|
||||
Ok = 200,
|
||||
BadRequest = 400,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
ImATeapot = 418,
|
||||
InternalServerError = 500,
|
||||
};
|
||||
|
||||
Http();
|
||||
|
||||
/*!
|
||||
* Parse a raw request or response from a string
|
||||
* into the object.
|
||||
*
|
||||
* @param data The request/response to parse
|
||||
*/
|
||||
virtual void parse(const std::string &data)=0;
|
||||
|
||||
/*!
|
||||
* Constructs a HTTP request/response to send.
|
||||
*
|
||||
* @return The HTTP request
|
||||
*/
|
||||
virtual std::string construct() 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);
|
||||
|
||||
/*!
|
||||
* Access a header
|
||||
*
|
||||
* @param key The name of the header data to access/create
|
||||
* @return The header data.
|
||||
*/
|
||||
std::string &operator[](const std::string &key);
|
||||
|
||||
/*!
|
||||
* Sets the request body
|
||||
*
|
||||
* @param body_ The request body
|
||||
*/
|
||||
void set_body(const std::string &body_);
|
||||
|
||||
/*!
|
||||
* Clear current request data
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/*!
|
||||
* 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(const 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(const 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(const 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(const 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();
|
||||
|
||||
/*!
|
||||
* 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;
|
||||
|
||||
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);
|
||||
|
||||
std::string request_type_to_string(RequestType type) const;
|
||||
|
||||
//Other request info
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
std::unordered_map<std::string, std::string> get_variables;
|
||||
std::string body;
|
||||
RequestType request_type;
|
||||
std::string uri;
|
||||
RequestStatus status;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //FRNETLIB_HTTP_H
|
||||
@ -8,185 +8,30 @@
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "TcpSocket.h"
|
||||
#include "Http.h"
|
||||
|
||||
namespace fr
|
||||
{
|
||||
class HttpRequest
|
||||
class HttpRequest : public Http
|
||||
{
|
||||
public:
|
||||
enum RequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
Get = 1,
|
||||
Post = 2,
|
||||
RequestTypeCount = 3,
|
||||
};
|
||||
enum RequestStatus
|
||||
{
|
||||
Ok = 200,
|
||||
BadRequest = 400,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
ImATeapot = 418,
|
||||
InternalServerError = 500,
|
||||
};
|
||||
|
||||
//Constructors
|
||||
HttpRequest();
|
||||
HttpRequest(HttpRequest &&other)=default;
|
||||
HttpRequest() = default;
|
||||
HttpRequest(HttpRequest &&other) = default;
|
||||
|
||||
/*!
|
||||
* Parses a browser request
|
||||
* Parse a HTTP response.
|
||||
*
|
||||
* @param request_data The request data itself
|
||||
* @param data The HTTP response to parse
|
||||
*/
|
||||
void parse_request(const std::string &request_data);
|
||||
void parse(const std::string &data) override;
|
||||
|
||||
/*!
|
||||
* Parses a browser response
|
||||
* Constructs a Http Request, ready to send.
|
||||
*
|
||||
* @param request_data The response data itself
|
||||
* @return The constructed HTTP request.
|
||||
*/
|
||||
void parse_response(const std::string &response_data);
|
||||
|
||||
/*!
|
||||
* 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);
|
||||
|
||||
/*!
|
||||
* Access a header
|
||||
*
|
||||
* @param key The name of the header data to access/create
|
||||
* @return The header data.
|
||||
*/
|
||||
std::string &operator[](const std::string &key);
|
||||
|
||||
/*!
|
||||
* Constructs a HTTP web request from the object.
|
||||
*
|
||||
* @return The HTTP request
|
||||
*/
|
||||
std::string construct_request() const;
|
||||
|
||||
/*!
|
||||
* Constructs a HTTP web response from the object.
|
||||
*
|
||||
* @return The HTTP response.
|
||||
*/
|
||||
std::string construct_response() const;
|
||||
|
||||
/*!
|
||||
* Sets the request body
|
||||
*
|
||||
* @param body_ The request body
|
||||
*/
|
||||
void set_body(const std::string &body_);
|
||||
|
||||
/*!
|
||||
* Clear current request data
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/*!
|
||||
* 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(const 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(const 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(const 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(const 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();
|
||||
|
||||
/*!
|
||||
* 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;
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Splits a string by new line. Ignores escaped \n's
|
||||
*
|
||||
* @return The split string
|
||||
*/
|
||||
std::vector<std::string> split_string(const std::string &str);
|
||||
|
||||
std::string request_type_to_string(RequestType type) const;
|
||||
|
||||
//Other request info
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
std::unordered_map<std::string, std::string> get_variables;
|
||||
std::string body;
|
||||
RequestType request_type;
|
||||
std::string uri;
|
||||
RequestStatus status;
|
||||
std::string construct() const override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -5,11 +5,34 @@
|
||||
#ifndef FRNETLIB_HTTPRESPONSE_H
|
||||
#define FRNETLIB_HTTPRESPONSE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "Http.h"
|
||||
|
||||
class HttpResponse
|
||||
namespace fr
|
||||
{
|
||||
class HttpResponse : public Http
|
||||
{
|
||||
public:
|
||||
//Constructors
|
||||
HttpResponse() = default;
|
||||
HttpResponse(HttpResponse &&other) = default;
|
||||
|
||||
};
|
||||
/*!
|
||||
* Parse a HTTP response.
|
||||
*
|
||||
* @param data The HTTP response to parse
|
||||
*/
|
||||
void parse(const std::string &data) override;
|
||||
|
||||
/*!
|
||||
* Constructs a HttpResponse, ready to send.
|
||||
*
|
||||
* @return The constructed HTTP response.
|
||||
*/
|
||||
std::string construct() const override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //FRNETLIB_HTTPRESPONSE_H
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define FRNETLIB_HTTPSOCKET_H
|
||||
|
||||
#include "TcpSocket.h"
|
||||
#include "HttpRequest.h"
|
||||
#include "Http.h"
|
||||
|
||||
namespace fr
|
||||
{
|
||||
@ -14,20 +14,12 @@ namespace fr
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Sends a HTTP request to the connected socket.
|
||||
* Receives a HTTP request from the connected socket
|
||||
*
|
||||
* @param request The request to send
|
||||
* @param request Where to store the received request.
|
||||
* @return The status of the operation.
|
||||
*/
|
||||
Socket::Status receive_request(HttpRequest &request);
|
||||
|
||||
/*!
|
||||
* Sends a HTTP response to the connected socket.
|
||||
*
|
||||
* @param request The response to send
|
||||
* @return The status of the operation.
|
||||
*/
|
||||
Socket::Status receive_response(HttpRequest &response);
|
||||
Socket::Status receive(Http &request);
|
||||
|
||||
/*!
|
||||
* Sends a HTTP request to the connected socket.
|
||||
@ -35,15 +27,7 @@ namespace fr
|
||||
* @param request The HTTP request to send.
|
||||
* @return The status of the operation.
|
||||
*/
|
||||
Socket::Status send_request(const HttpRequest &request);
|
||||
|
||||
/*!
|
||||
* Sends a HTTP response to the connected socket.
|
||||
*
|
||||
* @param request The HTTP response to send.
|
||||
* @return The status of the operation.
|
||||
*/
|
||||
Socket::Status send_response(const HttpRequest &request);
|
||||
Socket::Status send(const Http &request);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
19
main.cpp
19
main.cpp
@ -6,7 +6,9 @@
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <HttpSocket.h>
|
||||
#include "HttpSocket.h"
|
||||
#include "HttpRequest.h"
|
||||
#include "HttpResponse.h"
|
||||
|
||||
void server()
|
||||
{
|
||||
@ -52,17 +54,17 @@ void server()
|
||||
{
|
||||
//This client has sent a HTTP request, so receive_request it
|
||||
fr::HttpRequest request;
|
||||
if((*iter)->receive_request(request) == fr::Socket::Success)
|
||||
if((*iter)->receive(request) == fr::Socket::Success)
|
||||
{
|
||||
//Print to the console what we've been requested for
|
||||
std::cout << "Requested: " << request.get_uri() << std::endl;
|
||||
|
||||
//Construct a response
|
||||
request.clear();
|
||||
request.set_body("<h1>Hello, World!</h1>");
|
||||
fr::HttpResponse response;
|
||||
response.set_body("<h1>Hello, World!</h1>");
|
||||
|
||||
//Send the response, and close the connection
|
||||
(*iter)->send_response(request);
|
||||
(*iter)->send(response);
|
||||
(*iter)->close();
|
||||
}
|
||||
else
|
||||
@ -93,13 +95,14 @@ void client()
|
||||
fr::HttpRequest request;
|
||||
request.get("name") = "fred";
|
||||
|
||||
if(socket.send_request(request) != fr::Socket::Success)
|
||||
if(socket.send(request) != fr::Socket::Success)
|
||||
std::cout << "Failed to send HTTP request to server!" << std::endl;
|
||||
|
||||
if(socket.receive_response(request) != fr::Socket::Success)
|
||||
fr::HttpResponse response;
|
||||
if(socket.receive(response) != fr::Socket::Success)
|
||||
std::cout << "Failed to receive HTTP response from the server!" << std::endl;
|
||||
|
||||
std::cout << "Got page body: " << request.get_body() << std::endl;
|
||||
std::cout << "Got page body: " << response.get_body() << std::endl;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
116
src/Http.cpp
Normal file
116
src/Http.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
//
|
||||
// Created by fred on 11/12/16.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "Http.h"
|
||||
|
||||
namespace fr
|
||||
{
|
||||
const static std::string request_type_strings[Http::RequestType::RequestTypeCount] = {"UNKNOWN", "GET", "POST"};
|
||||
|
||||
Http::Http()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
Http::RequestType Http::get_type() const
|
||||
{
|
||||
return request_type;
|
||||
}
|
||||
|
||||
std::string &Http::operator[](const std::string &key)
|
||||
{
|
||||
return headers[key];
|
||||
}
|
||||
|
||||
std::vector<std::string> Http::split_string(const std::string &str)
|
||||
{
|
||||
char last_character = '\0';
|
||||
size_t line_start = 0;
|
||||
std::vector<std::string> result;
|
||||
|
||||
for(size_t a = 0; a < str.size(); a++)
|
||||
{
|
||||
if(str[a] == '\n' && last_character != '\\')
|
||||
{
|
||||
result.emplace_back(str.substr(line_start, a - line_start));
|
||||
line_start = a + 1;
|
||||
}
|
||||
last_character = str[a];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Http::set_body(const std::string &body_)
|
||||
{
|
||||
body = body_;
|
||||
}
|
||||
|
||||
void Http::clear()
|
||||
{
|
||||
headers.clear();
|
||||
body.clear();
|
||||
get_variables.clear();
|
||||
uri = "/";
|
||||
status = Ok;
|
||||
request_type = Get;
|
||||
}
|
||||
|
||||
std::string &Http::get(const std::string &key)
|
||||
{
|
||||
return get_variables[key];
|
||||
}
|
||||
|
||||
std::string &Http::post(const std::string &key)
|
||||
{
|
||||
return headers[key];
|
||||
}
|
||||
|
||||
bool Http::get_exists(const std::string &key) const
|
||||
{
|
||||
return get_variables.find(key) != get_variables.end();
|
||||
}
|
||||
|
||||
bool Http::post_exists(const std::string &key) const
|
||||
{
|
||||
return headers.find(key) != headers.end();
|
||||
}
|
||||
|
||||
const std::string &Http::get_uri() const
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
void Http::set_status(RequestStatus status_)
|
||||
{
|
||||
status = status_;
|
||||
}
|
||||
|
||||
Http::RequestStatus Http::get_status()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
void Http::set_uri(const std::string &str)
|
||||
{
|
||||
uri = str;
|
||||
}
|
||||
|
||||
std::string Http::request_type_to_string(RequestType type) const
|
||||
{
|
||||
if(type >= RequestType::RequestTypeCount)
|
||||
return request_type_strings[0];
|
||||
return request_type_strings[type];
|
||||
}
|
||||
|
||||
void Http::set_type(Http::RequestType type)
|
||||
{
|
||||
request_type = type;
|
||||
}
|
||||
|
||||
const std::string &Http::get_body() const
|
||||
{
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@ -6,14 +6,7 @@
|
||||
|
||||
namespace fr
|
||||
{
|
||||
const static std::string request_type_strings[HttpRequest::RequestType::RequestTypeCount] = {"UNKNOWN", "GET", "POST"};
|
||||
|
||||
HttpRequest::HttpRequest()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void HttpRequest::parse_request(const std::string &request_data)
|
||||
void HttpRequest::parse(const std::string &request_data)
|
||||
{
|
||||
//Warning: Horrible string parsing code
|
||||
|
||||
@ -112,86 +105,7 @@ namespace fr
|
||||
return;
|
||||
}
|
||||
|
||||
void HttpRequest::parse_response(const std::string &response_data)
|
||||
{
|
||||
//Warning: Horrible string parsing code
|
||||
std::cout << "Parsing response: " << std::endl << response_data << std::endl;
|
||||
//Clear old headers/data
|
||||
clear();
|
||||
|
||||
//Make sure there's actual request data to read
|
||||
if(response_data.empty())
|
||||
return;
|
||||
|
||||
//Split by new lines
|
||||
std::vector<std::string> lines = split_string(response_data);
|
||||
if(lines.empty())
|
||||
return;
|
||||
|
||||
//Extract request get_type
|
||||
if(lines[0].find("GET") != std::string::npos)
|
||||
request_type = RequestType::Get;
|
||||
else if(lines[0].find("POST") != std::string::npos)
|
||||
request_type = RequestType::Post;
|
||||
else
|
||||
request_type = RequestType::Unknown;
|
||||
|
||||
//Extract headers
|
||||
size_t a;
|
||||
for(a = 1; a < lines.size(); a++)
|
||||
{
|
||||
//New line indicates headers have ended
|
||||
if(lines[a].empty() || lines[a].size() <= 2)
|
||||
break;
|
||||
|
||||
//Find the colon separating the header name and header data
|
||||
auto colon_iter = lines[a].find(":");
|
||||
if(colon_iter == std::string::npos)
|
||||
continue;
|
||||
|
||||
//Store the header
|
||||
std::string header_name = lines[a].substr(0, colon_iter);
|
||||
std::string header_content = lines[a].substr(colon_iter + 2, lines[a].size () - colon_iter - 3);
|
||||
headers.emplace(header_name, header_content);
|
||||
}
|
||||
|
||||
//Store request body
|
||||
for(; a < lines.size(); a++)
|
||||
{
|
||||
body += lines[a] + "\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HttpRequest::RequestType HttpRequest::get_type() const
|
||||
{
|
||||
return request_type;
|
||||
}
|
||||
|
||||
std::string &HttpRequest::operator[](const std::string &key)
|
||||
{
|
||||
return headers[key];
|
||||
}
|
||||
|
||||
std::vector<std::string> HttpRequest::split_string(const std::string &str)
|
||||
{
|
||||
char last_character = '\0';
|
||||
size_t line_start = 0;
|
||||
std::vector<std::string> result;
|
||||
|
||||
for(size_t a = 0; a < str.size(); a++)
|
||||
{
|
||||
if(str[a] == '\n' && last_character != '\\')
|
||||
{
|
||||
result.emplace_back(str.substr(line_start, a - line_start));
|
||||
line_start = a + 1;
|
||||
}
|
||||
last_character = str[a];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string HttpRequest::construct_request() const
|
||||
std::string HttpRequest::construct() const
|
||||
{
|
||||
//Add HTTP header
|
||||
std::string request = request_type_to_string(request_type) + " " + uri + " HTTP/1.1\r\n";
|
||||
@ -214,102 +128,4 @@ namespace fr
|
||||
request += body + "\r\n";
|
||||
return request;
|
||||
}
|
||||
|
||||
std::string HttpRequest::construct_response() const
|
||||
{
|
||||
//Add HTTP header
|
||||
std::string response = "HTTP/1.1 " + std::to_string(status) + " \r\n";
|
||||
|
||||
//Add the headers to the response
|
||||
for(const auto &header : headers)
|
||||
{
|
||||
std::string data = header.first + ": " + header.second + "\r\n";
|
||||
response += data;
|
||||
}
|
||||
|
||||
//Add in required headers if they're missing
|
||||
if(headers.find("Connection") == headers.end())
|
||||
response += "Connection: close\r\n";
|
||||
if(headers.find("Content-type") == headers.end())
|
||||
response += "Content-type: text/html\r\n";
|
||||
|
||||
//Add in space
|
||||
response += "\r\n";
|
||||
|
||||
//Add in the body
|
||||
response += body + "\r\n";
|
||||
return response;
|
||||
}
|
||||
|
||||
void HttpRequest::set_body(const std::string &body_)
|
||||
{
|
||||
body = body_;
|
||||
}
|
||||
|
||||
void HttpRequest::clear()
|
||||
{
|
||||
headers.clear();
|
||||
body.clear();
|
||||
get_variables.clear();
|
||||
uri = "/";
|
||||
status = Ok;
|
||||
request_type = Get;
|
||||
}
|
||||
|
||||
std::string &HttpRequest::get(const std::string &key)
|
||||
{
|
||||
return get_variables[key];
|
||||
}
|
||||
|
||||
std::string &HttpRequest::post(const std::string &key)
|
||||
{
|
||||
return headers[key];
|
||||
}
|
||||
|
||||
bool HttpRequest::get_exists(const std::string &key) const
|
||||
{
|
||||
return get_variables.find(key) != get_variables.end();
|
||||
}
|
||||
|
||||
bool HttpRequest::post_exists(const std::string &key) const
|
||||
{
|
||||
return headers.find(key) != headers.end();
|
||||
}
|
||||
|
||||
const std::string &HttpRequest::get_uri() const
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
void HttpRequest::set_status(RequestStatus status_)
|
||||
{
|
||||
status = status_;
|
||||
}
|
||||
|
||||
HttpRequest::RequestStatus HttpRequest::get_status()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
void HttpRequest::set_uri(const std::string &str)
|
||||
{
|
||||
uri = str;
|
||||
}
|
||||
|
||||
std::string HttpRequest::request_type_to_string(RequestType type) const
|
||||
{
|
||||
if(type >= RequestType::RequestTypeCount)
|
||||
return request_type_strings[0];
|
||||
return request_type_strings[type];
|
||||
}
|
||||
|
||||
void HttpRequest::set_type(HttpRequest::RequestType type)
|
||||
{
|
||||
request_type = type;
|
||||
}
|
||||
|
||||
const std::string &HttpRequest::get_body() const
|
||||
{
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@ -2,4 +2,83 @@
|
||||
// Created by fred on 10/12/16.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "HttpResponse.h"
|
||||
|
||||
namespace fr
|
||||
{
|
||||
void HttpResponse::parse(const std::string &response_data)
|
||||
{
|
||||
//Clear old headers/data
|
||||
clear();
|
||||
|
||||
//Make sure there's actual request data to read
|
||||
if(response_data.empty())
|
||||
return;
|
||||
|
||||
//Split by new lines
|
||||
std::vector<std::string> lines = split_string(response_data);
|
||||
if(lines.empty())
|
||||
return;
|
||||
|
||||
//Extract request get_type
|
||||
if(lines[0].find("GET") != std::string::npos)
|
||||
request_type = RequestType::Get;
|
||||
else if(lines[0].find("POST") != std::string::npos)
|
||||
request_type = RequestType::Post;
|
||||
else
|
||||
request_type = RequestType::Unknown;
|
||||
|
||||
//Extract headers
|
||||
size_t a;
|
||||
for(a = 1; a < lines.size(); a++)
|
||||
{
|
||||
//New line indicates headers have ended
|
||||
if(lines[a].empty() || lines[a].size() <= 2)
|
||||
break;
|
||||
|
||||
//Find the colon separating the header name and header data
|
||||
auto colon_iter = lines[a].find(":");
|
||||
if(colon_iter == std::string::npos)
|
||||
continue;
|
||||
|
||||
//Store the header
|
||||
std::string header_name = lines[a].substr(0, colon_iter);
|
||||
std::string header_content = lines[a].substr(colon_iter + 2, lines[a].size () - colon_iter - 3);
|
||||
headers.emplace(header_name, header_content);
|
||||
}
|
||||
|
||||
//Store request body
|
||||
for(; a < lines.size(); a++)
|
||||
{
|
||||
body += lines[a] + "\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string HttpResponse::construct() const
|
||||
{
|
||||
//Add HTTP header
|
||||
std::string response = "HTTP/1.1 " + std::to_string(status) + " \r\n";
|
||||
|
||||
//Add the headers to the response
|
||||
for(const auto &header : headers)
|
||||
{
|
||||
std::string data = header.first + ": " + header.second + "\r\n";
|
||||
response += data;
|
||||
}
|
||||
|
||||
//Add in required headers if they're missing
|
||||
if(headers.find("Connection") == headers.end())
|
||||
response += "Connection: close\r\n";
|
||||
if(headers.find("Content-type") == headers.end())
|
||||
response += "Content-type: text/html\r\n";
|
||||
|
||||
//Add in space
|
||||
response += "\r\n";
|
||||
|
||||
//Add in the body
|
||||
response += body + "\r\n";
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@ -2,12 +2,13 @@
|
||||
// Created by fred on 10/12/16.
|
||||
//
|
||||
|
||||
#include <HttpResponse.h>
|
||||
#include "HttpSocket.h"
|
||||
|
||||
namespace fr
|
||||
{
|
||||
|
||||
Socket::Status HttpSocket::receive_request(HttpRequest &request)
|
||||
Socket::Status HttpSocket::receive(Http &request)
|
||||
{
|
||||
//Create buffer to receive_request the request
|
||||
std::string buffer(2048, '\0');
|
||||
@ -20,38 +21,14 @@ namespace fr
|
||||
buffer.resize(received);
|
||||
|
||||
//Parse it
|
||||
request.parse_request(buffer);
|
||||
request.parse(buffer);
|
||||
|
||||
return Socket::Success;
|
||||
}
|
||||
|
||||
Socket::Status HttpSocket::receive_response(HttpRequest &response)
|
||||
Socket::Status HttpSocket::send(const Http &request)
|
||||
{
|
||||
//Create buffer to receive_request the response
|
||||
std::string buffer(2048, '\0');
|
||||
|
||||
//Receive the response
|
||||
size_t received;
|
||||
Socket::Status status = receive_raw(&buffer[0], buffer.size(), received);
|
||||
if(status != Socket::Success)
|
||||
return status;
|
||||
buffer.resize(received);
|
||||
|
||||
//Parse it
|
||||
response.parse_response(buffer);
|
||||
|
||||
return Socket::Success;
|
||||
}
|
||||
|
||||
Socket::Status HttpSocket::send_request(const HttpRequest &request)
|
||||
{
|
||||
std::string data = request.construct_request();
|
||||
return send_raw(&data[0], data.size());
|
||||
}
|
||||
|
||||
Socket::Status HttpSocket::send_response(const HttpRequest &request)
|
||||
{
|
||||
std::string data = request.construct_response();
|
||||
std::string data = request.construct();
|
||||
return send_raw(&data[0], data.size());
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user