From 3a265bcf51dc53af85e8672a284bb41253caf8de Mon Sep 17 00:00:00 2001 From: Julien Chavanton Date: Thu, 6 Dec 2018 16:09:26 -0800 Subject: [PATCH] http_client: http_connect_raw similar to http_connect for http/post, however the data parameter is not PV parsed this way json and any other content can be used without any escaping --- .../http_client/doc/http_client_admin.xml | 63 +++++++++++- src/modules/http_client/http_client.c | 99 ++++++++++++++++++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/modules/http_client/doc/http_client_admin.xml b/src/modules/http_client/doc/http_client_admin.xml index 6e772aa9f5d..70bcd2a433f 100644 --- a/src/modules/http_client/doc/http_client_admin.xml +++ b/src/modules/http_client/doc/http_client_admin.xml @@ -646,7 +646,7 @@ http_follow_redirect = no data - Data or a pseudo variable holding - data to be posted. + data to be posted. (may contain pseudo variable) result - The name of a pseudo variable that @@ -675,6 +675,67 @@ xlog("L_INFO", "API-server HTTP connection: $avp(gurka) Result code $var(res)\n" $var(res) = http_connect("apiserver", "/callroute", "application/json", "$var(jsondata)", "$avp(route)"); xlog("L_INFO", "API-server HTTP connection: $avp(route) Result code $var(res)\n"); +... + + + +
+ + <function moreinfo="none">http_connect_raw(connection, url, content_type, data, result)</function> + + + Sends HTTP POST request to a given connection. + Similar to http_connect. + The only difference is that the data parameter will not be parsed for pseudo variables, + therefore it can safely be used for content that may contain "$" character like JSON. + + + + + connection - the name of an existing + HTTP connection, defined by a httpcon modparam. + + + url - the part of the URL to add to the + predefined URL in the connection definition. + + + content_type - Used only when posting + data with HTTP POST. An Internet Media type, like + "application/json" or "text/plain". Will be added to the + HTTP request as a header. + + + data - Data or a pseudo variable holding + data to be posted. (will not be parsed for pseudo variable) + + + result - The name of a pseudo variable that + will have the data of the response from the HTTP server. + + + + + The return value is the HTTP return code (if >=100) or the + CURL error code if below 100. See the $curlerror pseudovariable + below for more information about CURL error codes. + + + This function can be used from REQUEST_ROUTE, + ONREPLY_ROUTE, FAILURE_ROUTE, and BRANCH_ROUTE. + + + <function>http_connect_raw()</function> usage + +... +modparam("http_client", "httpcon", "apiserver=>http://kamailio.org/api/"); +... +# POST Request +$var(res) = http_connect_raw("apiserver", "/mailbox", "application/json", "{ ok, {200, ok}}", "$avp(gurka)"); +xlog("L_INFO", "API-server HTTP connection: $avp(gurka) Result code $var(res)\n"); + +$var(res) = http_connect_war("apiserver", "/callroute", "application/json", "$var(jsondata)", "$avp(route)"); +xlog("L_INFO", "API-server HTTP connection: $avp(route) Result code $var(res)\n"); ... diff --git a/src/modules/http_client/http_client.c b/src/modules/http_client/http_client.c index ecf04ba28b3..432d71a6c8e 100644 --- a/src/modules/http_client/http_client.c +++ b/src/modules/http_client/http_client.c @@ -120,9 +120,13 @@ static int fixup_free_http_query_post_hdr(void **param, int param_no); static int fixup_curl_connect(void **param, int param_no); static int fixup_free_curl_connect(void **param, int param_no); static int fixup_curl_connect_post(void **param, int param_no); +static int fixup_curl_connect_post_raw(void **param, int param_no); static int fixup_free_curl_connect_post(void **param, int param_no); +static int fixup_free_curl_connect_post_raw(void **param, int param_no); static int w_curl_connect_post(struct sip_msg *_m, char *_con, char *_url, char *_result, char *_ctype, char *_data); +static int w_curl_connect_post_raw(struct sip_msg *_m, char *_con, char *_url, + char *_result, char *_ctype, char *_data); static int fixup_curl_get_redirect(void **param, int param_no); static int fixup_free_curl_get_redirect(void **param, int param_no); @@ -161,6 +165,9 @@ static cmd_export_t cmds[] = { {"http_connect", (cmd_function)w_curl_connect_post, 5, fixup_curl_connect_post, fixup_free_curl_connect_post, REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, + {"http_connect_raw", (cmd_function)w_curl_connect_post_raw, 5, fixup_curl_connect_post_raw, + fixup_free_curl_connect_post_raw, + REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, {"http_get_redirect", (cmd_function)w_curl_get_redirect, 2, fixup_curl_get_redirect, fixup_free_curl_get_redirect, REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE}, @@ -482,6 +489,37 @@ static int fixup_curl_connect_post(void **param, int param_no) return -1; } +/* + * Fix curl_connect params when posting (5 parameters): + * connection (string/pvar), url (string with pvars), content-type, + * data (string(with no pvar parsing), pvar) + */ +static int fixup_curl_connect_post_raw(void **param, int param_no) +{ + + if(param_no == 1 || param_no == 3 || param_no == 4) { + /* We want char * strings */ + return 0; + } + /* URL and data may contain pvar */ + if(param_no == 2) { + return fixup_spve_null(param, 1); + } + if(param_no == 5) { + if(fixup_pvar_null(param, 1) != 0) { + LM_ERR("failed to fixup result pseudo variable\n"); + return -1; + } + if(((pv_spec_t *)(*param))->setf == NULL) { + LM_ERR("result pvar is not writeable\n"); + return -1; + } + return 0; + } + + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; +} /* * Free curl_connect params. @@ -504,6 +542,27 @@ static int fixup_free_curl_connect_post(void **param, int param_no) return -1; } +/* + * Free curl_connect params. + */ +static int fixup_free_curl_connect_post_raw(void **param, int param_no) +{ + if(param_no == 1 || param_no == 3 || param_no == 4) { + /* Char strings don't need freeing */ + return 0; + } + if(param_no == 2) { + return fixup_free_spve_null(param, 1); + } + + if(param_no == 5) { + return fixup_free_pvar_null(param, 1); + } + + LM_ERR("invalid parameter number <%d>\n", param_no); + return -1; +} + /* * Free curl_connect params. */ @@ -645,6 +704,44 @@ static int ki_curl_connect_post(sip_msg_t *_m, str *con, str *url, return ki_curl_connect_post_helper(_m, con, url, ctype, data, dst); } +/* + * Wrapper for Curl_connect (POST) raw data (no pvar parsing inside the data) + */ +static int w_curl_connect_post_raw(struct sip_msg *_m, char *_con, char *_url, + char *_ctype, char *_data, char *_result) +{ + str con = {NULL, 0}; + str url = {NULL, 0}; + str ctype = {NULL, 0}; + str data = {NULL, 0}; + pv_spec_t *dst; + + if(_con == NULL || _url == NULL || _ctype==NULL || _data == NULL + || _result == NULL) { + LM_ERR("http_connect: Invalid parameters\n"); + return -1; + } + con.s = _con; + con.len = strlen(con.s); + + if(get_str_fparam(&url, _m, (gparam_p)_url) != 0) { + LM_ERR("http_connect: URL has no value\n"); + return -1; + } + + ctype.s = _ctype; + ctype.len = strlen(ctype.s); + + data.s = _data; + data.len = strlen(data.s); + + LM_DBG("**** HTTP_CONNECT: Connection %s URL %s Result var %s\n", _con, + _url, _result); + dst = (pv_spec_t *)_result; + + return ki_curl_connect_post_helper(_m, &con, &url, &ctype, &data, dst); +} + /* * Wrapper for Curl_connect (POST) */ @@ -1058,4 +1155,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2) { sr_kemi_modules_add(sr_kemi_http_client_exports); return 0; -} \ No newline at end of file +}