add http_client library, using libcurl

take out common http entities to http_common dir
This commit is contained in:
2024-11-23 17:54:22 +03:00
parent bf9ad65ff0
commit dff4f2b3a0
17 changed files with 955 additions and 137 deletions

View File

@@ -1,4 +1,5 @@
#include "microhttpd_server.h"
#include "piliterals_bytes.h"
#include "piliterals_string.h"
#include "piliterals_time.h"
@@ -31,11 +32,11 @@
struct MicrohttpdServerConnection {
bool ready();
int send_reply(const MicrohttpdServer::Reply & r);
int send_error();
int sendReply(const PIHTTP::MessageMutable & r);
int sendError();
bool done = false;
MicrohttpdServer::Method method = MicrohttpdServer::Method::Unknown;
bool done = false;
PIHTTP::Method method = PIHTTP::Method::Unknown;
PIString path;
PIByteArray body;
PIMap<PIString, PIString> headers, args, post;
@@ -49,47 +50,48 @@ bool MicrohttpdServerConnection::ready() {
if (!server) return false;
if (done) return true;
done = true;
MicrohttpdServer::Reply rep;
if (method == MicrohttpdServer::Method::Get) {
PIHTTP::MessageMutable rep;
if (method == PIHTTP::Method::Get) {
if (path == "/favicon.ico"_a) {
// piCout << "send favicon" << server->favicon.size() << "bytes";
rep.setBody(server->favicon);
send_reply(rep);
sendReply(rep);
return true;
}
}
// piCout << "ready" << (int)method << path;
MicrohttpdServer::Request req;
req.method = method;
req.path = path;
req.body = body;
req.headers = headers;
req.args = args;
rep.setCode(MHD_HTTP_BAD_REQUEST);
PIHTTP::MessageMutable req;
req.setMethod(method);
req.setPath(path);
req.setBody(body);
req.headers() = headers;
req.arguments() = args;
rep.setCode(PIHTTP::Code::BadRequest);
if (server->callback) rep = server->callback(req);
rep.addFixedHeaders();
send_reply(rep);
MicrohttpdServer::addFixedHeaders(rep);
sendReply(rep);
// piCout << "ready ok" << (int)rep.code() << rep.body().size();
return true;
}
int MicrohttpdServerConnection::send_reply(const MicrohttpdServer::Reply & r) {
MHD_Response * response = MHD_create_response_from_buffer(r.body.size(), (void *)r.body.data(), MHD_RESPMEM_MUST_COPY);
int MicrohttpdServerConnection::sendReply(const PIHTTP::MessageMutable & r) {
MHD_Response * response = MHD_create_response_from_buffer(r.body().size(), (void *)r.body().data(), MHD_RESPMEM_MUST_COPY);
if (!response) {
// piCout << "null response" << r.body.size() << (void *)r.body.data();
return MHD_NO;
}
auto it = r.headers.makeIterator();
auto it = r.headers().makeIterator();
while (it.next())
MHD_add_response_header(response, it.key().dataAscii(), it.value().dataUTF8());
// piCout << "status" << r.code;
int ret = MHD_queue_response(connection, r.code, response);
int ret = MHD_queue_response(connection, static_cast<int>(r.code()), response);
MHD_destroy_response(response);
return ret;
}
int MicrohttpdServerConnection::send_error() {
int MicrohttpdServerConnection::sendError() {
return MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY));
}
@@ -98,9 +100,9 @@ void log_callback(void * cls, const char * fmt, va_list ap) {
MicrohttpdServer * server = (MicrohttpdServer *)cls;
piCout << "log" << server;
if (!server) return;
char buffer[1024];
memset(buffer, 0, 1024);
std::vsnprintf(buffer, 1024, fmt, ap);
char buffer[1_KiB];
memset(buffer, 0, 1_KiB);
std::vsnprintf(buffer, 1_KiB, fmt, ap);
piCout << buffer;
}
@@ -158,30 +160,30 @@ int answer_to_connection(void * cls,
const char * upload_data,
size_t * upload_data_size,
void ** con_cls) {
MicrohttpdServer * server = (MicrohttpdServer *)cls;
MicrohttpdServer * server = (MicrohttpdServer *)cls;
MicrohttpdServer::Method m = MicrohttpdServer::Method::Unknown;
PIHTTP::Method m = PIHTTP::Method::Unknown;
if (0 == strcmp(method, "GET"))
m = MicrohttpdServer::Method::Get;
m = PIHTTP::Method::Get;
else if (0 == strcmp(method, "POST"))
m = MicrohttpdServer::Method::Post;
m = PIHTTP::Method::Post;
else if (0 == strcmp(method, "HEAD"))
m = MicrohttpdServer::Method::Head;
m = PIHTTP::Method::Head;
else if (0 == strcmp(method, "PUT"))
m = MicrohttpdServer::Method::Put;
m = PIHTTP::Method::Put;
else if (0 == strcmp(method, "DELETE"))
m = MicrohttpdServer::Method::Delete;
m = PIHTTP::Method::Delete;
else if (0 == strcmp(method, "CONNECT"))
m = MicrohttpdServer::Method::Connect;
m = PIHTTP::Method::Connect;
else if (0 == strcmp(method, "OPTIONS"))
m = MicrohttpdServer::Method::Options;
m = PIHTTP::Method::Options;
else if (0 == strcmp(method, "TRACE"))
m = MicrohttpdServer::Method::Trace;
m = PIHTTP::Method::Trace;
else if (0 == strcmp(method, "PATCH"))
m = MicrohttpdServer::Method::Patch;
m = PIHTTP::Method::Patch;
if (m == MicrohttpdServer::Method::Unknown) {
if (m == PIHTTP::Method::Unknown) {
piCout << "[MicrohttpdServer]"
<< "Warning:"
<< "Unknown method!";
@@ -201,20 +203,20 @@ int answer_to_connection(void * cls,
return MHD_YES;
}
if (m == MicrohttpdServer::Method::Unknown) {
return conn->send_error();
if (m == PIHTTP::Method::Unknown) {
return conn->sendError();
}
if (*upload_data_size) {
if (!conn->postprocessor) {
conn->postprocessor = MHD_create_post_processor(connection, 65536, (MHD_PostDataIterator)iterate_post, (void *)conn);
conn->postprocessor = MHD_create_post_processor(connection, 64_KiB, (MHD_PostDataIterator)iterate_post, (void *)conn);
}
conn->body.append(upload_data, *upload_data_size);
MHD_post_process(conn->postprocessor, upload_data, *upload_data_size);
*upload_data_size = 0;
} else {
// qDebug() << "answer ok";
if (!conn->ready()) return conn->send_error();
if (!conn->ready()) return conn->sendError();
}
return MHD_YES;
}
@@ -305,34 +307,14 @@ void MicrohttpdServer::stop() {
}
void MicrohttpdServer::Reply::addHeader(const PIString & header, const PIString & value) {
headers[header] = value;
}
void MicrohttpdServer::Reply::removeHeader(const PIString & header) {
headers.remove(header);
}
void MicrohttpdServer::Reply::setBody(const PIByteArray & b) {
body = b;
}
void MicrohttpdServer::Reply::setCode(int c) {
code = c;
}
void MicrohttpdServer::Reply::addFixedHeaders() {
if (!headers.contains(MHD_HTTP_HEADER_CONTENT_TYPE)) {
if (body.isNotEmpty()) {
if (body.startsWith(PIByteArray::fromAscii("<!DOCTYPE html>")))
addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "text/html; charset=utf-8");
else if (body[0] == '[' || body[0] == '{')
addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "application/json; charset=utf-8");
void MicrohttpdServer::addFixedHeaders(PIHTTP::MessageMutable & msg) {
if (!msg.headers().contains(PIHTTP::Header::ContentType)) {
if (msg.body().isNotEmpty()) {
if (msg.body().startsWith(PIByteArray::fromAscii("<!DOCTYPE html>")))
msg.addHeader(PIHTTP::Header::ContentType, "text/html; charset=utf-8");
else if (msg.body()[0] == '[' || msg.body()[0] == '{')
msg.addHeader(PIHTTP::Header::ContentType, "application/json; charset=utf-8");
}
}
addHeader(MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, "*");
msg.addHeader(PIHTTP::Header::AccessControlAllowOrigin, "*");
}