aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/mcpserver/httpparser.h
blob: aa898a98dc48da974762c3ffa4b7246c3d6b6e87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (C) 2025 David M. Cotter
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once

#include <QByteArray>
#include <QMap>
#include <QObject>
#include <QString>
#include <QStringList>

namespace Mcp::Internal {

/**
 * @brief HTTP/1.1 Request Parser
 *
 * Parses HTTP requests from raw TCP data and extracts:
 * - HTTP method (GET, POST, etc.)
 * - Request URI
 * - HTTP version
 * - Headers
 * - Body content
 *
 * Designed to work with the existing TCP MCP server to provide
 * HTTP compatibility without requiring the HttpServer module.
 */
class HttpParser : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief HTTP request structure
     */
    struct HttpRequest
    {
        QString method;                 ///< HTTP method (GET, POST, etc.)
        QString uri;                    ///< Request URI
        QString version;                ///< HTTP version (1.1, etc.)
        QMap<QString, QString> headers; ///< HTTP headers (case-insensitive keys)
        QByteArray body;                ///< Request body content
        bool isValid;                   ///< Whether the request is valid
        bool needMoreData;              ///< Whether the request has all data available
        QString errorMessage;           ///< Error message if parsing failed
    };

    explicit HttpParser(QObject *parent = nullptr);

    /**
     * @brief Parse HTTP request from raw TCP data
     * @param data Raw TCP data received from client
     * @return Parsed HTTP request structure
     */
    HttpRequest parseRequest(const QByteArray &data);

    /**
     * @brief Check if data looks like an HTTP request
     * @param data Raw data to check
     * @return true if data appears to be HTTP
     */
    static bool isHttpRequest(const QByteArray &data);

private:
    /**
     * @brief Parse the HTTP request line (method URI version)
     * @param requestLine First line of HTTP request
     * @param request Output request structure
     * @return true if parsing succeeded
     */
    bool parseRequestLine(const QString &requestLine, HttpRequest &request);

    /**
     * @brief Parse HTTP headers
     * @param headerLines List of header lines
     * @param request Output request structure
     */
    void parseHeaders(const QStringList &headerLines, HttpRequest &request);

    /**
     * @brief Normalize header name (lowercase for case-insensitive lookup)
     * @param headerName Header name to normalize
     * @return Normalized header name
     */
    static QString normalizeHeaderName(const QString &headerName);

    /**
     * @brief Extract body content from HTTP data
     * @param data Complete HTTP data
     * @param headerEnd Position where headers end
     * @param contentLength Content-Length header value
     * @return Body content
     */
    QByteArray extractBody(const QByteArray &data, int headerEnd, int contentLength);

    /**
     * @brief Split HTTP data into lines
     * @param data HTTP data to split
     * @return List of lines
     */
    QStringList splitHttpLines(const QByteArray &data);
};

} // namespace Mcp::Internal