#ifndef HTTP_HH #define HTTP_HH #include "unique_fd.hh" #include #include #include #include class Buffer; namespace logger { class Logger; } // namespace logger namespace looper { class Looper; } // namespace looper namespace cfg { class Config; } // namespace cfg namespace http { enum class StatusCode : uint16_t { kSwitchingProtocols = 101, kOK = 200, kNoContent = 204, kBadRequest = 400, kNotFound = 404, kMethodNotAllowed = 405, }; class OpenPort { public: virtual ~OpenPort() = default; protected: OpenPort() = default; OpenPort(OpenPort const&) = delete; OpenPort& operator=(OpenPort const&) = delete; }; // Returns nullptr in case of error, the error is written to logger. std::unique_ptr open_port(std::string_view host_port, logger::Logger& logger); class MimeType { public: virtual ~MimeType() = default; [[nodiscard]] virtual std::string_view type() const = 0; [[nodiscard]] virtual std::string_view subtype() const = 0; [[nodiscard]] virtual std::optional parameter( std::string_view name) const = 0; [[nodiscard]] virtual std::string const& string() const = 0; class Builder { public: virtual ~Builder() = default; virtual Builder& parameter(std::string_view name, std::string_view value) = 0; [[nodiscard]] virtual std::unique_ptr build() const = 0; [[nodiscard]] static std::unique_ptr create(std::string_view type, std::string_view subtype); protected: Builder() = default; Builder(Builder const&) = delete; Builder& operator=(Builder const&) = delete; }; // Short version of Builder::create(type, subtype).build() [[nodiscard]] static std::unique_ptr create(std::string_view type, std::string_view subtype); protected: MimeType() = default; MimeType(MimeType const&) = delete; MimeType& operator=(MimeType const&) = delete; }; class Request { public: virtual ~Request() = default; [[nodiscard]] virtual std::string_view method() const = 0; [[nodiscard]] virtual std::string_view path() const = 0; [[nodiscard]] virtual std::string_view body() const = 0; [[nodiscard]] virtual bool header_contains(std::string_view name, std::string_view value) const = 0; [[nodiscard]] virtual std::optional header_value( std::string_view name) const = 0; protected: Request() = default; Request(Request const&) = delete; Request& operator=(Request const&) = delete; }; class SocketReceiver { public: virtual ~SocketReceiver() = default; virtual void receive(unique_fd&& fd) = 0; protected: SocketReceiver() = default; }; class Response { public: virtual ~Response() = default; class Builder { public: virtual ~Builder() = default; virtual Builder& content(std::string_view content) = 0; virtual Builder& add_header(std::string_view name, std::string_view value) = 0; virtual Builder& take_over(SocketReceiver& receiver) = 0; [[nodiscard]] virtual std::unique_ptr build() const = 0; [[nodiscard]] static std::unique_ptr create(StatusCode status_code); protected: Builder() = default; Builder(Builder const&) = delete; Builder& operator=(Builder const&) = delete; }; // Short version of Builder::create(status_code).build() [[nodiscard]] static std::unique_ptr status(StatusCode status_code); // Short version of Builder::create(StatusCode::kOK).content(content) // .add_header("Content-Type", mime_type).build() [[nodiscard]] static std::unique_ptr content(std::string_view content, MimeType const& mime_type); // Returns true while there is more data to write. virtual bool write(Buffer& buffer) = 0; virtual SocketReceiver* socket_receiver() const = 0; protected: Response() = default; Response(Response const&) = delete; Response& operator=(Response const&) = delete; }; class Server { public: virtual ~Server() = default; class Delegate { public: virtual ~Delegate() = default; virtual std::unique_ptr handle(Request const& request) = 0; protected: Delegate() = default; }; protected: Server() = default; Server(Server const&) = delete; Server& operator=(Server const&) = delete; }; std::unique_ptr create_server(logger::Logger& logger, cfg::Config const& cfg, looper::Looper& looper, std::unique_ptr open_port, Server::Delegate& delegate); } // namespace http #endif // HTTP_HH