diff options
author | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2021-11-25 11:47:06 +0300 |
---|---|---|
committer | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2021-11-25 11:47:06 +0300 |
commit | 699215ede1dbfc7d64ca20181a86124f1fe06076 (patch) | |
tree | dfbe732c57476aa66816b7b5c9141f35fca4c6da /src/libs/zbxembed | |
parent | 1fdf0ec1f9f901793b8f2f85ddd07af571c9a93a (diff) |
........S. [ZBX-19806] added support of multiple header fields in JS method getHeaders()
Diffstat (limited to 'src/libs/zbxembed')
-rw-r--r-- | src/libs/zbxembed/httprequest.c | 166 |
1 files changed, 151 insertions, 15 deletions
diff --git a/src/libs/zbxembed/httprequest.c b/src/libs/zbxembed/httprequest.c index 8ad63a2750a..2e27278f51e 100644 --- a/src/libs/zbxembed/httprequest.c +++ b/src/libs/zbxembed/httprequest.c @@ -25,6 +25,7 @@ #include "httprequest.h" #include "embed.h" #include "duktape.h" +#include "zbxalgo.h" #ifdef HAVE_LIBCURL @@ -440,6 +441,32 @@ static duk_ret_t es_httprequest_status(duk_context *ctx) /****************************************************************************** * * + * Function: parse_header * + * * + * Purpose: retrives value of a header * + * * + * Parameters: header - [IN] the http header to extract value from * + * value_out - [OUT] the value * + * * + ******************************************************************************/ +static int parse_header(char *header, char **value_out) +{ + char *value; + + if (NULL == (value = strchr(header, ':'))) + return FAIL; + + *value++ = '\0'; + while (' ' == *value || '\t' == *value) + value++; + + *value_out = value; + + return SUCCEED; +} + +/****************************************************************************** + * * * Function: es_obj_put_http_header * * * * Purpose: puts http header <field>: <value> as object property/value * @@ -453,13 +480,9 @@ static void es_put_header(duk_context *ctx, int idx, char *header) { char *value; - if (NULL == (value = strchr(header, ':'))) + if (FAIL == parse_header(header, &value)) return; - *value++ = '\0'; - while (' ' == *value || '\t' == *value) - value++; - duk_push_string(ctx, value); /* duk_put_prop_string() throws error on failure, no need to check return code */ @@ -468,19 +491,18 @@ static void es_put_header(duk_context *ctx, int idx, char *header) /****************************************************************************** * * - * Function: es_httprequest_get_headers * + * Function: get_headers_as_strings * * * - * Purpose: CurlHttpRequest.GetHeaders method * + * Purpose: retrieve headers from request in form of arrays * + * * + * Parameters: ctx - [IN] the duktape context * + * request - [IN] the request to retrieve headers from * * * ******************************************************************************/ -static duk_ret_t es_httprequest_get_headers(duk_context *ctx) +static duk_ret_t get_headers_as_strings(duk_context *ctx, zbx_es_httprequest_t *request) { - zbx_es_httprequest_t *request; - duk_idx_t idx; char *ptr, *header; - - if (NULL == (request = es_httprequest(ctx))) - return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object"); + duk_idx_t idx; idx = duk_push_object(ctx); @@ -496,6 +518,120 @@ static duk_ret_t es_httprequest_get_headers(duk_context *ctx) return 1; } +typedef struct +{ + char *name; + zbx_vector_str_t values; +} +zbx_cached_header_t; + +static void cached_headers_free(zbx_cached_header_t *header) +{ + zbx_free(header->name); + zbx_vector_str_clear(&header->values); + zbx_vector_str_destroy(&header->values); + zbx_free(header); +} + +static duk_ret_t get_headers_as_arrays(duk_context *ctx, zbx_es_httprequest_t *request) +{ + char *ptr, *header; + zbx_vector_ptr_t headers; + duk_idx_t idx; + + zbx_vector_ptr_create(&headers); + + idx = duk_push_object(ctx); + + if (0 == request->headers_in_offset) + goto out; + + for (ptr = request->headers_in; NULL != (header = zbx_http_parse_header(&ptr)); ) + { + char *value; + zbx_cached_header_t *existing_header = NULL; + + if (FAIL == parse_header(header, &value)) + { + goto skip; + } + + for (int j = 0; j < headers.values_num; j++) { + zbx_cached_header_t *h = (zbx_cached_header_t*)headers.values[j]; + + if (0 == strcmp(header, h->name)) + { + existing_header = h; + break; + } + } + + if (existing_header != NULL) { + zbx_vector_str_append(&existing_header->values, value); + } + else { + zbx_cached_header_t *cached_header; + + cached_header = zbx_malloc(NULL, sizeof(zbx_cached_header_t)); + + cached_header->name = zbx_strdup(NULL, header); + zbx_vector_str_create(&cached_header->values); + zbx_vector_str_append(&cached_header->values, value); + zbx_vector_ptr_append(&headers, cached_header); + } +skip: + zbx_free(header); + } + + for (int i = 0; i < headers.values_num; i++) { + zbx_cached_header_t *h = (zbx_cached_header_t*)headers.values[i]; + duk_idx_t arr_idx; + + arr_idx = duk_push_array(ctx); + + for (int j = 0; j < h->values.values_num; j++) + { + duk_push_string(ctx, h->values.values[j]); + duk_put_prop_index(ctx, arr_idx, j); + } + + (void)duk_put_prop_string(ctx, idx, h->name); + } + +out: + zbx_vector_ptr_clear_ext(&headers, (zbx_mem_free_func_t)cached_headers_free); + zbx_vector_ptr_destroy(&headers); + return 1; +} + +/****************************************************************************** + * * + * Function: es_httprequest_get_headers * + * * + * Purpose: CurlHttpRequest.GetHeaders method * + * * + ******************************************************************************/ +static duk_ret_t es_httprequest_get_headers(duk_context *ctx) +{ + zbx_es_httprequest_t *request; + duk_idx_t idx; + + if (NULL == (request = es_httprequest(ctx))) + return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object"); + + if (0 == duk_is_null_or_undefined(ctx, 0)) + { + duk_bool_t as_array; + + as_array = duk_to_boolean(ctx, 0); + + if (0 != as_array) + return get_headers_as_arrays(ctx, request); + } + + return get_headers_as_strings(ctx, request); +} + /****************************************************************************** * * * Function: es_httprequest_set_httpauth * @@ -563,7 +699,7 @@ static const duk_function_list_entry curlhttprequest_methods[] = { {"Delete", es_httprequest_delete, 2}, {"Status", es_httprequest_status, 0}, {"SetProxy", es_httprequest_set_proxy, 1}, - {"GetHeaders", es_httprequest_get_headers, 0}, + {"GetHeaders", es_httprequest_get_headers, 1}, {"SetHttpAuth", es_httprequest_set_httpauth, 3}, {NULL, NULL, 0} }; @@ -577,7 +713,7 @@ static const duk_function_list_entry httprequest_methods[] = { {"delete", es_httprequest_delete, 2}, {"getStatus", es_httprequest_status, 0}, {"setProxy", es_httprequest_set_proxy, 1}, - {"getHeaders", es_httprequest_get_headers, 0}, + {"getHeaders", es_httprequest_get_headers, 1}, {"setHttpAuth", es_httprequest_set_httpauth, 3}, {NULL, NULL, 0} }; |