/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2015 Simon Stuerz * * * * This file is part of guh. * * * * Guh is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, version 2 of the License. * * * * Guh is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with guh. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "httprequest.h" #include "loggingcategories.h" #include HttpRequest::HttpRequest(QByteArray rawData) : m_rawData(rawData), m_valid(false) { // Parese the HTTP request. The request is invalid, until the end of the parse process. if (m_rawData.isEmpty()) return; // split the data into header and payload int headerEndIndex = m_rawData.indexOf("\r\n\r\n"); if (headerEndIndex < 0) { qCWarning(dcWebServer) << "Could not parse end of HTTP header (empty line between header and body):" << rawData; return; } m_rawHeader = m_rawData.left(headerEndIndex); m_payload = m_rawData.right(m_rawData.length() - headerEndIndex).simplified(); // parse status line QStringList headerLines = QString(m_rawHeader).split(QRegExp("\r\n")); QString statusLine = headerLines.takeFirst(); QStringList statusLineTokens = statusLine.split(QRegExp("[ \r\n][ \r\n]*")); if (statusLineTokens.count() != 3) { qCWarning(dcWebServer) << "Could not parse HTTP status line:" << statusLine; return; } // verify http version m_httpVersion = statusLineTokens.at(2).toUtf8().simplified(); if (!m_httpVersion.contains("HTTP")) { qCWarning(dcWebServer) << "Unknown HTTP version:" << m_httpVersion; return; } m_method = getRequestMethodType(statusLineTokens.at(0).simplified()); m_urlQuery = QUrlQuery(statusLineTokens.at(1).simplified()); // verify headers foreach (const QString &line, headerLines) { if (!line.contains(":")) { qCWarning(dcWebServer) << "Invalid HTTP header:" << line; return; } int index = line.indexOf(":"); QByteArray key = line.left(index).toUtf8().simplified(); QByteArray value = line.right(line.count() - index - 1).toUtf8().simplified(); m_rawHeaderList.insert(key, value); } // TODO: check content size m_valid = true; } QByteArray HttpRequest::rawHeader() const { return m_rawHeader; } QHash HttpRequest::rawHeaderList() const { return m_rawHeaderList; } HttpRequest::RequestMethod HttpRequest::method() const { return m_method; } QByteArray HttpRequest::httpVersion() const { return m_httpVersion; } QUrlQuery HttpRequest::urlQuery() const { return m_urlQuery; } QByteArray HttpRequest::payload() const { return m_payload; } bool HttpRequest::isValid() const { return m_valid; } bool HttpRequest::hasPayload() const { return !m_payload.isEmpty(); } HttpRequest::RequestMethod HttpRequest::getRequestMethodType(const QString &methodString) { if (methodString == "GET") { return RequestMethod::Get; } else if (methodString == "POST") { return RequestMethod::Post; } else if (methodString == "PUT") { return RequestMethod::Put; } else if (methodString == "DELETE") { return RequestMethod::Delete; } qCWarning(dcWebServer) << "Method" << methodString << "will not be handled."; return RequestMethod::Unhandled; } QDebug operator<<(QDebug debug, const HttpRequest &httpRequest) { debug << "===================================" << "\n"; debug << " http version: " << httpRequest.httpVersion() << "\n"; debug << " method: " << httpRequest.method() << "\n"; debug << " URL query: " << httpRequest.urlQuery().query() << "\n"; debug << " is valid: " << httpRequest.isValid() << "\n"; debug << "-----------------------------------" << "\n"; debug << httpRequest.rawHeader() << "\n"; debug << "-----------------------------------" << "\n"; debug << httpRequest.payload() << "\n"; debug << "-----------------------------------" << "\n"; return debug; }