#pragma once
#include <future>
+
#include "error.h"
#include "method.h"
#include "request.h"
#include "response.h"
+#include "listener.h"
#define ERR(error) std::unexpected(error)
#define NEW_LINE std::string_view("\r\n")
namespace http {
- std::expected<Response, Error> send(Method, const RequestOpts& req);
+ std::expected<Response, Error> send(Method, const Request& req);
std::expected<int8_t, Error> connect(const std::string_view& domain_name, const uint16_t port = 80);
- std::string build_request(Method method, const RequestOpts &req);
+ std::string build_request(Method method, const Request &req);
std::expected<std::string, Error> read_raw_response(const int8_t socketfd);
namespace async {
- std::future<std::expected<Response, Error>> send(Method method, const RequestOpts &req);
+ std::future<std::expected<Response, Error>> send(Method method, const Request &req);
}
} // namespace http
--- /dev/null
+#include "listener.h"
+
+namespace http {
+ std::expected<Listener, Error> Listener::create_on_local(uint16_t port) {
+ Listener server;
+
+ ++port;
+
+ return server;
+ }
+
+
+ void Listener::serve() {
+
+ }
+} // namespace http
--- /dev/null
+#pragma once
+
+#include <cstdint>
+#include <expected>
+#include <functional>
+#include <string>
+#include <unordered_map>
+
+#include "error.h"
+#include "request.h"
+
+namespace http {
+ struct Listener {
+ public:
+ ~Listener() {}
+
+ static std::expected<Listener, Error> create_on_local(uint16_t port);
+ static std::expected<Listener, Error> create_on_lan(uint16_t port);
+
+ void serve();
+ void serve_async();
+
+ private:
+ Listener() : routes({}) {}
+
+ public:
+ std::unordered_map<std::string, std::function<void(const Request &)>> routes;
+ };
+} // namespace http
#include "http.h"
int main() {
- auto resp1 = http::async::send(http::Method::GET, {.domain_name = "example.com",
- .version = {1, 1}});
+ auto server = http::Listener::create_on_local(8800);
+ server.value().serve();
- auto resp = resp1.get();
- if (!resp.has_value()) {
- switch (resp.error()) {
- case http::Error::SocketCreation: {
- std::cout << "Socket creation" << std::endl;
- } break;
- case http::Error::SocketConnection: {
- std::cout << "Socket connection" << std::endl;
- } break;
- case http::Error::DNSResolution: {
- std::cout << "DNS resolution" << std::endl;
- } break;
- case http::Error::ServerNotFound: {
- std::cout << "Server not found" << std::endl;
- } break;
- case http::Error::InvalidRead: {
- std::cout << "Invalid read" << std::endl;
- } break;
- case http::Error::InvalidResponse: {
- std::cout << "Invalid response" << std::endl;
- } break;
- case http::Error::InvalidResponseHTTPVersion: {
- std::cout << "Invalid response http version" << std::endl;
- } break;
- case http::Error::InvalidResponseStatusCode: {
- std::cout << "Invalid response status code" << std::endl;
- } break;
- }
- } else {
- std::cout << resp.value() << std::endl;
- }
+ server.value().routes["prova"] = [](const http::Request &req) { std::cout << req << std::endl; };
+
+ http::Request request;
+ server.value().routes["prova"](request);
}
--- /dev/null
+#include "request.h"
+
+#include <iomanip>
+
+std::ostream &operator<<(std::ostream &os, const http::Request &req) {
+ return os << "Request { domain: " << std::quoted(req.domain_name) << ", port: " << req.port
+ << ", host: " << std::quoted(req.host) << ", query: " << std::quoted(req.query)
+ << ", accept: " << std::quoted(req.accept) << ", body: " << std::quoted(req.body)
+ << " }";
+}
#include <cstdint>
#include <string_view>
+#include <ostream>
namespace http {
struct http_version {
uint8_t minor = 1;
};
- struct RequestOpts {
+ struct Request {
uint16_t port = 80;
std::string_view domain_name;
std::string_view host = domain_name;
http_version version = {.major = 1, .minor = 1};
};
} // namespace http
+
+std::ostream &operator<<(std::ostream &os, const http::Request &req);
return remote_socketfd;
}
- std::expected<Response, Error> send(Method method, const RequestOpts &req) {
+ std::expected<Response, Error> send(Method method, const Request &req) {
auto maybe_socketfd = connect(req.domain_name, req.port);
if (!maybe_socketfd.has_value()) {
return Response::build(maybe_response.value());
}
- std::string build_request(Method method, const RequestOpts &req) {
+ std::string build_request(Method method, const Request &req) {
std::stringstream ss;
ss << method << " " << req.query << " HTTP/" << (int)req.version.major << "."
<< (int)req.version.minor << NEW_LINE;
}
namespace async {
- std::future<std::expected<Response, Error>> send(Method method, const RequestOpts &req) {
+ std::future<std::expected<Response, Error>> send(Method method, const Request &req) {
return std::async(::http::send, method, req);
}
} // namespace async