Coverage Report

Created: 2026-05-18 13:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/http/http_request.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "http/http_request.h"
19
20
#include <event2/buffer.h>
21
#include <event2/http.h>
22
#include <event2/http_struct.h>
23
#include <event2/keyvalq_struct.h>
24
25
#include <sstream>
26
#include <string>
27
#include <unordered_map>
28
#include <utility>
29
30
#include "http/http_handler.h"
31
#include "http/http_headers.h"
32
33
namespace doris {
34
35
static std::string s_empty = "";
36
37
// Helper function to check if a header should be masked in logs
38
64
static bool is_sensitive_header(const std::string& header_name) {
39
64
    return iequal(header_name, HttpHeaders::AUTHORIZATION) ||
40
64
           iequal(header_name, HttpHeaders::PROXY_AUTHORIZATION) || iequal(header_name, "token") ||
41
64
           iequal(header_name, HttpHeaders::AUTH_TOKEN);
42
64
}
43
44
66
HttpRequest::HttpRequest(evhttp_request* evhttp_request) : _ev_req(evhttp_request) {}
45
46
66
HttpRequest::~HttpRequest() {
47
66
    if (_handler_ctx != nullptr) {
48
0
        DCHECK(_handler != nullptr);
49
0
        _handler->free_handler_ctx(_handler_ctx);
50
0
    }
51
66
}
52
53
57
int HttpRequest::init_from_evhttp() {
54
57
    _method = to_http_method(evhttp_request_get_command(_ev_req));
55
57
    if (_method == HttpMethod::UNKNOWN) {
56
0
        LOG(WARNING) << "unknown method of HTTP request, method="
57
0
                     << evhttp_request_get_command(_ev_req);
58
0
        return -1;
59
0
    }
60
57
    _uri = evhttp_request_get_uri(_ev_req);
61
    // conver header
62
57
    auto headers = evhttp_request_get_input_headers(_ev_req);
63
217
    for (auto header = headers->tqh_first; header != nullptr; header = header->next.tqe_next) {
64
160
        _headers.emplace(header->key, header->value);
65
160
    }
66
    // parse
67
57
    auto ev_uri = evhttp_request_get_evhttp_uri(_ev_req);
68
57
    _raw_path = evhttp_uri_get_path(ev_uri);
69
57
    auto query = evhttp_uri_get_query(ev_uri);
70
57
    if (query == nullptr || *query == '\0') {
71
45
        return 0;
72
45
    }
73
12
    struct evkeyvalq params;
74
12
    auto res = evhttp_parse_query_str(query, &params);
75
12
    if (res < 0) {
76
0
        LOG(WARNING) << "parse query str failed, query=" << query;
77
0
        return res;
78
0
    }
79
39
    for (auto param = params.tqh_first; param != nullptr; param = param->next.tqe_next) {
80
27
        _query_params.emplace(param->key, param->value);
81
27
    }
82
12
    _params.insert(_query_params.begin(), _query_params.end());
83
12
    evhttp_clear_headers(&params);
84
12
    return 0;
85
12
}
86
87
25
std::string HttpRequest::debug_string() const {
88
25
    std::stringstream ss;
89
25
    ss << "HttpRequest: \n"
90
25
       << "method:" << _method << "\n"
91
25
       << "uri:" << _uri << "\n"
92
25
       << "raw_path:" << _raw_path << "\n"
93
25
       << "headers: \n";
94
64
    for (auto& iter : _headers) {
95
64
        if (is_sensitive_header(iter.first)) {
96
2
            ss << "key=" << iter.first << ", value=***MASKED***\n";
97
62
        } else {
98
62
            ss << "key=" << iter.first << ", value=" << iter.second << "\n";
99
62
        }
100
64
    }
101
25
    ss << "params: \n";
102
30
    for (auto& iter : _params) {
103
30
        ss << "key=" << iter.first << ", value=" << iter.second << "\n";
104
30
    }
105
106
25
    return ss.str();
107
25
}
108
109
155
const std::string& HttpRequest::header(const std::string& key) const {
110
155
    auto iter = _headers.find(key);
111
155
    if (iter == _headers.end()) {
112
126
        return s_empty;
113
126
    }
114
29
    return iter->second;
115
155
}
116
117
53
const std::string& HttpRequest::param(const std::string& key) const {
118
53
    auto iter = _params.find(key);
119
53
    if (iter == _params.end()) {
120
27
        return s_empty;
121
27
    }
122
26
    return iter->second;
123
53
}
124
125
0
std::string HttpRequest::get_all_headers() const {
126
0
    std::stringstream headers;
127
0
    for (const auto& header : _headers) {
128
0
        if (is_sensitive_header(header.first)) {
129
0
            headers << header.first << ":***MASKED***, ";
130
0
        } else {
131
0
            headers << header.first << ":" << header.second + ", ";
132
0
        }
133
0
    }
134
0
    return headers.str();
135
0
}
136
137
23
void HttpRequest::add_output_header(const char* key, const char* value) {
138
23
    evhttp_add_header(evhttp_request_get_output_headers(_ev_req), key, value);
139
23
}
140
141
2
std::string HttpRequest::get_request_body() {
142
2
    if (!_request_body.empty()) {
143
0
        return _request_body;
144
0
    }
145
    // read buf
146
2
    auto evbuf = evhttp_request_get_input_buffer(_ev_req);
147
2
    if (evbuf == nullptr) {
148
0
        return _request_body;
149
0
    }
150
2
    auto length = evbuffer_get_length(evbuf);
151
2
    _request_body.resize(length);
152
2
    evbuffer_remove(evbuf, (char*)_request_body.data(), length);
153
2
    return _request_body;
154
2
}
155
156
32
const char* HttpRequest::remote_host() const {
157
32
    return _ev_req->remote_host;
158
32
}
159
160
} // namespace doris