/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Fluent Bit * ========== * Copyright (C) 2015-2022 The Fluent Bit Authors * * Licensed 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 #include #include #include #include #include /* * Callbacks * ========= */ static void debug_cb_request_headers(char *name, void *p1, void *p2) { struct flb_http_client *c = p1; flb_idebug("[http] request headers\n%s", c->header_buf); } static void debug_cb_request_payload(char *name, void *p1, void *p2) { unsigned char *ptr; struct flb_http_client *c = p1; if (c->body_len > 3) { ptr = (unsigned char *) c->body_buf; if (ptr[0] == 0x1F && ptr[1] == 0x8B && ptr[2] == 0x08) { flb_idebug("[http] request payload (%d bytes)\n[GZIP binary content...]", c->body_len); } else { flb_idebug("[http] request payload (%d bytes)\n%s", c->body_len, c->body_buf); } } else { flb_idebug("[http] request payload (%d bytes)\n%s", c->body_len, c->body_buf); } } static void debug_cb_response_headers(char *name, void *p1, void *p2) { char tmp; struct flb_http_client *c = p1; /* * Just to make easier debugging, we are going to put a NULL byte after * the header break (\r\n\r\n) and then restore it. */ tmp = *c->resp.headers_end; *c->resp.headers_end = '\0'; flb_idebug("[http] response headers\n%s", c->resp.data); *c->resp.headers_end = tmp; } static void debug_cb_response_payload(char *name, void *p1, void *p2) { struct flb_http_client *c = p1; flb_idebug("[http] response payload (%lu bytes)\n%s", c->resp.payload_size, c->resp.payload); } struct flb_http_callback { char *name; void (*func)(char *, void *, void *); }; /* * Callbacks Table */ struct flb_http_callback http_callbacks[] = { /* request */ { "_debug.http.request_headers", debug_cb_request_headers }, { "_debug.http.request_payload", debug_cb_request_payload }, /* response */ { "_debug.http.response_headers", debug_cb_response_headers }, { "_debug.http.response_payload", debug_cb_response_payload }, { 0 } }; /* * Exported Functions * ================== */ /* Determinate if a http.debug property is valid or not */ int flb_http_client_debug_property_is_valid(char *key, char *val) { int i; int ret; int len; struct flb_http_callback *cb; if (!key) { flb_error("[http_client] given property is invalid"); return -1; } if (!val) { flb_error("[http_client] property '%s' don't have a valid value", key); return -1; } len = (sizeof(http_callbacks) / sizeof(struct flb_http_callback)) - 1; for (i = 0; i < len ; i++) { cb = &http_callbacks[i]; if (strcasecmp(key, cb->name) == 0) { ret = flb_utils_bool(val); if (ret == -1) { return FLB_FALSE; } return FLB_TRUE; } } return FLB_FALSE; } int flb_http_client_debug_cb(struct flb_http_client *c, char *name) { int ret; ret = flb_callback_do(c->cb_ctx, name, c, NULL); return ret; } /* * This function helps to setup 'HTTP' debugging mode on a HTTP client context * using the list of configuration properties set by the instance. On this * specific case we don't pass the 'plugin instance' reference since it can be * an input, filter or output, we try to make this agnostic. */ int flb_http_client_debug_setup(struct flb_callback *cb_ctx, struct mk_list *props) { int i; int len; int ret; const char *tmp; struct flb_http_callback *cb; /* * Iterate table of callbacks, if the callbacks are not pre-defined in the * context (this might happen when callbacks are overrided by a library * caller), set the default ones. */ len = (sizeof(http_callbacks) / sizeof(struct flb_http_callback)) - 1; for (i = 0; i < len ; i++) { cb = &http_callbacks[i]; /* Check if the debug property has been enabled */ tmp = flb_config_prop_get(cb->name, props); if (!tmp) { continue; } ret = flb_utils_bool(tmp); if (ret == FLB_FALSE) { continue; } ret = flb_callback_exists(cb_ctx, cb->name); if (ret == FLB_FALSE) { /* Set default callback */ ret = flb_callback_set(cb_ctx, cb->name, cb->func); if (ret == -1) { flb_error("[http_client] error setting up default " "callback '%s'", cb->name); } } } return 0; }