| /** @file | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| #include "xdebug_headers.h" | |
| #include <cstdlib> | |
| #include <cstdio> | |
| #include <cstdio> | |
| #include <strings.h> | |
| #include <string_view> | |
| #include <sstream> | |
| #include <cstring> | |
| #include <getopt.h> | |
| #define DEBUG_TAG_LOG_HEADERS "xdebug.headers" | |
| namespace xdebug | |
| { | |
| namespace | |
| { | |
| DbgCtl dbg_ctl_hdrs{DEBUG_TAG_LOG_HEADERS}; | |
| } | |
| /////////////////////////////////////////////////////////////////////////// | |
| // Dump a header on stderr, useful together with Dbg(). | |
| void | |
| print_headers(TSMBuffer bufp, TSMLoc hdr_loc, std::stringstream &ss, bool full_json) | |
| { | |
| TSIOBuffer output_buffer; | |
| TSIOBufferReader reader; | |
| TSIOBufferBlock block; | |
| const char *block_start; | |
| int64_t block_avail; | |
| EscapeCharForJson escape_char_for_json{full_json}; | |
| output_buffer = TSIOBufferCreate(); | |
| reader = TSIOBufferReaderAlloc(output_buffer); | |
| if (full_json) { | |
| ss << R"("start-line":")"; | |
| } else { | |
| ss << "\t'Start-Line' : '"; | |
| } | |
| // Print all message header lines. | |
| TSHttpHdrPrint(bufp, hdr_loc, output_buffer); | |
| /* We need to loop over all the buffer blocks, there can be more than 1 */ | |
| block = TSIOBufferReaderStart(reader); | |
| do { | |
| block_start = TSIOBufferBlockReadStart(block, reader, &block_avail); | |
| for (const char *c = block_start; c < block_start + block_avail; ++c) { | |
| ss << escape_char_for_json(*c); | |
| } | |
| TSIOBufferReaderConsume(reader, block_avail); | |
| block = TSIOBufferReaderStart(reader); | |
| } while (block && block_avail != 0); | |
| ss.seekp(-escape_char_for_json.backup(full_json), std::ios_base::end); | |
| /* Free up the TSIOBuffer that we used to print out the header */ | |
| TSIOBufferReaderFree(reader); | |
| TSIOBufferDestroy(output_buffer); | |
| Dbg(dbg_ctl_hdrs, "%.*s", static_cast<int>(ss.tellp()), ss.str().data()); | |
| } | |
| void | |
| log_headers(TSHttpTxn /* txn ATS_UNUSED */, TSMBuffer bufp, TSMLoc hdr_loc, char const *type_msg) | |
| { | |
| if (dbg_ctl_hdrs.on()) { | |
| std::stringstream output; | |
| print_headers(bufp, hdr_loc, output, FULL_JSON); | |
| Dbg(dbg_ctl_hdrs, "\n=============\n %s headers are... \n %s", type_msg, output.str().c_str()); | |
| } | |
| } | |
| void | |
| print_request_headers(TSHttpTxn txn, std::stringstream &output) | |
| { | |
| TSMBuffer buf_c, buf_s; | |
| TSMLoc hdr_loc; | |
| if (TSHttpTxnClientReqGet(txn, &buf_c, &hdr_loc) == TS_SUCCESS) { | |
| output << "{'type':'request', 'side':'client', 'headers': {\n"; | |
| print_headers(buf_c, hdr_loc, output, !FULL_JSON); | |
| output << "\n\t}}"; | |
| TSHandleMLocRelease(buf_c, TS_NULL_MLOC, hdr_loc); | |
| } | |
| if (TSHttpTxnServerReqGet(txn, &buf_s, &hdr_loc) == TS_SUCCESS) { | |
| output << ",{'type':'request', 'side':'server', 'headers': {\n"; | |
| print_headers(buf_s, hdr_loc, output, !FULL_JSON); | |
| output << "\n\t}}"; | |
| TSHandleMLocRelease(buf_s, TS_NULL_MLOC, hdr_loc); | |
| } | |
| } | |
| void | |
| print_response_headers(TSHttpTxn txn, std::stringstream &output) | |
| { | |
| TSMBuffer buf_c, buf_s; | |
| TSMLoc hdr_loc; | |
| if (TSHttpTxnServerRespGet(txn, &buf_s, &hdr_loc) == TS_SUCCESS) { | |
| output << "{'type':'response', 'side':'server', 'headers': {\n"; | |
| print_headers(buf_s, hdr_loc, output, !FULL_JSON); | |
| output << "\n\t}},"; | |
| TSHandleMLocRelease(buf_s, TS_NULL_MLOC, hdr_loc); | |
| } | |
| if (TSHttpTxnClientRespGet(txn, &buf_c, &hdr_loc) == TS_SUCCESS) { | |
| output << "{'type':'response', 'side':'client', 'headers': {\n"; | |
| print_headers(buf_c, hdr_loc, output, !FULL_JSON); | |
| output << "\n\t}}"; | |
| TSHandleMLocRelease(buf_c, TS_NULL_MLOC, hdr_loc); | |
| } | |
| } | |
| void | |
| print_request_headers_full_json(TSHttpTxn txn, std::stringstream &output) | |
| { | |
| TSMBuffer buf_c, buf_s; | |
| TSMLoc hdr_loc; | |
| bool has_client = false; | |
| Dbg(dbg_ctl_hdrs, "Printing client request headers for full JSON"); | |
| if (TSHttpTxnClientReqGet(txn, &buf_c, &hdr_loc) == TS_SUCCESS) { | |
| output << "{\"client-request\":{"; | |
| print_headers(buf_c, hdr_loc, output, FULL_JSON); | |
| output << "}"; | |
| has_client = true; | |
| TSHandleMLocRelease(buf_c, TS_NULL_MLOC, hdr_loc); | |
| } | |
| if (TSHttpTxnServerReqGet(txn, &buf_s, &hdr_loc) == TS_SUCCESS) { | |
| if (has_client) { | |
| output << ","; | |
| } | |
| output << "\"proxy-request\":{"; | |
| print_headers(buf_s, hdr_loc, output, FULL_JSON); | |
| output << "}"; | |
| TSHandleMLocRelease(buf_s, TS_NULL_MLOC, hdr_loc); | |
| } | |
| } | |
| void | |
| print_response_headers_full_json(TSHttpTxn txn, std::stringstream &output) | |
| { | |
| TSMBuffer buf_c, buf_s; | |
| TSMLoc hdr_loc; | |
| bool has_server = false; | |
| if (TSHttpTxnServerRespGet(txn, &buf_s, &hdr_loc) == TS_SUCCESS) { | |
| output << "\"server-response\":{"; | |
| print_headers(buf_s, hdr_loc, output, FULL_JSON); | |
| output << "}"; | |
| has_server = true; | |
| TSHandleMLocRelease(buf_s, TS_NULL_MLOC, hdr_loc); | |
| } | |
| if (TSHttpTxnClientRespGet(txn, &buf_c, &hdr_loc) == TS_SUCCESS) { | |
| if (has_server) { | |
| output << ","; | |
| } | |
| output << "\"proxy-response\":{"; | |
| print_headers(buf_c, hdr_loc, output, FULL_JSON); | |
| output << "}}"; | |
| TSHandleMLocRelease(buf_c, TS_NULL_MLOC, hdr_loc); | |
| } | |
| } | |
| } // namespace xdebug |