Mime stuff

FossilOrigin-Name: 27b3deb5ffb4cde38e07cbe295572add5a2fe709bb6a1f376effb8ca1f6d60a6
This commit is contained in:
nekobit 2022-10-23 05:39:42 +00:00
parent f00029c5d1
commit f549f93608
9 changed files with 121 additions and 38 deletions

View file

@ -16,10 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "microhttpd_server.h"
#include "http/request.h"
#include <cstdint>
#include <cstring>
#include <array>
#include <utility>
#include "microhttpd_server.h"
#include "http/mime.h"
#include "http/request.h"
#include <microhttpd.h>
#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);

View file

@ -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;
}

View file

@ -18,15 +18,52 @@
#pragma once
#include <cstdint>
#include <string>
#include <string_view>
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);
}
}

View file

@ -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 "???";
}

View file

@ -26,6 +26,7 @@
#include <vector>
#include <unordered_map>
#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<HTTP::MIME::Mimetypes>(mimetypes); }
KeyStrVarMap get;
private:
Type type;
/** @remark Used as a plain old path too. */
std::string url;
/** @see mime.h */
unsigned mimetypes;
};
}

View file

@ -23,7 +23,7 @@
using namespace HTTP;
Response::Response(std::vector<unsigned char> 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},

View file

@ -22,6 +22,7 @@
#include <vector>
#include <string_view>
#include <map>
#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<unsigned char> 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<unsigned char> data;
const char* mimetype;
MIME::mime_t mimetype;
/// @see responsecode.h
HTTP::Code code;
};

View file

@ -34,7 +34,6 @@
using namespace Protocol;
HTTP::Response Route::masto_api(std::any& args,
const HTTP::Request& req,
const HTTP::RequestArgs_t& arg)

View file

@ -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});
}