Skip to content

Commit b6524e4

Browse files
committed
- new feature respTo desired $variableName and use it via return $variableName
- respTo directive will not write response out, instead, it store it into variable and use it later - Sample ngx_http_c_func_call "my_app_simple_get_greeting" respTo=myResponseVariable; return 200 $myResponseVariable;
1 parent 3d7d5ad commit b6524e4

File tree

5 files changed

+176
-16
lines changed

5 files changed

+176
-16
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ server {
3939
...
4040
...
4141
location = /testCFunGreeting {
42-
ngx_http_c_func_call "my_app_simple_get_greeting";
42+
# if not variable specified, direct write response out
43+
ngx_http_c_func_call "my_app_simple_get_greeting";
4344
}
4445
}
4546
@@ -50,7 +51,10 @@ server {
5051
...
5152
...
5253
location = /testCFunGreeting {
53-
ngx_http_c_func_call "my_app_simple_get_greeting";
54+
# if variable specified, not response write out, but it stored into myResponseVariable
55+
ngx_http_c_func_call "my_app_simple_get_greeting" respTo=myResponseVariable;
56+
57+
return 200 $myResponseVariable;
5458
}
5559
}
5660

build_test_resources/sanity_test_raw_parse.t

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Content-Type: text/plain
2626
--- response_body_like eval
2727
qr/greeting from ngx_http_c_func testing$/
2828

29+
2930
=== TEST 2: Set C_FUNC_TEST_ARGS
3031
--- config
3132
ngx_http_c_func_link_lib "NGINX_HTTP_C_FUNCTION_TEST_LIB_PATH/libcfuntest.so";
@@ -129,3 +130,35 @@ POST /testCFunGetCache
129130
Content-Type: text/plain
130131
--- response_body_like eval
131132
qr/This is cache value$/
133+
134+
135+
=== TEST 9: Set C_FUNC_TEST_VARIABLE
136+
--- config
137+
ngx_http_c_func_link_lib "NGINX_HTTP_C_FUNCTION_TEST_LIB_PATH/libcfuntest.so";
138+
location = /testCFunGreeting {
139+
ngx_http_c_func_call "my_app_simple_get_greeting" respTo=myRespVariable;
140+
return 200 $myRespVariable;
141+
}
142+
--- request
143+
GET /testCFunGreeting
144+
--- error_code: 200
145+
--- response_headers
146+
Content-Type: text/plain
147+
--- response_body_like eval
148+
qr/greeting from ngx_http_c_func testing$/
149+
150+
151+
=== TEST 10: Set C_FUNC_TEST_ARGS_AND_VARIABLE
152+
--- config
153+
ngx_http_c_func_link_lib "NGINX_HTTP_C_FUNCTION_TEST_LIB_PATH/libcfuntest.so";
154+
location = /testCFunARGS {
155+
ngx_http_c_func_call "my_app_simple_get_args" respTo=simpleRespVariable;
156+
return 200 $simpleRespVariable;
157+
}
158+
--- request
159+
GET /testCFunARGS?greeting=hello_nginx?id=129310923
160+
--- error_code: 200
161+
--- response_headers
162+
Content-Type: text/plain
163+
--- response_body_like eval
164+
qr/greeting=hello_nginx\?id=129310923$/

config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ngx_feature_incs="#include <ngx_http_c_func_module.h>"
2424
ngx_feature_path=
2525
ngx_feature_libs=
2626
# ngx_feature_exit_if_not_found=yes
27-
ngx_feature_test="int ngx_http_c_func_module_current_version_=ngx_http_c_func_module_version_7;"
27+
ngx_feature_test="int ngx_http_c_func_module_current_version_=ngx_http_c_func_module_version_8;"
2828
. auto/feature
2929

3030
if [ $ngx_found != yes ]; then

src/ngx_http_c_func_module.c

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,23 @@ typedef struct {
8282
typedef struct {
8383
ngx_str_t _method_name;
8484
ngx_http_c_func_app_handler _handler;
85+
ngx_flag_t _is_call_to_var;
8586
} ngx_http_c_func_loc_conf_t;
8687

8788
typedef struct {
8889
unsigned done: 1;
8990
unsigned waiting_more_body: 1;
91+
92+
/*** For store Response ***/
93+
size_t resp_len;
94+
u_char *resp;
9095
} ngx_http_c_func_internal_ctx_t;
9196

9297
typedef struct {
9398
ngx_queue_t _queue;
9499
ngx_http_c_func_loc_conf_t* _loc_conf;
95100
} ngx_http_c_func_loc_q_t;
96101

97-
98102
static ngx_int_t ngx_http_c_func_pre_configuration(ngx_conf_t *cf);
99103
static ngx_int_t ngx_http_c_func_post_configuration(ngx_conf_t *cf);
100104
static char* ngx_http_c_func_validation_check_and_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@@ -117,6 +121,8 @@ static void ngx_http_c_func_client_body_handler(ngx_http_request_t *r);
117121
static ngx_int_t ngx_http_c_func_proceed_init_calls(ngx_cycle_t* cycle, ngx_http_c_func_srv_conf_t *scf, ngx_http_c_func_main_conf_t* mcf);
118122
static u_char* ngx_http_c_func_strdup(ngx_pool_t *pool, const char *src, size_t len);
119123

124+
static ngx_int_t ngx_http_c_func_get_resp_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
125+
120126
/*** Download Feature Support ***/
121127
typedef struct {
122128
char* header_content;
@@ -160,6 +166,12 @@ void* ngx_http_c_func_cache_put(void *shared_mem, const char* key, void* value);
160166
void* ngx_http_c_func_cache_new(void *shared_mem, const char* key, size_t size);
161167
void* ngx_http_c_func_cache_remove(void *shared_mem, const char* key);
162168

169+
void
170+
ngx_http_c_func_set_resp_var(
171+
ngx_http_c_func_ctx_t *ctx,
172+
const char* resp_content
173+
);
174+
163175
void ngx_http_c_func_write_resp(
164176
ngx_http_c_func_ctx_t *ctx,
165177
uintptr_t status_code,
@@ -172,6 +184,7 @@ void ngx_http_c_func_write_resp(
172184
// ngx_http_c_func_srv_post_conf_handler
173185
// };
174186

187+
175188
/**
176189
* This module provided directive.
177190
*/
@@ -209,8 +222,7 @@ static ngx_command_t ngx_http_c_func_commands[] = {
209222
NULL
210223
},
211224
{ ngx_string("ngx_http_c_func_call"), /* directive */
212-
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, /* location context and takes
213-
no arguments*/
225+
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE12, /* location context and takes 1 or 2 arguments*/
214226
ngx_http_c_func_init_method, /* configuration setup function */
215227
NGX_HTTP_LOC_CONF_OFFSET, /* No offset. Only one context is supported. */
216228
offsetof(ngx_http_c_func_loc_conf_t, _method_name), /* No offset when storing the module configuration on struct. */
@@ -259,7 +271,8 @@ ngx_http_c_func_shm_cache_init(ngx_shm_zone_t *shm_zone, void *data)
259271
ngx_slab_pool_t *shpool;
260272

261273
if (oshm) {
262-
shm_zone->data = oshm;
274+
nshm->name = oshm->name;
275+
nshm->shared_mem = oshm->shared_mem;
263276
return NGX_OK;
264277
}
265278

@@ -418,18 +431,43 @@ ngx_http_c_func_validation_check_and_set_str_slot(ngx_conf_t *cf, ngx_command_t
418431
*/
419432
static char *
420433
ngx_http_c_func_init_method(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
421-
// ngx_str_t *value;
434+
ngx_str_t *value;
422435
ngx_http_core_loc_conf_t *clcf; /* pointer to core location configuration */
423436
ngx_http_c_func_srv_conf_t *scf;
424437
ngx_http_c_func_loc_conf_t *lcf = conf;
438+
ngx_str_t varname;
425439

426-
// value = cf->args->elts;
427440

428441
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
429442
scf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_c_func_module);
430443

444+
value = cf->args->elts;
445+
446+
if (cf->args->nelts == 3 &&
447+
value[2].len > sizeof("respTo=") - 1 &&
448+
ngx_strncmp(value[2].data, "respTo=", 6) == 0 ) {
449+
450+
lcf->_is_call_to_var = 1;
451+
452+
varname.data = value[2].data + sizeof("respTo=") - 1;
453+
varname.len = value[2].len - (sizeof("respTo=") - 1);
454+
455+
ngx_http_variable_t *var;
456+
var = ngx_http_add_variable(cf, &varname, NGX_HTTP_VAR_CHANGEABLE | NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH);
457+
if (var == NULL) {
458+
return NGX_CONF_ERROR;
459+
}
460+
var->get_handler = ngx_http_c_func_get_resp_var;
461+
var->data = 0;
462+
}
463+
464+
465+
431466
/***This handler is under NGX_HTTP_CONTENT_PHASE which is the phase ready to generate response ****/
432-
clcf->handler = ngx_http_c_func_content_handler;
467+
if (!lcf->_is_call_to_var) {
468+
clcf->handler = ngx_http_c_func_content_handler;
469+
}
470+
433471
if (scf && scf->_libname.len > 0) {
434472
ngx_http_c_func_loc_q_t *loc_q = ngx_pcalloc(cf->pool, sizeof(ngx_http_c_func_loc_q_t));
435473
loc_q->_loc_conf = lcf;
@@ -439,6 +477,7 @@ ngx_http_c_func_init_method(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
439477
return ngx_conf_set_str_slot(cf, cmd, conf);
440478
} /* ngx_http_c_func_init_method */
441479

480+
442481
static ngx_int_t
443482
ngx_http_c_func_proceed_init_calls(ngx_cycle_t* cycle, ngx_http_c_func_srv_conf_t *scf, ngx_http_c_func_main_conf_t* mcf) {
444483
/**** Init the client apps ngx_http_c_func_init ***/
@@ -503,7 +542,7 @@ ngx_http_c_func_post_configuration(ngx_conf_t *cf) {
503542
static ngx_int_t
504543
ngx_http_c_func_pre_configuration(ngx_conf_t *cf) {
505544

506-
#ifndef ngx_http_c_func_module_version_7
545+
#ifndef ngx_http_c_func_module_version_8
507546
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", "the latest ngx_http_c_func_module.h not found in the c header path, \
508547
please copy latest ngx_http_c_func_module.h to your /usr/include or /usr/local/include or relavent header search path \
509548
with read and write permission.");
@@ -701,6 +740,7 @@ ngx_http_c_func_master_exit(ngx_cycle_t *cycle) {
701740
return;
702741
}
703742

743+
704744
// if (cfunmcf->shm_ctx && cfunmcf->shm_ctx->shared_mem) {
705745
// if (cfunmcf->shm_ctx->shared_mem->shpool && cfunmcf->shm_ctx->shared_mem->shpool->log_ctx) {
706746
// ngx_slab_free(cfunmcf->shm_ctx->shared_mem->shpool, cfunmcf->shm_ctx->shared_mem->shpool->log_ctx);
@@ -800,6 +840,7 @@ ngx_http_c_func_create_loc_conf(ngx_conf_t *cf) {
800840
if (conf == NULL) {
801841
return NGX_CONF_ERROR;
802842
}
843+
conf->_is_call_to_var = 0;
803844
/***ngx_pcalloc has inited properly*/
804845
// conf->_method_name.len = NGX_CONF_UNSET_SIZE;
805846
return conf;
@@ -965,6 +1006,7 @@ ngx_http_c_func_content_handler(ngx_http_request_t *r) {
9651006
*/
9661007
static ngx_int_t
9671008
ngx_http_c_func_rewrite_handler(ngx_http_request_t *r) {
1009+
ngx_http_c_func_loc_conf_t *lcf = ngx_http_get_module_loc_conf(r, ngx_http_c_func_module);
9681010
ngx_http_c_func_internal_ctx_t *ctx;
9691011
ngx_int_t rc;
9701012

@@ -977,6 +1019,9 @@ ngx_http_c_func_rewrite_handler(ngx_http_request_t *r) {
9771019
if (ctx != NULL) {
9781020
if (ctx->done) {
9791021
/***Done Reading***/
1022+
if (lcf->_is_call_to_var) {
1023+
return ngx_http_c_func_content_handler(r);
1024+
}
9801025
return NGX_DECLINED;
9811026
}
9821027
return NGX_DONE;
@@ -990,6 +1035,8 @@ ngx_http_c_func_rewrite_handler(ngx_http_request_t *r) {
9901035
return NGX_HTTP_INTERNAL_SERVER_ERROR;
9911036
}
9921037

1038+
ctx->resp = NULL;
1039+
9931040
ngx_http_set_ctx(r, ctx, ngx_http_c_func_module);
9941041

9951042
/****Reading Body Request ****/
@@ -1007,8 +1054,26 @@ ngx_http_c_func_rewrite_handler(ngx_http_request_t *r) {
10071054
ctx->waiting_more_body = 1;
10081055
return NGX_DONE;
10091056
}
1057+
1058+
if (lcf->_is_call_to_var) {
1059+
return ngx_http_c_func_content_handler(r);
1060+
}
10101061
return NGX_DECLINED;
10111062
} else { //if (!(r->method & (NGX_HTTP_POST | NGX_HTTP_PUT | NGX_HTTP_PATCH))) {
1063+
ctx = ngx_http_get_module_ctx(r, ngx_http_c_func_module);
1064+
if (ctx == NULL) {
1065+
/* calloc, has init with 0 value*/
1066+
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_c_func_internal_ctx_t));
1067+
if (ctx == NULL) {
1068+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient Memory to create ngx_http_c_func_internal_ctx_t");
1069+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
1070+
}
1071+
ctx->resp = NULL;
1072+
ngx_http_set_ctx(r, ctx, ngx_http_c_func_module);
1073+
}
1074+
if (lcf->_is_call_to_var) {
1075+
return ngx_http_c_func_content_handler(r);
1076+
}
10121077
return NGX_DECLINED;
10131078
}
10141079
}
@@ -1259,6 +1324,50 @@ ngx_http_c_func_cache_remove(void *shared_mem, const char* key) {
12591324
return NULL;
12601325
}
12611326

1327+
/***This handler when nginx.conf call $ngx_c_func_resp*/
1328+
static ngx_int_t
1329+
ngx_http_c_func_get_resp_var(ngx_http_request_t *r,
1330+
ngx_http_variable_value_t *v, uintptr_t data)
1331+
{
1332+
ngx_http_c_func_internal_ctx_t *internal_ctx;
1333+
1334+
internal_ctx = ngx_http_get_module_ctx(r, ngx_http_c_func_module);
1335+
1336+
if (internal_ctx == NULL) {
1337+
v->not_found = 1;
1338+
return NGX_OK;
1339+
}
1340+
1341+
v->len = internal_ctx->resp_len;
1342+
v->valid = 1;
1343+
v->no_cacheable = 0;
1344+
v->not_found = 0;
1345+
v->data = internal_ctx->resp;
1346+
1347+
return NGX_OK;
1348+
}
1349+
1350+
void
1351+
ngx_http_c_func_set_resp_var(
1352+
ngx_http_c_func_ctx_t *ctx,
1353+
const char* resp_content
1354+
) {
1355+
ngx_http_c_func_internal_ctx_t *internal_ctx;
1356+
ngx_http_request_t *r = (ngx_http_request_t*)ctx->__r__;
1357+
internal_ctx = ngx_http_get_module_ctx(r, ngx_http_c_func_module);
1358+
1359+
if (internal_ctx != NULL) {
1360+
internal_ctx->resp_len = ngx_strlen(resp_content);
1361+
internal_ctx->resp = (u_char*)resp_content;
1362+
1363+
/** Decline means continue to next handler for this phase **/
1364+
ctx->__rc__ = NGX_DECLINED;
1365+
} else {
1366+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Error while storing resp to variable.");
1367+
ctx->__rc__ = NGX_HTTP_INTERNAL_SERVER_ERROR;
1368+
}
1369+
}
1370+
12621371
void
12631372
ngx_http_c_func_write_resp(
12641373
ngx_http_c_func_ctx_t *ctx,
@@ -1271,6 +1380,15 @@ ngx_http_c_func_write_resp(
12711380
ngx_chain_t out;
12721381
size_t resp_content_len;
12731382
ngx_http_request_t *r = (ngx_http_request_t*)ctx->__r__;
1383+
1384+
if ( ((ngx_http_c_func_loc_conf_t*) ngx_http_get_module_loc_conf(r, ngx_http_c_func_module) )->_is_call_to_var ) {
1385+
ngx_log_error(NGX_LOG_WARN,
1386+
r->connection->log,
1387+
0,
1388+
", \n Recommended to call ngx_http_c_func_set_resp_var. \n ngx_http_c_func_write_resp only applicable when no variable stored");
1389+
return ngx_http_c_func_set_resp_var(ctx, resp_content);
1390+
}
1391+
12741392
/* Set the Content-Type header. */
12751393
if (content_type) {
12761394
r->headers_out.content_type.len = ngx_strlen(content_type);

src/ngx_http_c_func_module.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88
* @section LICENSE
99
*
1010
* Copyright (c) 2018, Taymindis <cloudleware2015@gmail.com>
11-
*
11+
*
1212
* This module is licensed under the terms of the BSD license.
13-
*
13+
*
1414
* Redistribution and use in source and binary forms, with or without
1515
* modification, are permitted provided that the following conditions are met:
16-
*
16+
*
1717
* 1. Redistributions of source code must retain the above copyright notice, this
1818
* list of conditions and the following disclaimer.
1919
* 2. Redistributions in binary form must reproduce the above copyright notice,
2020
* this list of conditions and the following disclaimer in the documentation
2121
* and/or other materials provided with the distribution.
22-
*
22+
*
2323
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2424
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2525
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -35,7 +35,7 @@
3535
#include <stdlib.h>
3636
#include <stdint.h>
3737

38-
#define ngx_http_c_func_module_version_7 7
38+
#define ngx_http_c_func_module_version_8 8
3939

4040

4141
#define ngx_http_c_func_content_type_plaintext "text/plain"
@@ -82,6 +82,11 @@ extern void ngx_http_c_func_write_resp(
8282
const char* resp_content
8383
);
8484

85+
extern void ngx_http_c_func_set_resp_var(
86+
ngx_http_c_func_ctx_t *ctx,
87+
const char* resp_content
88+
);
89+
8590
// Shared Memory and Cache Scope
8691
extern uintptr_t ngx_http_c_func_shmtx_trylock(void *shared_mem);
8792
extern void ngx_http_c_func_shmtx_lock(void *shared_mem);

0 commit comments

Comments
 (0)