From f549f936089b2c24862de7cb48dec733f6d6d326 Mon Sep 17 00:00:00 2001 From: nekobit Date: Sun, 23 Oct 2022 05:39:42 +0000 Subject: [PATCH] Mime stuff FossilOrigin-Name: 27b3deb5ffb4cde38e07cbe295572add5a2fe709bb6a1f376effb8ca1f6d60a6 --- src/http/microhttpd_server.cpp | 29 ++++++++-------- src/http/mime.cpp | 41 +++++++++++++++++++---- src/http/mime.h | 49 ++++++++++++++++++++++++---- src/http/request.cpp | 5 +-- src/http/request.h | 16 +++++++-- src/http/response.cpp | 4 +-- src/http/response.h | 7 ++-- src/protocol/masto-api/mastoapi.cpp | 1 - src/protocol/webfinger/webfinger.cpp | 7 +++- 9 files changed, 121 insertions(+), 38 deletions(-) diff --git a/src/http/microhttpd_server.cpp b/src/http/microhttpd_server.cpp index febdce7..79c5889 100644 --- a/src/http/microhttpd_server.cpp +++ b/src/http/microhttpd_server.cpp @@ -16,10 +16,13 @@ * along with this program. If not, see . */ -#include "microhttpd_server.h" -#include "http/request.h" #include #include +#include +#include +#include "microhttpd_server.h" +#include "http/mime.h" +#include "http/request.h" #include #include "http/response.h" @@ -29,18 +32,14 @@ namespace { HTTP::Request::Type str_to_method(std::string method) { - if (method == "GET") - return HTTP::Request::Type::GET; - else if (method == "POST") - return HTTP::Request::Type::POST; - else if (method == "PUT") - return HTTP::Request::Type::PUT; - else if (method == "DELETE") - return HTTP::Request::Type::DELETE; - else if (method == "PATCH") - return HTTP::Request::Type::PATCH; - else - return HTTP::Request::Type::UNSUPPORTED; + // i.e. if (method == "GET") return HTTP::Request::Type::GET; +#define IF_METHOD(val) if (method == #val) return HTTP::Request::Type::val + IF_METHOD(GET); + IF_METHOD(POST); + IF_METHOD(PUT); + IF_METHOD(DELETE); + IF_METHOD(PATCH); + else return HTTP::Request::Type::OTHER; } // Iterator function for POST, GET, etc. @@ -88,7 +87,7 @@ namespace (void*)(resp->data.data()), MHD_RESPMEM_MUST_COPY); - MHD_add_response_header(response, "Content-Type", resp->mimetype); + MHD_add_response_header(response, "Content-Type", MIME::mime_to_str(resp->mimetype).begin()); // HTTP::Code works for MHD already since it's just int's that represent the HTTP response codes ret = MHD_queue_response(conn, resp->code, response); diff --git a/src/http/mime.cpp b/src/http/mime.cpp index c08e196..b67f388 100644 --- a/src/http/mime.cpp +++ b/src/http/mime.cpp @@ -18,9 +18,38 @@ #include "http/mime.h" -const char* HTTP::MIME::HTML = "text/html"; -const char* HTTP::MIME::CSS = "text/css"; -const char* HTTP::MIME::JSON = "application/json"; -const char* HTTP::MIME::ACTIVITY_JSON = "application/activity+json"; -const char* HTTP::MIME::LD_JSON = "application/ld+json"; -const char* HTTP::MIME::XML = "application/xml"; +std::string_view HTTP::MIME::HTML_STR = "text/html"; +std::string_view HTTP::MIME::CSS_STR = "text/css"; +std::string_view HTTP::MIME::JSON_STR = "application/json"; +std::string_view HTTP::MIME::ACTIVITY_JSON_STR = "application/activity+json"; +std::string_view HTTP::MIME::LD_JSON_STR = "application/ld+json"; +std::string_view HTTP::MIME::XML_STR = "application/xml"; + +HTTP::MIME::mime_t HTTP::MIME::str_to_mime(HTTP::MIME::mime_str_t mime) +{ + // i.e. if (mime == HTTP::MIME::MIME_HTML_STR) return HTTP::MIME::MIME_HTML; +#define IF_MIME(val) if (mime == HTTP::MIME::val ## _STR) return HTTP::MIME::val + IF_MIME(HTML); + IF_MIME(CSS); + IF_MIME(JSON); + IF_MIME(ACTIVITY_JSON); + IF_MIME(LD_JSON); + IF_MIME(XML); + else + return HTTP::MIME::OTHER; +} + +// Opposite of the last function +HTTP::MIME::mime_str_t HTTP::MIME::mime_to_str(HTTP::MIME::mime_t mime) +{ + // i.e. if (mime == HTTP::MIME::MIME_HTML) return HTTP::MIME::MIME_HTML_STR; +#define IF_STR(val) if (mime == HTTP::MIME::val) return HTTP::MIME::val ## _STR + IF_STR(HTML); + IF_STR(CSS); + IF_STR(JSON); + IF_STR(ACTIVITY_JSON); + IF_STR(LD_JSON); + IF_STR(XML); + else + return HTTP::MIME::JSON_STR; +} diff --git a/src/http/mime.h b/src/http/mime.h index ba2766d..6f565a3 100644 --- a/src/http/mime.h +++ b/src/http/mime.h @@ -18,15 +18,52 @@ #pragma once +#include +#include +#include + namespace HTTP { namespace MIME { - extern const char* HTML; // = "text/html" - extern const char* CSS; // = "text/css" - extern const char* JSON; // = "application/json" - extern const char* ACTIVITY_JSON; // = "application/activity+json" - extern const char* LD_JSON; // = "application/ld+json" - extern const char* XML; // = "application/xml" + enum Mimetypes : uint8_t + { + HTML = 1<<0, + CSS = 1<<1, + JSON = 1<<2, + ACTIVITY_JSON = 1<<3, + LD_JSON = 1<<4, + XML = 1<<5, + OTHER = 1<<6, + ANY = 0xFF, + }; + + constexpr uint8_t MIME_JSON_TYPE = JSON | ACTIVITY_JSON | LD_JSON; + + using mime_t = enum Mimetypes; + using mime_str_t = std::string_view; + + extern std::string_view HTML_STR; // = "text/html" + extern std::string_view CSS_STR; // = "text/css" + extern std::string_view JSON_STR; // = "application/json" + extern std::string_view ACTIVITY_JSON_STR; // = "application/activity+json" + extern std::string_view LD_JSON_STR; // = "application/ld+json" + extern std::string_view XML_STR; // = "application/xml" + + /** + * @brief Converts Mime string to Mime enumeration type + * @example "text/html" returns HTTP::MIME::HTML + * @param mime Mime string + * @return Converted Mime enum type + */ + MIME::mime_t str_to_mime(MIME::mime_str_t mime); + + /** + * @brief Converts Mime enumeration type to Mime string + * @example HTTP::MIME::JSON returns "application/json" + * @param mime Mime enumeration type + * @return Converted Mime string + */ + MIME::mime_str_t mime_to_str(MIME::mime_t mime); } } diff --git a/src/http/request.cpp b/src/http/request.cpp index 91a1014..253c620 100644 --- a/src/http/request.cpp +++ b/src/http/request.cpp @@ -21,7 +21,7 @@ using namespace HTTP; -Request::Request(Type type, const std::string url) +Request::Request(Type type, const std::string url, unsigned mimetypes /* = HTTP::MIME::ANY */) : type{type}, url{std::move(url)} {} @@ -122,6 +122,7 @@ std::string_view Request::get_type_string() const noexcept case Request::Type::PUT: return "PUT"; case Request::Type::DELETE: return "DELETE"; case Request::Type::PATCH: return "PATCH"; + default: + return "???"; } - return "???"; } diff --git a/src/http/request.h b/src/http/request.h index e7b973f..48221ee 100644 --- a/src/http/request.h +++ b/src/http/request.h @@ -26,6 +26,7 @@ #include #include #include "response.h" +#include "mime.h" namespace HTTP { @@ -64,7 +65,7 @@ namespace HTTP PUT, DELETE, PATCH, - UNSUPPORTED, + OTHER, }; /** @@ -72,8 +73,14 @@ namespace HTTP * * General usage is to compare against another request (with a function), * with call_if_match + * + * @param type Type of request, @see Request::Type + * @param req Request match parameter + * @param mimetypes Bitwise OR set of Mimetypes + * + * @example Request(Request::GET, "/api/v1/user/:", MIME::ACTIVITY_JSON | MIME::XML) */ - Request(Type type, std::string req); + Request(Type type, std::string req, unsigned mimetypes = HTTP::MIME::ANY); ~Request() = default; /** @@ -111,11 +118,16 @@ namespace HTTP std::string_view get_type_string() const noexcept; /** @remark May be a path */ inline const std::string& get_url() const noexcept { return url; } + /** @remark Assuming this wasn't a propagated mimetype (OR mime) */ + inline HTTP::MIME::Mimetypes get_mime() const noexcept + { return static_cast(mimetypes); } KeyStrVarMap get; private: Type type; /** @remark Used as a plain old path too. */ std::string url; + /** @see mime.h */ + unsigned mimetypes; }; } diff --git a/src/http/response.cpp b/src/http/response.cpp index acb7061..94d6b1b 100644 --- a/src/http/response.cpp +++ b/src/http/response.cpp @@ -23,7 +23,7 @@ using namespace HTTP; Response::Response(std::vector data, - const char* mimetype, + MIME::mime_t mimetype, HTTP::Code code /* = HTTP::Code::OK*/) : data{std::move(data)}, mimetype{mimetype}, @@ -35,7 +35,7 @@ Response::Response(const std::string& str) {} Response::Response(const std::string& str, - const char* mimetype, + MIME::mime_t mimetype, HTTP::Code code /* = HTTP::Code::OK*/) : data{str.begin(), str.end()}, mimetype{mimetype}, diff --git a/src/http/response.h b/src/http/response.h index 1e365af..2abf1c9 100644 --- a/src/http/response.h +++ b/src/http/response.h @@ -22,6 +22,7 @@ #include #include #include +#include "mime.h" #include "responsecode.h" #include "type/stringvariant.h" @@ -32,18 +33,18 @@ namespace HTTP public: /** Initialize from vector of unsigned chars */ Response(std::vector data, - const char* mimetype, + MIME::mime_t mimetype, HTTP::Code code = HTTP::Code::OK); /** Initialize from string */ Response(const std::string& str); Response(const std::string& str, - const char* mimetype, + MIME::mime_t mimetype, HTTP::Code code = HTTP::Code::OK); ~Response() = default; const std::vector data; - const char* mimetype; + MIME::mime_t mimetype; /// @see responsecode.h HTTP::Code code; }; diff --git a/src/protocol/masto-api/mastoapi.cpp b/src/protocol/masto-api/mastoapi.cpp index 31c34ae..f64aa96 100644 --- a/src/protocol/masto-api/mastoapi.cpp +++ b/src/protocol/masto-api/mastoapi.cpp @@ -34,7 +34,6 @@ using namespace Protocol; - HTTP::Response Route::masto_api(std::any& args, const HTTP::Request& req, const HTTP::RequestArgs_t& arg) diff --git a/src/protocol/webfinger/webfinger.cpp b/src/protocol/webfinger/webfinger.cpp index d545062..6f57557 100644 --- a/src/protocol/webfinger/webfinger.cpp +++ b/src/protocol/webfinger/webfinger.cpp @@ -135,5 +135,10 @@ HTTP::Response Route::webfinger(std::any& args, const HTTP::Request& req, const void Webfinger::init_webfinger(HTTP::Server* server) { - server->add_route({{HTTP::Request::Type::GET, "/.well-known/webfinger"}, Route::webfinger}); + server->add_route({ + { + HTTP::Request::Type::GET, + "/.well-known/webfinger", + HTTP::MIME::JSON, + }, Route::webfinger}); }