PIHTTPServer basic auth works
This commit is contained in:
@@ -30,13 +30,23 @@
|
||||
// clang-format on
|
||||
|
||||
|
||||
struct MicrohttpdServerConnection {
|
||||
bool ready();
|
||||
int sendReply(const PIHTTP::MessageMutable & r);
|
||||
int sendError();
|
||||
using namespace PIHTTP;
|
||||
|
||||
bool done = false;
|
||||
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
||||
|
||||
struct BasicAuthCred {
|
||||
bool exists = false;
|
||||
PIString user;
|
||||
PIString pass;
|
||||
};
|
||||
|
||||
struct MicrohttpdServerConnection {
|
||||
bool checkBasicAuth();
|
||||
bool ready();
|
||||
int sendReply(const MessageMutable & r);
|
||||
BasicAuthCred getBasicAuthCred();
|
||||
|
||||
bool done = false, authorized = false;
|
||||
Method method = Method::Unknown;
|
||||
PIString path;
|
||||
PIByteArray body;
|
||||
PIMap<PIString, PIString> headers, args, post;
|
||||
@@ -46,12 +56,31 @@ struct MicrohttpdServerConnection {
|
||||
};
|
||||
|
||||
|
||||
bool MicrohttpdServerConnection::checkBasicAuth() {
|
||||
if (headers.contains(Header::Authorization)) {
|
||||
auto ba_up = getBasicAuthCred();
|
||||
bool ok = false; // server->callback_auth(ba_up.user, ba_up.pass);
|
||||
if (server->callback_auth) ok = server->callback_auth(ba_up.user, ba_up.pass);
|
||||
if (ok) {
|
||||
authorized = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// piCout << "miss authorization";
|
||||
sendReply(MessageMutable::fromCode(Code::Unauthorized)
|
||||
.addHeader(Header::WWWAuthenticate, "Basic realm=\"%1\", charset=\"UTF-8\""_a.arg(server->realm))
|
||||
.setBody(PIByteArray::fromAscii("Authorization required")));
|
||||
// piCout << "answer sent";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool MicrohttpdServerConnection::ready() {
|
||||
if (!server) return false;
|
||||
if (done) return true;
|
||||
done = true;
|
||||
PIHTTP::MessageMutable rep;
|
||||
if (method == PIHTTP::Method::Get) {
|
||||
MessageMutable rep;
|
||||
if (method == Method::Get) {
|
||||
if (path == "/favicon.ico"_a) {
|
||||
// piCout << "send favicon" << server->favicon.size() << "bytes";
|
||||
rep.setBody(server->favicon);
|
||||
@@ -60,13 +89,13 @@ bool MicrohttpdServerConnection::ready() {
|
||||
}
|
||||
}
|
||||
// piCout << "ready" << (int)method << path;
|
||||
PIHTTP::MessageMutable req;
|
||||
MessageMutable req;
|
||||
req.setMethod(method);
|
||||
req.setPath(path);
|
||||
req.setBody(body);
|
||||
req.headers() = headers;
|
||||
req.arguments() = args;
|
||||
rep.setCode(PIHTTP::Code::BadRequest);
|
||||
rep.setCode(Code::BadRequest);
|
||||
if (server->callback) rep = server->callback(req);
|
||||
MicrohttpdServer::addFixedHeaders(rep);
|
||||
sendReply(rep);
|
||||
@@ -75,7 +104,7 @@ bool MicrohttpdServerConnection::ready() {
|
||||
}
|
||||
|
||||
|
||||
int MicrohttpdServerConnection::sendReply(const PIHTTP::MessageMutable & r) {
|
||||
int MicrohttpdServerConnection::sendReply(const 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();
|
||||
@@ -91,8 +120,21 @@ int MicrohttpdServerConnection::sendReply(const PIHTTP::MessageMutable & r) {
|
||||
}
|
||||
|
||||
|
||||
int MicrohttpdServerConnection::sendError() {
|
||||
return MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY));
|
||||
BasicAuthCred MicrohttpdServerConnection::getBasicAuthCred() {
|
||||
BasicAuthCred ret;
|
||||
char * p = nullptr;
|
||||
auto u = MHD_basic_auth_get_username_password(connection, &p);
|
||||
if (u) {
|
||||
ret.user = PIString::fromUTF8(u);
|
||||
ret.exists = true;
|
||||
MHD_free(u);
|
||||
}
|
||||
if (p) {
|
||||
ret.pass = PIString::fromUTF8(p);
|
||||
ret.exists = true;
|
||||
MHD_free(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,38 +194,38 @@ int args_iterate(void * cls, MHD_ValueKind kind, const char * key, const char *
|
||||
}
|
||||
|
||||
|
||||
int answer_to_connection(void * cls,
|
||||
MHD_Connection * connection,
|
||||
const char * url,
|
||||
const char * method,
|
||||
const char * version,
|
||||
const char * upload_data,
|
||||
size_t * upload_data_size,
|
||||
void ** con_cls) {
|
||||
int answer_callback(void * cls,
|
||||
MHD_Connection * connection,
|
||||
const char * url,
|
||||
const char * method,
|
||||
const char * version,
|
||||
const char * upload_data,
|
||||
size_t * upload_data_size,
|
||||
void ** con_cls) {
|
||||
MicrohttpdServer * server = (MicrohttpdServer *)cls;
|
||||
|
||||
PIHTTP::Method m = PIHTTP::Method::Unknown;
|
||||
Method m = Method::Unknown;
|
||||
|
||||
if (0 == strcmp(method, "GET"))
|
||||
m = PIHTTP::Method::Get;
|
||||
m = Method::Get;
|
||||
else if (0 == strcmp(method, "POST"))
|
||||
m = PIHTTP::Method::Post;
|
||||
m = Method::Post;
|
||||
else if (0 == strcmp(method, "HEAD"))
|
||||
m = PIHTTP::Method::Head;
|
||||
m = Method::Head;
|
||||
else if (0 == strcmp(method, "PUT"))
|
||||
m = PIHTTP::Method::Put;
|
||||
m = Method::Put;
|
||||
else if (0 == strcmp(method, "DELETE"))
|
||||
m = PIHTTP::Method::Delete;
|
||||
m = Method::Delete;
|
||||
else if (0 == strcmp(method, "CONNECT"))
|
||||
m = PIHTTP::Method::Connect;
|
||||
m = Method::Connect;
|
||||
else if (0 == strcmp(method, "OPTIONS"))
|
||||
m = PIHTTP::Method::Options;
|
||||
m = Method::Options;
|
||||
else if (0 == strcmp(method, "TRACE"))
|
||||
m = PIHTTP::Method::Trace;
|
||||
m = Method::Trace;
|
||||
else if (0 == strcmp(method, "PATCH"))
|
||||
m = PIHTTP::Method::Patch;
|
||||
m = Method::Patch;
|
||||
|
||||
if (m == PIHTTP::Method::Unknown) {
|
||||
if (m == Method::Unknown) {
|
||||
piCout << "[MicrohttpdServer]"
|
||||
<< "Warning:"
|
||||
<< "Unknown method!";
|
||||
@@ -200,11 +242,14 @@ int answer_to_connection(void * cls,
|
||||
conn->method = m;
|
||||
MHD_get_connection_values(connection, MHD_HEADER_KIND, (MHD_KeyValueIterator)header_iterate, *con_cls);
|
||||
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, (MHD_KeyValueIterator)args_iterate, *con_cls);
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
if (m == PIHTTP::Method::Unknown) {
|
||||
return conn->sendError();
|
||||
if (m == Method::Unknown) {
|
||||
return conn->sendReply(MessageMutable::fromCode(Code::MethodNotAllowed));
|
||||
}
|
||||
|
||||
if (server->isBasicAuthEnabled() && !conn->authorized) {
|
||||
if (!conn->checkBasicAuth()) return MHD_YES;
|
||||
}
|
||||
|
||||
if (*upload_data_size) {
|
||||
@@ -216,7 +261,7 @@ int answer_to_connection(void * cls,
|
||||
*upload_data_size = 0;
|
||||
} else {
|
||||
// qDebug() << "answer ok";
|
||||
if (!conn->ready()) return conn->sendError();
|
||||
if (!conn->ready()) return conn->sendReply(MessageMutable::fromCode(Code::InternalServerError));
|
||||
}
|
||||
return MHD_YES;
|
||||
}
|
||||
@@ -231,6 +276,7 @@ MicrohttpdServer::MicrohttpdServer() {
|
||||
PRIVATE->daemon = nullptr;
|
||||
opts[Option::ConnectionLimit] = FD_SETSIZE - 4;
|
||||
opts[Option::ConnectionTimeout] = 0_s;
|
||||
realm = "Restricted"_a;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +331,7 @@ bool MicrohttpdServer::listen(PINetworkAddress addr) {
|
||||
addr.port(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
(MHD_AccessHandlerCallback)answer_to_connection,
|
||||
(MHD_AccessHandlerCallback)answer_callback,
|
||||
this,
|
||||
MHD_OPTION_ARRAY,
|
||||
options.data(),
|
||||
@@ -307,14 +353,14 @@ void MicrohttpdServer::stop() {
|
||||
}
|
||||
|
||||
|
||||
void MicrohttpdServer::addFixedHeaders(PIHTTP::MessageMutable & msg) {
|
||||
if (!msg.headers().contains(PIHTTP::Header::ContentType)) {
|
||||
void MicrohttpdServer::addFixedHeaders(MessageMutable & msg) {
|
||||
if (!msg.headers().contains(Header::ContentType)) {
|
||||
if (msg.body().isNotEmpty()) {
|
||||
if (msg.body().startsWith(PIByteArray::fromAscii("<!DOCTYPE html>")))
|
||||
msg.addHeader(PIHTTP::Header::ContentType, "text/html; charset=utf-8");
|
||||
msg.addHeader(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");
|
||||
msg.addHeader(Header::ContentType, "application/json; charset=utf-8");
|
||||
}
|
||||
}
|
||||
msg.addHeader(PIHTTP::Header::AccessControlAllowOrigin, "*");
|
||||
msg.addHeader(Header::AccessControlAllowOrigin, "*");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user