Explorar o código

http_async_client: set request's body through $http_req pseudovariable

Federico Cabiddu %!s(int64=9) %!d(string=hai) anos
pai
achega
61adc6e16c

+ 31 - 11
modules/http_async_client/async_http.c

@@ -219,7 +219,6 @@ void notification_socket_cb(int fd, short event, void *arg)
 	http_m_params_t query_params;
 	http_m_params_t query_params;
 
 
 	str query;
 	str query;
-	str post;
 
 
 	if ((received = recvfrom(worker->notication_socket[0],
 	if ((received = recvfrom(worker->notication_socket[0],
 			&aq, sizeof(async_query_t*),
 			&aq, sizeof(async_query_t*),
@@ -234,7 +233,6 @@ void notification_socket_cb(int fd, short event, void *arg)
 	}
 	}
 
 
 	query = ((str)aq->query);
 	query = ((str)aq->query);
-	post = ((str)aq->post);
 
 
 	query_params.timeout = aq->query_params.timeout;
 	query_params.timeout = aq->query_params.timeout;
 	query_params.tls_verify_peer = aq->query_params.tls_verify_peer;
 	query_params.tls_verify_peer = aq->query_params.tls_verify_peer;
@@ -272,9 +270,18 @@ void notification_socket_cb(int fd, short event, void *arg)
 		}
 		}
 	}
 	}
 
 
+	query_params.body.s = NULL;
+	query_params.body.len = 0;
+	if (aq->query_params.body.s && aq->query_params.body.len > 0) {
+		if (shm_str_dup(&query_params.body, &(aq->query_params.body)) < 0) {
+			LM_ERR("Error allocating query_params.body\n");
+			return;
+		}
+	}
+
 	LM_DBG("query received: [%.*s] (%p)\n", query.len, query.s, aq);
 	LM_DBG("query received: [%.*s] (%p)\n", query.len, query.s, aq);
 
 
-	if (new_request(&query, &post, &query_params, async_http_cb, aq) < 0) {
+	if (new_request(&query, &query_params, async_http_cb, aq) < 0) {
 		LM_ERR("Cannot create request for %.*s\n", query.len, query.s);
 		LM_ERR("Cannot create request for %.*s\n", query.len, query.s);
 		free_async_query(aq);
 		free_async_query(aq);
 	}
 	}
@@ -294,6 +301,11 @@ void notification_socket_cb(int fd, short event, void *arg)
 		query_params.tls_ca_path.s = NULL;
 		query_params.tls_ca_path.s = NULL;
 		query_params.tls_ca_path.len = 0;
 		query_params.tls_ca_path.len = 0;
 	}
 	}
+	if (query_params.body.s && query_params.body.len > 0) {
+		shm_free(query_params.body.s);
+		query_params.body.s = NULL;
+		query_params.body.len = 0;
+	}
 
 
 	return;
 	return;
 }
 }
@@ -305,7 +317,7 @@ int init_socket(async_http_worker_t *worker)
 	return (0);
 	return (0);
 }
 }
 
 
-int async_send_query(sip_msg_t *msg, str *query, str *post, cfg_action_t *act)
+int async_send_query(sip_msg_t *msg, str *query, cfg_action_t *act)
 {
 {
 	async_query_t *aq;
 	async_query_t *aq;
 	unsigned int tindex = 0;
 	unsigned int tindex = 0;
@@ -353,13 +365,6 @@ int async_send_query(sip_msg_t *msg, str *query, str *post, cfg_action_t *act)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	if (post != NULL) {
-
-		if(shm_str_dup(&aq->post, post)<0) {
-			goto error;
-		}
-	}
-
 	aq->param = act;
 	aq->param = act;
 	aq->tindex = tindex;
 	aq->tindex = tindex;
 	aq->tlabel = tlabel;
 	aq->tlabel = tlabel;
@@ -402,6 +407,15 @@ int async_send_query(sip_msg_t *msg, str *query, str *post, cfg_action_t *act)
 		}
 		}
 	}
 	}
 
 
+	aq->query_params.body.s = NULL;
+	aq->query_params.body.len = 0;
+	if (ah_params.body.s && ah_params.body.len > 0) {
+		if (shm_str_dup(&aq->query_params.body, &(ah_params.body)) < 0) {
+			LM_ERR("Error allocating aq->query_params.body\n");
+			goto error;
+		}
+	}
+
 	set_query_params(&ah_params);
 	set_query_params(&ah_params);
 
 
 	if(async_push_query(aq)<0) {
 	if(async_push_query(aq)<0) {
@@ -495,6 +509,12 @@ void set_query_params(struct query_params *p) {
 			return;
 			return;
 		}
 		}
 	}
 	}
+
+	if (p->body.s && p->body.len > 0) {
+		shm_free(p->body.s);
+		p->body.s = NULL;
+		p->body.len = 0;
+	}
 }
 }
 
 
 int header_list_add(struct header_list *hl, str* hdr) {
 int header_list_add(struct header_list *hl, str* hdr) {

+ 8 - 8
modules/http_async_client/async_http.h

@@ -91,13 +91,13 @@ struct query_params {
 	str tls_client_cert;
 	str tls_client_cert;
 	str tls_client_key;
 	str tls_client_key;
 	str tls_ca_path;
 	str tls_ca_path;
+	str body;
 };
 };
 
 
 extern struct query_params ah_params;
 extern struct query_params ah_params;
 
 
 typedef struct async_query {
 typedef struct async_query {
 	str query;
 	str query;
-	str post;
 	char id[MAX_ID_LEN+1];
 	char id[MAX_ID_LEN+1];
 	unsigned int tindex;
 	unsigned int tindex;
 	unsigned int tlabel;
 	unsigned int tlabel;
@@ -109,7 +109,7 @@ int async_http_init_sockets(async_http_worker_t *worker);
 int async_http_init_worker(int prank, async_http_worker_t* worker);
 int async_http_init_worker(int prank, async_http_worker_t* worker);
 void async_http_run_worker(async_http_worker_t* worker);
 void async_http_run_worker(async_http_worker_t* worker);
 
 
-int async_send_query(sip_msg_t *msg, str *query, str *post, cfg_action_t *act);
+int async_send_query(sip_msg_t *msg, str *query, cfg_action_t *act);
 int async_push_query(async_query_t *aq);
 int async_push_query(async_query_t *aq);
 
 
 void notification_socket_cb(int fd, short event, void *arg);
 void notification_socket_cb(int fd, short event, void *arg);
@@ -132,12 +132,6 @@ static inline void free_async_query(async_query_t *aq)
 		aq->query.len=0;
 		aq->query.len=0;
 	}
 	}
 
 
-	if (aq->post.s && aq->post.len) {
-		shm_free(aq->post.s);
-		aq->post.s=0;
-		aq->post.len=0;
-	}
-
 	if(aq->query_params.headers.t) {
 	if(aq->query_params.headers.t) {
 		while(aq->query_params.headers.len--)
 		while(aq->query_params.headers.len--)
 			shm_free(aq->query_params.headers.t[aq->query_params.headers.len]);
 			shm_free(aq->query_params.headers.t[aq->query_params.headers.len]);
@@ -162,6 +156,12 @@ static inline void free_async_query(async_query_t *aq)
 		aq->query_params.tls_ca_path.len = 0;
 		aq->query_params.tls_ca_path.len = 0;
 	}
 	}
 
 
+	if (aq->query_params.body.s && aq->query_params.body.len > 0) {
+		shm_free(aq->query_params.body.s);
+		aq->query_params.body.s = NULL;
+		aq->query_params.body.len = 0;
+	}
+
 	shm_free(aq);
 	shm_free(aq);
 }
 }
 
 

+ 3 - 8
modules/http_async_client/doc/http_async_client_admin.xml

@@ -300,17 +300,11 @@ modparam("http_async_client", "tls_ca_path", "/etc/kamailio/ssl/ca/")
 	<title>Functions</title>
 	<title>Functions</title>
 	<section id="http_async_client.f.http_async_query">
 	<section id="http_async_client.f.http_async_query">
 	    <title>
 	    <title>
-		<function moreinfo="none">http_async_query(url, [post_data], route_name)</function>
+		<function moreinfo="none">http_async_query(url, route_name)</function>
 	    </title>
 	    </title>
         <para>
         <para>
             Sends HTTP(S) request asyncronously to the URL given in <quote>url</quote> parameter, which is a string that may contain pseudo variables.
             Sends HTTP(S) request asyncronously to the URL given in <quote>url</quote> parameter, which is a string that may contain pseudo variables.
         </para>
         </para>
-        <para>
-            Unless a specific HTTP method was specified using <emphasis>http_async_set_method()</emphasis>, it defaults to a GET request, or to a POST request if <quote>post_data</quote> is provided as second argument.
-        </para>
-        <para>
-            Parameter <quote>post_data</quote>, optional, which is sent as the body of the request, may also contain pseudo variables.
-        </para>
         <para>
         <para>
 			Parameter <quote>route_name</quote> defines the route to be executed upon reception of HTTP reply, on error or on timeout. 
 			Parameter <quote>route_name</quote> defines the route to be executed upon reception of HTTP reply, on error or on timeout. 
 			If a transaction exists before calling <emphasis>http_async_query()</emphasis>, it will be paused and resumed in this route, while the routing script execution will be stopped.
 			If a transaction exists before calling <emphasis>http_async_query()</emphasis>, it will be paused and resumed in this route, while the routing script execution will be stopped.
@@ -588,7 +582,8 @@ xlog("L_INFO", "received reply for query $http_query_id\n");
 	<para><literal>key</literal> can be one of:</para>
 	<para><literal>key</literal> can be one of:</para>
 	<itemizedlist>
 	<itemizedlist>
 		<listitem><para><emphasis>all</emphasis>: if set to <literal>$null</literal>, resets all the parameters to their default value (the ones defined in modparam)</para></listitem>
 		<listitem><para><emphasis>all</emphasis>: if set to <literal>$null</literal>, resets all the parameters to their default value (the ones defined in modparam)</para></listitem>
-		<listitem><para><emphasis>hdr</emphasis>: sets/modifies/remove a HTTP header (see <emphasis>http_append_header()</emphasis>). N.B.: setting this variable multiple times will add several headers to the query.</para></listitem>
+		<listitem><para><emphasis>hdr</emphasis>: sets/modifies/removes a HTTP header (see <emphasis>http_append_header()</emphasis>). N.B.: setting this variable multiple times will add several headers to the query.</para></listitem>
+		<listitem><para><emphasis>body</emphasis>: sets/modifies/removes the request body</para></listitem>
 		<listitem><para><emphasis>method</emphasis>: sets the HTTP method (see <emphasis>http_set_method()</emphasis>)</para></listitem>
 		<listitem><para><emphasis>method</emphasis>: sets the HTTP method (see <emphasis>http_set_method()</emphasis>)</para></listitem>
 		<listitem><para><emphasis>timeout</emphasis>: sets the HTTP timeout (see <emphasis>http_set_timeout()</emphasis>)</para></listitem>
 		<listitem><para><emphasis>timeout</emphasis>: sets the HTTP timeout (see <emphasis>http_set_timeout()</emphasis>)</para></listitem>
 		<listitem><para><emphasis>tls_client_cert</emphasis>: sets the client certificate to use (see <emphasis>http_set_tls_client_cert()</emphasis>)</para></listitem>
 		<listitem><para><emphasis>tls_client_cert</emphasis>: sets the client certificate to use (see <emphasis>http_set_tls_client_cert()</emphasis>)</para></listitem>

+ 0 - 4
modules/http_async_client/hm_hash.c

@@ -184,10 +184,6 @@ void free_http_m_cell(struct http_m_cell *cell)
 
 
 	if (cell->url) shm_free(cell->url);
 	if (cell->url) shm_free(cell->url);
 
 
-	if (cell->post_data) {
-		shm_free(cell->post_data);
-	}
-
 	shm_free(cell);
 	shm_free(cell);
 }
 }
 
 

+ 1 - 1
modules/http_async_client/hm_hash.h

@@ -73,6 +73,7 @@ typedef struct hm_params {
 	str tls_client_cert;
 	str tls_client_cert;
 	str tls_client_key;
 	str tls_client_key;
 	str tls_ca_path;
 	str tls_ca_path;
+	str body;
 } http_m_params_t;
 } http_m_params_t;
 
 
 typedef struct http_m_cell
 typedef struct http_m_cell
@@ -93,7 +94,6 @@ typedef struct http_m_cell
 	int evset;
 	int evset;
 
 
 	char *url;
 	char *url;
-	char *post_data;
 	char error[CURL_ERROR_SIZE];
 	char error[CURL_ERROR_SIZE];
 
 
 	http_multi_cbe_t cb;
 	http_multi_cbe_t cb;

+ 22 - 83
modules/http_async_client/http_async_client_mod.c

@@ -80,8 +80,7 @@ static int  mod_init(void);
 static int  child_init(int);
 static int  child_init(int);
 static void mod_destroy(void);
 static void mod_destroy(void);
 
 
-static int w_http_async_get(sip_msg_t* msg, char* query, char* rt);
-static int w_http_async_post(sip_msg_t* msg, char* query, char* post, char* rt);
+static int w_http_async_query(sip_msg_t* msg, char* query, char* rt);
 static int w_tls_verify_host(sip_msg_t* msg, char* vh, char*);
 static int w_tls_verify_host(sip_msg_t* msg, char* vh, char*);
 static int w_tls_verify_peer(sip_msg_t* msg, char* vp, char*);
 static int w_tls_verify_peer(sip_msg_t* msg, char* vp, char*);
 static int w_http_async_suspend_transaction(sip_msg_t* msg, char* vp, char*);
 static int w_http_async_suspend_transaction(sip_msg_t* msg, char* vp, char*);
@@ -92,8 +91,7 @@ static int w_http_set_tls_client_cert(sip_msg_t* msg, char* sc, char*);
 static int w_http_set_tls_client_key(sip_msg_t* msg, char* sk, char*);
 static int w_http_set_tls_client_key(sip_msg_t* msg, char* sk, char*);
 static int w_http_set_tls_ca_path(sip_msg_t* msg, char* cp, char*);
 static int w_http_set_tls_ca_path(sip_msg_t* msg, char* cp, char*);
 static int set_query_param(str* param, str input);
 static int set_query_param(str* param, str input);
-static int fixup_http_async_get(void** param, int param_no);
-static int fixup_http_async_post(void** param, int param_no);
+static int fixup_http_async_query(void** param, int param_no);
 
 
 /* pv api binding */
 /* pv api binding */
 static int ah_get_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
 static int ah_get_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
@@ -129,13 +127,12 @@ enum http_req_name_t {
 	E_HRN_ALL = 0,
 	E_HRN_ALL = 0,
 	E_HRN_HDR, E_HRN_METHOD, E_HRN_TIMEOUT,
 	E_HRN_HDR, E_HRN_METHOD, E_HRN_TIMEOUT,
 	E_HRN_TLS_CA_PATH, E_HRN_TLS_CLIENT_KEY,
 	E_HRN_TLS_CA_PATH, E_HRN_TLS_CLIENT_KEY,
-	E_HRN_TLS_CLIENT_CERT, E_HRN_SUSPEND
+	E_HRN_TLS_CLIENT_CERT, E_HRN_SUSPEND,
+	E_HRN_BODY
 };
 };
 
 
 static cmd_export_t cmds[]={
 static cmd_export_t cmds[]={
-	{"http_async_query",  (cmd_function)w_http_async_get, 2, fixup_http_async_get,
-		0, ANY_ROUTE},
-	{"http_async_query", (cmd_function)w_http_async_post, 3, fixup_http_async_post,
+	{"http_async_query",  (cmd_function)w_http_async_query, 2, fixup_http_async_query,
 		0, ANY_ROUTE},
 		0, ANY_ROUTE},
 	{"tls_verify_host", (cmd_function)w_tls_verify_host, 1, fixup_igp_all,
 	{"tls_verify_host", (cmd_function)w_tls_verify_host, 1, fixup_igp_all,
 		0, ANY_ROUTE},
 		0, ANY_ROUTE},
@@ -408,7 +405,7 @@ static void mod_destroy(void)
 /**
 /**
  *
  *
  */
  */
-static int w_http_async_get(sip_msg_t *msg, char *query, char* rt)
+static int w_http_async_query(sip_msg_t *msg, char *query, char* rt)
 {
 {
 	str sdata;
 	str sdata;
 	cfg_action_t *act;
 	cfg_action_t *act;
@@ -446,66 +443,10 @@ static int w_http_async_get(sip_msg_t *msg, char *query, char* rt)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	return async_send_query(msg, &sdata, NULL, act);
+	return async_send_query(msg, &sdata, act);
 
 
 }
 }
 
 
-/**
- *
- */
-static int w_http_async_post(sip_msg_t *msg, char *query, char* post, char* rt)
-{
-	str sdata;
-	str post_data;
-	cfg_action_t *act;
-	str rn;
-	int ri;
-
-	if(msg==NULL)
-		return -1;
-
-	if(fixup_get_svalue(msg, (gparam_t*)query, &sdata)!=0) {
-		LM_ERR("unable to get data\n");
-		return -1;
-	}
-
-	if(sdata.s==NULL || sdata.len == 0) {
-		LM_ERR("invalid data parameter\n");
-		return -1;
-	}
-
-	if(fixup_get_svalue(msg, (gparam_t*)post, &post_data)!=0) {
-		LM_ERR("unable to get post data\n");
-		return -1;
-	}
-
-	if(post_data.s==NULL || post_data.len == 0) {
-		LM_ERR("invalid post data parameter\n");
-		return -1;
-	}
-
-	if(fixup_get_svalue(msg, (gparam_t*)rt, &rn)!=0)
-	{
-		LM_ERR("no route block name\n");
-		return -1;
-	}
-
-	ri = route_get(&main_rt, rn.s);
-	if(ri<0)
-	{
-		LM_ERR("unable to find route block [%.*s]\n", rn.len, rn.s);
-		return -1;
-	}
-	act = main_rt.rlist[ri];
-	if(act==NULL)
-	{
-		LM_ERR("empty action lists in route block [%.*s]\n", rn.len, rn.s);
-		return -1;
-	}
-
-	return async_send_query(msg, &sdata, &post_data, act);
-}
-
 #define _IVALUE_ERROR(NAME) LM_ERR("invalid parameter '" #NAME "' (must be a number)\n")
 #define _IVALUE_ERROR(NAME) LM_ERR("invalid parameter '" #NAME "' (must be a number)\n")
 #define _IVALUE(NAME)\
 #define _IVALUE(NAME)\
 int i_##NAME ;\
 int i_##NAME ;\
@@ -635,7 +576,7 @@ static int set_query_param(str* param, str input)
 /**
 /**
  *
  *
  */
  */
-static int fixup_http_async_get(void** param, int param_no)
+static int fixup_http_async_query(void** param, int param_no)
 {
 {
 	if (param_no == 1) {
 	if (param_no == 1) {
 		return fixup_spve_null(param, 1);
 		return fixup_spve_null(param, 1);
@@ -648,22 +589,6 @@ static int fixup_http_async_get(void** param, int param_no)
 	return -1;
 	return -1;
 }
 }
 
 
-/**
- *
- */
-static int fixup_http_async_post(void** param, int param_no)
-{
-	if (param_no == 1 || param_no == 2) {
-		return fixup_spve_null(param, 1);
-	}
-	if (param_no == 3) {
-		return fixup_var_str_12(param, param_no);
-	}
-
-	LM_ERR("invalid parameter number <%d>\n", param_no);
-	return -1;
-}
-
 /* module PVs */
 /* module PVs */
 
 
 #define AH_WRAP_GET_PV(AH_F, PV_F) static int AH_F(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) \
 #define AH_WRAP_GET_PV(AH_F, PV_F) static int AH_F(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) \
@@ -736,6 +661,11 @@ static int ah_parse_req_name(pv_spec_p sp, str *in) {
 				sp->pvp.pvn.u.isname.name.n = E_HRN_HDR;
 				sp->pvp.pvn.u.isname.name.n = E_HRN_HDR;
 			else goto error;
 			else goto error;
 			break;
 			break;
+		case 4:
+			if(strncmp(in->s, "body", 4)==0)
+				sp->pvp.pvn.u.isname.name.n = E_HRN_BODY;
+			else goto error;
+			break;
 		case 6:
 		case 6:
 			if(strncmp(in->s, "method", 6)==0)
 			if(strncmp(in->s, "method", 6)==0)
 				sp->pvp.pvn.u.isname.name.n = E_HRN_METHOD;
 				sp->pvp.pvn.u.isname.name.n = E_HRN_METHOD;
@@ -869,6 +799,15 @@ static int ah_set_req(struct sip_msg* msg, pv_param_t *param,
 			ah_params.suspend_transaction = 1;
 			ah_params.suspend_transaction = 1;
 		}
 		}
 		break;
 		break;
+	case E_HRN_BODY:
+		if (tval) {
+			if (!(tval->flags & PV_VAL_STR)) {
+				LM_ERR("invalid value type for $http_req(body)\n");
+				return -1;
+			}
+			set_query_param(&ah_params.body, tval->rs);
+		}
+		break;
 	}
 	}
 
 
 	return 1;
 	return 1;

+ 4 - 11
modules/http_async_client/http_multi.c

@@ -412,7 +412,7 @@ int init_http_multi(struct event_base *evbase, struct http_m_global *wg)
 	return init_http_m_table(hash_size);
 	return init_http_m_table(hash_size);
 }
 }
 
 
-int new_request(str *query, str *post, http_m_params_t *query_params, http_multi_cbe_t cb, void *param)
+int new_request(str *query, http_m_params_t *query_params, http_multi_cbe_t cb, void *param)
 {
 {
 
 
 	LM_DBG("received query %.*s with timeout %d, tls_verify_peer %d, tls_verify_host %d (param=%p)\n", 
 	LM_DBG("received query %.*s with timeout %d, tls_verify_peer %d, tls_verify_host %d (param=%p)\n", 
@@ -490,16 +490,9 @@ int new_request(str *query, str *post, http_m_params_t *query_params, http_multi
 		curl_easy_setopt(cell->easy, CURLOPT_HTTPHEADER, cell->params.headers);
 		curl_easy_setopt(cell->easy, CURLOPT_HTTPHEADER, cell->params.headers);
 	}
 	}
 
 
-	if (post && post->s && post->len) {
-		curl_easy_setopt(cell->easy, CURLOPT_POST, 1L);
-		cell->post_data = shm_malloc(post->len + 1);
-		if (cell->post_data == NULL) {
-			LM_ERR("cannot allocate pkg memory for post\n");
-			goto error;
-		}
-		strncpy(cell->post_data, post->s, post->len);
-		cell->post_data[post->len] = '\0';
-		curl_easy_setopt(cell->easy, CURLOPT_POSTFIELDS, cell->post_data);
+	if (cell->params.body.s && cell->params.body.len) {
+		curl_easy_setopt(cell->easy, CURLOPT_POSTFIELDSIZE, (long)cell->params.body.len);
+		curl_easy_setopt(cell->easy, CURLOPT_COPYPOSTFIELDS, cell->params.body.s);
 	}
 	}
 
 
 	switch (cell->params.method) {
 	switch (cell->params.method) {

+ 1 - 1
modules/http_async_client/http_multi.h

@@ -61,7 +61,7 @@ int multi_timer_cb(CURLM *multi, long timeout_ms, struct http_m_global *g);
 void timer_cb(int fd, short kind, void *userp);
 void timer_cb(int fd, short kind, void *userp);
 int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp);
 int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp);
 int check_mcode(CURLMcode code, char *error);
 int check_mcode(CURLMcode code, char *error);
-int new_request(str *query, str *post, http_m_params_t *query_params, http_multi_cbe_t cb, void *param);
+int new_request(str *query, http_m_params_t *query_params, http_multi_cbe_t cb, void *param);
 void check_multi_info(struct http_m_global *g);
 void check_multi_info(struct http_m_global *g);
 void setsock(struct http_m_cell *cell, curl_socket_t s, CURL* e, int act);
 void setsock(struct http_m_cell *cell, curl_socket_t s, CURL* e, int act);
 void addsock(curl_socket_t s, CURL *easy, int action, struct http_m_global *g);
 void addsock(curl_socket_t s, CURL *easy, int action, struct http_m_global *g);