diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp index 617b64163..f6514e365 100644 --- a/src/base/http/connection.cpp +++ b/src/base/http/connection.cpp @@ -32,7 +32,6 @@ #include -#include "base/logger.h" #include "irequesthandler.h" #include "requestparser.h" #include "responsegenerator.h" @@ -94,8 +93,8 @@ void Connection::read() const long bufferLimit = RequestParser::MAX_CONTENT_SIZE * 1.1; // some margin for headers if (m_receivedData.size() > bufferLimit) { - LogMsg(tr("Http request size exceeds limitation, closing socket. Limit: %1, IP: %2") - .arg(bufferLimit).arg(m_socket->peerAddress().toString()), Log::WARNING); + qWarning("%s", qUtf8Printable(tr("Http request size exceeds limitation, closing socket. Limit: %1, IP: %2") + .arg(QString::number(bufferLimit), m_socket->peerAddress().toString()))); Response resp(413, u"Payload Too Large"_s); resp.headers[HEADER_CONNECTION] = u"close"_s; @@ -106,10 +105,23 @@ void Connection::read() } return; + case RequestParser::ParseStatus::BadMethod: + { + qWarning("%s", qUtf8Printable(tr("Bad Http request method, closing socket. IP: %1. Method: \"%2\"") + .arg(m_socket->peerAddress().toString(), result.request.method))); + + Response resp(501, u"Not Implemented"_s); + resp.headers[HEADER_CONNECTION] = u"close"_s; + + sendResponse(resp); + m_socket->close(); + } + return; + case RequestParser::ParseStatus::BadRequest: { - LogMsg(tr("Bad Http request, closing socket. IP: %1") - .arg(m_socket->peerAddress().toString()), Log::WARNING); + qWarning("%s", qUtf8Printable(tr("Bad Http request, closing socket. IP: %1") + .arg(m_socket->peerAddress().toString()))); Response resp(400, u"Bad Request"_s); resp.headers[HEADER_CONNECTION] = u"close"_s; @@ -123,14 +135,30 @@ void Connection::read() { const Environment env {m_socket->localAddress(), m_socket->localPort(), m_socket->peerAddress(), m_socket->peerPort()}; - Response resp = m_requestHandler->processRequest(result.request, env); + if (result.request.method == HEADER_REQUEST_METHOD_HEAD) + { + Request getRequest = result.request; + getRequest.method = HEADER_REQUEST_METHOD_GET; - if (acceptsGzipEncoding(result.request.headers[u"accept-encoding"_s])) - resp.headers[HEADER_CONTENT_ENCODING] = u"gzip"_s; + Response resp = m_requestHandler->processRequest(getRequest, env); - resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + resp.headers[HEADER_CONTENT_LENGTH] = QString::number(resp.content.length()); + resp.content.clear(); + + sendResponse(resp); + } + else + { + Response resp = m_requestHandler->processRequest(result.request, env); + + if (acceptsGzipEncoding(result.request.headers.value(u"accept-encoding"_s))) + resp.headers[HEADER_CONTENT_ENCODING] = u"gzip"_s; + resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; + + sendResponse(resp); + } - sendResponse(resp); m_receivedData.remove(0, result.frameSize); } break; diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index 540f6481c..2568e4a55 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -103,6 +103,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) // handle supported methods if ((m_request.method == HEADER_REQUEST_METHOD_GET) || (m_request.method == HEADER_REQUEST_METHOD_HEAD)) return {ParseStatus::OK, m_request, headerLength}; + if (m_request.method == HEADER_REQUEST_METHOD_POST) { const auto parseContentLength = [this]() -> int @@ -146,8 +147,7 @@ RequestParser::ParseResult RequestParser::doParse(const QByteArray &data) return {ParseStatus::OK, m_request, (headerLength + contentLength)}; } - qWarning() << Q_FUNC_INFO << "unsupported request method: " << m_request.method; - return {ParseStatus::BadRequest, Request(), 0}; // TODO: SHOULD respond "501 Not Implemented" + return {ParseStatus::BadMethod, m_request, 0}; } bool RequestParser::parseStartLines(const QStringView data) diff --git a/src/base/http/requestparser.h b/src/base/http/requestparser.h index 0cab0db0e..b55907ea4 100644 --- a/src/base/http/requestparser.h +++ b/src/base/http/requestparser.h @@ -41,6 +41,7 @@ namespace Http { OK, Incomplete, + BadMethod, BadRequest }; diff --git a/src/base/http/responsegenerator.cpp b/src/base/http/responsegenerator.cpp index a152e7fe2..b34b973db 100644 --- a/src/base/http/responsegenerator.cpp +++ b/src/base/http/responsegenerator.cpp @@ -38,8 +38,9 @@ QByteArray Http::toByteArray(Response response) { compressContent(response); - response.headers[HEADER_CONTENT_LENGTH] = QString::number(response.content.length()); response.headers[HEADER_DATE] = httpDate(); + if (QString &value = response.headers[HEADER_CONTENT_LENGTH]; value.isEmpty()) + value = QString::number(response.content.length()); QByteArray buf; buf.reserve(1024 + response.content.length()); @@ -63,7 +64,7 @@ QByteArray Http::toByteArray(Response response) // the first empty line buf += CRLF; - // message body // TODO: support HEAD request + // message body buf += response.content; return buf;