From 4f4f39f05a0a97a85fcfa2d4aab744501bb1e10c Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 10:21:13 +0800 Subject: [PATCH 1/8] invoke python app with hard-coded env var --- .gitignore | 5 +- config | 12 +- src/ngx_http_asgi_module.c | 207 +++++++++++++++++++++++----------- test/resource/example.py | 14 +++ test/resource/nginx.test.conf | 3 +- 5 files changed, 171 insertions(+), 70 deletions(-) create mode 100644 test/resource/example.py diff --git a/.gitignore b/.gitignore index 600d2d3..9be1c21 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.vscode \ No newline at end of file +.vscode +.* +_build/ +__pycache__/ diff --git a/config b/config index f94066e..6104c92 100644 --- a/config +++ b/config @@ -1,3 +1,9 @@ -ngx_addon_name=ngx_http_asgi_module -HTTP_MODULES="$HTTP_MODULES ngx_http_asgi_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_asgi_module.c" +ngx_module_type=HTTP +ngx_module_name=ngx_http_asgi_module +ngx_module_incs="/usr/include/python3.9/ $ngx_addon_dir/src" +ngx_module_libs="-lpython3.9 -lcrypt -lpthread -ldl -lutil -lm" +ngx_module_srcs="$ngx_addon_dir/src/ngx_http_asgi_module.c" + +. auto/module + +ngx_addon_name=$ngx_module_name \ No newline at end of file diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 7484b25..1a5bc3e 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -7,19 +7,32 @@ #include #include #include +#include +#include typedef struct { - ngx_str_t python_file; - ngx_str_t app_name; -} ngx_http_asgi_loc_conf_t; + // const char *app_folder; + const char *py_module; + const char *app_name; +} ngx_http_asgi_conf_t; static ngx_int_t ngx_http_asgi_init(ngx_conf_t *cf); static void *ngx_http_asgi_create_loc_conf(ngx_conf_t *cf); +// static char *ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r); +static const char * to_null_terminated_string(ngx_str_t n_string, ngx_pool_t *pool); +static ngx_int_t ngx_http_asgi_init_process(ngx_cycle_t *cycle); static ngx_command_t ngx_http_asgi_commands[] = { + // { + // ngx_string("asgi_app_path"), + // NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + // ngx_http_asgi_set_path, + // NGX_HTTP_LOC_CONF_OFFSET, + // 0, + // NULL }, { ngx_string("asgi_app"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, @@ -42,17 +55,27 @@ static ngx_http_module_t ngx_http_asgi_module_ctx = { NULL /* merge location configuration */ }; -static void *ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_asgi_loc_conf_t* local_conf = NULL; - local_conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_loc_conf_t)); - if (local_conf != NULL) - { - ngx_str_null(&local_conf->python_file); - ngx_str_null(&local_conf->app_name); - } +ngx_module_t ngx_http_asgi_module = { + NGX_MODULE_V1, + &ngx_http_asgi_module_ctx, /* module context */ + ngx_http_asgi_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + ngx_http_asgi_init_process, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; - return local_conf; +static void * +ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_asgi_conf_t* loc_cf = NULL; + loc_cf = ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); + return loc_cf; } static ngx_int_t @@ -60,94 +83,148 @@ ngx_http_asgi_init(ngx_conf_t *cf) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf; - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); if (h == NULL) { - return NGX_ERROR; + return NGX_ERROR; } - *h = ngx_http_asgi_handler; - return NGX_OK; }; -ngx_module_t ngx_http_asgi_module = { - NGX_MODULE_V1, - &ngx_http_asgi_module_ctx, /* module context */ - ngx_http_asgi_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; +// static char * +// ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +// { +// ngx_str_t *params = cf->args->elts; +// if (params[1].len == 0) { +// ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app_path' doesn't take empty parameters"); +// return NGX_CONF_ERROR; +// } +// ngx_http_asgi_conf_t* c = conf; +// c->app_folder = to_null_terminated_string(params[1], cf->pool); + +// // ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Set ASGI app path: %s", buf); +// return NGX_CONF_OK; +// } static char * ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *params = cf->args->elts; - if (params[1].len == 0 || params[2].len == 0) - { + if (params[1].len == 0 || params[2].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app' doesn't take empty parameters"); return NGX_CONF_ERROR; } - - ngx_http_asgi_loc_conf_t* local_conf = conf; - local_conf->python_file = params[1]; - local_conf->app_name = params[2]; + ngx_http_asgi_conf_t* c = conf; + c->py_module = to_null_terminated_string(params[1], cf->pool); + c->app_name = to_null_terminated_string(params[2], cf->pool); return NGX_CONF_OK; } +static ngx_int_t +ngx_http_asgi_init_process(ngx_cycle_t *cycle) +{ + // ngx_http_asgi_conf_t *cf; + // cf = (ngx_http_asgi_conf_t *) ngx_http_cycle_get_module_main_conf(cycle, ngx_http_asgi_module); // ngx_get_conf(cycle->conf_ctx, ngx_http_asgi_module); + + if (!Py_IsInitialized()) { + // char buf[1024]; + // sprintf(buf, "%s:${PYTHONPATH}", cf->app_folder); + setenv("PYTHONPATH", "/home/rim99/Projects/cpp/nginx-http-asgi-module/test/resource:${PYTHONPATH}", 1); + // ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "set Path: %s", buf); + Py_Initialize(); + } + return NGX_OK; +} + +static const char * to_null_terminated_string(ngx_str_t n_string, ngx_pool_t *pool) { + char *dst = ngx_pcalloc(pool, (n_string.len + 1) * sizeof(char)); + u_char *src = n_string.data; + for (size_t i = 0; i < n_string.len; i++) { + dst[i] = (char) src[i]; + } + + dst[n_string.len] = '\0'; + return dst; +} + +u_char * +execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) +{ + u_char *rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); + PyObject *pModule, *pFunc, *pArgs, *pValue; + u_char * py_ret; + + pModule = PyImport_ImportModule(py_module); + if (pModule == NULL) { + // TODO: error happen + ngx_sprintf(rt, "{\"error\":\"connot find module %s\"}", py_module); + goto ret; + } + pFunc = PyObject_GetAttrString(pModule, app_name); + if (pFunc == NULL) { + // TODO: error happen + Py_XDECREF(pFunc); + ngx_sprintf(rt, "{\"error\":\"connot find app\"}"); + goto ret; + } + if (!PyCallable_Check(pFunc)) { + // TODO: not function + Py_XDECREF(pFunc); + ngx_sprintf(rt, "{\"error\":\"app is not callable\"}"); + goto ret; + } + pArgs = PyTuple_New(0); + pValue = PyObject_CallObject(pFunc, pArgs); + Py_DECREF(pArgs); + py_ret = (u_char *) PyUnicode_AsUTF8(pValue); + if (pValue == NULL) { + // ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "python error: app returns NULL"); + Py_DECREF(pValue); + ngx_sprintf(rt, "{\"error\":\"result is NULL\"}"); + } + Py_XDECREF(pFunc); + Py_DECREF(pModule); + + // ngx_sprintf(rt, "{\"hello\":\"from Python\"}"); + rt = py_ret; + + ret: + return rt; + +} + + + static ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; - ngx_http_asgi_loc_conf_t* my_conf; - u_char ngx_asgi_json[512] = {0}; + ngx_http_asgi_conf_t* cf = ngx_http_get_module_loc_conf(r, ngx_http_asgi_module); ngx_uint_t content_length = 0; - my_conf = ngx_http_get_module_loc_conf(r, ngx_http_asgi_module); - if (my_conf->python_file.len == 0 ) - { - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "asgi_name is empty!"); - return NGX_DECLINED; - } - - if (my_conf->app_name.len == 0 ) - { - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "asgi_email is empty!"); - return NGX_DECLINED; - } - - ngx_sprintf( - ngx_asgi_json, - "{\"file\":\"%s\",\"app\":\"%s\"}", - my_conf->python_file.data, - my_conf->app_name.data + u_char *ngx_asgi_json = execute_python_script( + cf->py_module, + cf->app_name, + r->pool, + r->connection->log ); - - - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return JSON:%s", ngx_asgi_json); + ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return 1 JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); + // ngx_sprintf(ngx_asgi_json, (const char*) ngx_asgi_json); content_length = ngx_strlen(ngx_asgi_json); /* we response to 'GET' requests only */ if (!(r->method & (NGX_HTTP_GET))) { - return NGX_HTTP_NOT_ALLOWED; + return NGX_HTTP_NOT_ALLOWED; } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { - return rc; + return rc; } ngx_str_set(&r->headers_out.content_type, "application/json"); @@ -156,7 +233,7 @@ ngx_http_asgi_handler(ngx_http_request_t *r) /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach this buffer to the buffer chain */ @@ -177,7 +254,7 @@ ngx_http_asgi_handler(ngx_http_request_t *r) rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - return rc; + return rc; } /* send the buffer chain of your response */ diff --git a/test/resource/example.py b/test/resource/example.py new file mode 100644 index 0000000..d5e7e43 --- /dev/null +++ b/test/resource/example.py @@ -0,0 +1,14 @@ +#! /usr/env/python3 + +import os + +def t_app(): + return """ + { + "hello": "from Python (example)", + "time": """ + "\"" + str(os.uname()) + "\"" + """ + } + """ + +app = "not callable ^o^" + \ No newline at end of file diff --git a/test/resource/nginx.test.conf b/test/resource/nginx.test.conf index 9b00843..2b3c618 100644 --- a/test/resource/nginx.test.conf +++ b/test/resource/nginx.test.conf @@ -8,6 +8,7 @@ events { } http { + server { listen 8080; server_name test_asgi_ngx; @@ -18,7 +19,7 @@ http { } location /asgi { - asgi_app example.py t_app; + asgi_app example t_app; } } } \ No newline at end of file -- Gitee From de3b56946aaaa2124fa8b06d9d95b78df62a3bda Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 11:39:30 +0800 Subject: [PATCH 2/8] use ngx_str_t in config struct --- src/ngx_http_asgi_module.c | 130 +++++++++++++--------------------- test/resource/nginx.test.conf | 2 + 2 files changed, 52 insertions(+), 80 deletions(-) diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 1a5bc3e..4b40efb 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -10,29 +10,29 @@ #include #include +typedef struct{} ngx_http_asgi_main_conf_t; + typedef struct { - // const char *app_folder; - const char *py_module; - const char *app_name; + ngx_str_t py_module; + ngx_str_t app_name; } ngx_http_asgi_conf_t; static ngx_int_t ngx_http_asgi_init(ngx_conf_t *cf); +static void *ngx_http_asgi_create_main_conf(ngx_conf_t *cf); static void *ngx_http_asgi_create_loc_conf(ngx_conf_t *cf); -// static char *ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r); -static const char * to_null_terminated_string(ngx_str_t n_string, ngx_pool_t *pool); -static ngx_int_t ngx_http_asgi_init_process(ngx_cycle_t *cycle); static ngx_command_t ngx_http_asgi_commands[] = { - // { - // ngx_string("asgi_app_path"), - // NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - // ngx_http_asgi_set_path, - // NGX_HTTP_LOC_CONF_OFFSET, - // 0, - // NULL }, + { + ngx_string("asgi_app_path"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_http_asgi_set_path, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, { ngx_string("asgi_app"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, @@ -47,7 +47,7 @@ static ngx_command_t ngx_http_asgi_commands[] = { static ngx_http_module_t ngx_http_asgi_module_ctx = { NULL, /* preconfiguration */ ngx_http_asgi_init, /* postconfiguration */ - NULL, /* create main configuration */ + ngx_http_asgi_create_main_conf,/* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ @@ -57,12 +57,12 @@ static ngx_http_module_t ngx_http_asgi_module_ctx = { ngx_module_t ngx_http_asgi_module = { NGX_MODULE_V1, - &ngx_http_asgi_module_ctx, /* module context */ - ngx_http_asgi_commands, /* module directives */ + &ngx_http_asgi_module_ctx, /* module context */ + ngx_http_asgi_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ - ngx_http_asgi_init_process, /* init process */ + NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ @@ -71,16 +71,17 @@ ngx_module_t ngx_http_asgi_module = { }; static void * -ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_asgi_conf_t* loc_cf = NULL; - loc_cf = ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); - return loc_cf; +ngx_http_asgi_create_main_conf(ngx_conf_t *cf) { + return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_main_conf_t)); +} + +static void * +ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) { + return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); } static ngx_int_t -ngx_http_asgi_init(ngx_conf_t *cf) -{ +ngx_http_asgi_init(ngx_conf_t *cf) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); @@ -92,65 +93,41 @@ ngx_http_asgi_init(ngx_conf_t *cf) return NGX_OK; }; -// static char * -// ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -// { -// ngx_str_t *params = cf->args->elts; -// if (params[1].len == 0) { -// ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app_path' doesn't take empty parameters"); -// return NGX_CONF_ERROR; -// } -// ngx_http_asgi_conf_t* c = conf; -// c->app_folder = to_null_terminated_string(params[1], cf->pool); - -// // ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Set ASGI app path: %s", buf); -// return NGX_CONF_OK; -// } - static char * -ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ +ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *params = cf->args->elts; - if (params[1].len == 0 || params[2].len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app' doesn't take empty parameters"); + if (params[1].len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app_path' cannot be empty"); return NGX_CONF_ERROR; } - ngx_http_asgi_conf_t* c = conf; - c->py_module = to_null_terminated_string(params[1], cf->pool); - c->app_name = to_null_terminated_string(params[2], cf->pool); - return NGX_CONF_OK; -} -static ngx_int_t -ngx_http_asgi_init_process(ngx_cycle_t *cycle) -{ - // ngx_http_asgi_conf_t *cf; - // cf = (ngx_http_asgi_conf_t *) ngx_http_cycle_get_module_main_conf(cycle, ngx_http_asgi_module); // ngx_get_conf(cycle->conf_ctx, ngx_http_asgi_module); - if (!Py_IsInitialized()) { - // char buf[1024]; - // sprintf(buf, "%s:${PYTHONPATH}", cf->app_folder); - setenv("PYTHONPATH", "/home/rim99/Projects/cpp/nginx-http-asgi-module/test/resource:${PYTHONPATH}", 1); - // ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "set Path: %s", buf); + if (cf != NULL) { + u_char buf[1024]; + ngx_sprintf(buf, "%s:${PYTHONPATH}", params[1].data); + setenv("PYTHONPATH", (char *)buf, 1); + } Py_Initialize(); } - return NGX_OK; + ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "Set ASGI app path: %s", params[1].data); + return NGX_CONF_OK; } -static const char * to_null_terminated_string(ngx_str_t n_string, ngx_pool_t *pool) { - char *dst = ngx_pcalloc(pool, (n_string.len + 1) * sizeof(char)); - u_char *src = n_string.data; - for (size_t i = 0; i < n_string.len; i++) { - dst[i] = (char) src[i]; +static char * +ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + ngx_str_t *params = cf->args->elts; + if (params[1].len == 0 || params[2].len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app' doesn't take empty parameters"); + return NGX_CONF_ERROR; } - - dst[n_string.len] = '\0'; - return dst; + ngx_http_asgi_conf_t* c = conf; + c->py_module = params[1]; + c->app_name = params[2]; + return NGX_CONF_OK; } u_char * -execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) -{ +execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) { u_char *rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); PyObject *pModule, *pFunc, *pArgs, *pValue; u_char * py_ret; @@ -179,14 +156,12 @@ execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *p Py_DECREF(pArgs); py_ret = (u_char *) PyUnicode_AsUTF8(pValue); if (pValue == NULL) { - // ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "python error: app returns NULL"); Py_DECREF(pValue); ngx_sprintf(rt, "{\"error\":\"result is NULL\"}"); } Py_XDECREF(pFunc); Py_DECREF(pModule); - // ngx_sprintf(rt, "{\"hello\":\"from Python\"}"); rt = py_ret; ret: @@ -194,11 +169,8 @@ execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *p } - - static ngx_int_t -ngx_http_asgi_handler(ngx_http_request_t *r) -{ +ngx_http_asgi_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; @@ -206,13 +178,12 @@ ngx_http_asgi_handler(ngx_http_request_t *r) ngx_uint_t content_length = 0; u_char *ngx_asgi_json = execute_python_script( - cf->py_module, - cf->app_name, + (char *)cf->py_module.data, + (char *)cf->app_name.data, r->pool, r->connection->log ); - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return 1 JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); - // ngx_sprintf(ngx_asgi_json, (const char*) ngx_asgi_json); + ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); content_length = ngx_strlen(ngx_asgi_json); /* we response to 'GET' requests only */ @@ -260,4 +231,3 @@ ngx_http_asgi_handler(ngx_http_request_t *r) /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); } - diff --git a/test/resource/nginx.test.conf b/test/resource/nginx.test.conf index 2b3c618..a46e650 100644 --- a/test/resource/nginx.test.conf +++ b/test/resource/nginx.test.conf @@ -9,6 +9,8 @@ events { http { + asgi_app_path /home/rim99/Projects/cpp/nginx-http-asgi-module/test/resource; + server { listen 8080; server_name test_asgi_ngx; -- Gitee From e986b0009b02202d751420167f1cd195a4e664d6 Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 12:06:25 +0800 Subject: [PATCH 3/8] import & get app per connection --- config | 9 ++- src/ngx_http_asgi_handler.c | 114 ++++++++++++++++++++++++++++++++ src/ngx_http_asgi_handler.h | 18 ++++++ src/ngx_http_asgi_module.c | 118 +--------------------------------- test/resource/nginx.test.conf | 2 +- 5 files changed, 143 insertions(+), 118 deletions(-) create mode 100644 src/ngx_http_asgi_handler.c create mode 100644 src/ngx_http_asgi_handler.h diff --git a/config b/config index 6104c92..94341d2 100644 --- a/config +++ b/config @@ -2,7 +2,14 @@ ngx_module_type=HTTP ngx_module_name=ngx_http_asgi_module ngx_module_incs="/usr/include/python3.9/ $ngx_addon_dir/src" ngx_module_libs="-lpython3.9 -lcrypt -lpthread -ldl -lutil -lm" -ngx_module_srcs="$ngx_addon_dir/src/ngx_http_asgi_module.c" +ngx_module_deps=" \ + $ngx_addon_dir/src/ngx_http_asgi_handler.h \ +" + +ngx_module_srcs=" \ + $ngx_addon_dir/src/ngx_http_asgi_module.c \ + $ngx_addon_dir/src/ngx_http_asgi_handler.c \ +" . auto/module diff --git a/src/ngx_http_asgi_handler.c b/src/ngx_http_asgi_handler.c new file mode 100644 index 0000000..39e8cad --- /dev/null +++ b/src/ngx_http_asgi_handler.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) ZHANG Xin + * LICENSE: MIT + */ + +#include +#include +#include + +static u_char * +execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) { + u_char *rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); + PyObject *pModule, *pFunc, *pArgs, *pValue; + u_char * py_ret; + + pModule = PyImport_ImportModule(py_module); + if (pModule == NULL) { + // TODO: error happen + ngx_sprintf(rt, "{\"error\":\"connot find module %s\"}", py_module); + goto ret; + } + pFunc = PyObject_GetAttrString(pModule, app_name); + if (pFunc == NULL) { + // TODO: error happen + Py_XDECREF(pFunc); + ngx_sprintf(rt, "{\"error\":\"connot find app\"}"); + goto ret; + } + if (!PyCallable_Check(pFunc)) { + // TODO: not function + Py_XDECREF(pFunc); + ngx_sprintf(rt, "{\"error\":\"app is not callable\"}"); + goto ret; + } + pArgs = PyTuple_New(0); + pValue = PyObject_CallObject(pFunc, pArgs); + Py_DECREF(pArgs); + py_ret = (u_char *) PyUnicode_AsUTF8(pValue); + if (pValue == NULL) { + Py_DECREF(pValue); + ngx_sprintf(rt, "{\"error\":\"result is NULL\"}"); + } + Py_XDECREF(pFunc); + Py_DECREF(pModule); + + rt = py_ret; + + ret: + return rt; + +} + +ngx_int_t +ngx_http_asgi_handler(ngx_http_request_t *r) { + ngx_int_t rc; + ngx_buf_t *b; + ngx_chain_t out; + ngx_http_asgi_conf_t* cf = ngx_http_get_module_loc_conf(r, ngx_http_asgi_module); + ngx_uint_t content_length = 0; + + u_char *ngx_asgi_json = execute_python_script( + (char *)cf->py_module.data, + (char *)cf->app_name.data, + r->pool, + r->connection->log + ); + ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); + content_length = ngx_strlen(ngx_asgi_json); + + /* we response to 'GET' requests only */ + if (!(r->method & (NGX_HTTP_GET))) { + return NGX_HTTP_NOT_ALLOWED; + } + + /* discard request body, since we don't need it here */ + rc = ngx_http_discard_request_body(r); + + if (rc != NGX_OK) { + return rc; + } + + ngx_str_set(&r->headers_out.content_type, "application/json"); + + + /* allocate a buffer for your response body */ + b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + if (b == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + /* attach this buffer to the buffer chain */ + out.buf = b; + out.next = NULL; + + /* adjust the pointers of the buffer */ + b->pos = ngx_asgi_json; + b->last = ngx_asgi_json + content_length; + b->memory = 1; /* this buffer is in memory */ + b->last_buf = 1; /* this is the last buffer in the buffer chain */ + + /* set the status line */ + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = content_length; + + /* send the headers of your response */ + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + return rc; + } + + /* send the buffer chain of your response */ + return ngx_http_output_filter(r, &out); +} diff --git a/src/ngx_http_asgi_handler.h b/src/ngx_http_asgi_handler.h new file mode 100644 index 0000000..4990ed4 --- /dev/null +++ b/src/ngx_http_asgi_handler.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) ZHANG Xin + * LICENSE: MIT + */ + +#include + +typedef struct{} ngx_http_asgi_main_conf_t; + +typedef struct +{ + ngx_str_t py_module; + ngx_str_t app_name; +} ngx_http_asgi_conf_t; + +ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r); + +extern ngx_module_t ngx_http_asgi_module; \ No newline at end of file diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 4b40efb..a9fef2f 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -1,29 +1,21 @@ /* * Copyright (C) ZHANG Xin + * LICENSE: MIT */ - #include #include #include #include #include - -typedef struct{} ngx_http_asgi_main_conf_t; - -typedef struct -{ - ngx_str_t py_module; - ngx_str_t app_name; -} ngx_http_asgi_conf_t; +#include static ngx_int_t ngx_http_asgi_init(ngx_conf_t *cf); static void *ngx_http_asgi_create_main_conf(ngx_conf_t *cf); static void *ngx_http_asgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r); static ngx_command_t ngx_http_asgi_commands[] = { { @@ -125,109 +117,3 @@ ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { c->app_name = params[2]; return NGX_CONF_OK; } - -u_char * -execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) { - u_char *rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); - PyObject *pModule, *pFunc, *pArgs, *pValue; - u_char * py_ret; - - pModule = PyImport_ImportModule(py_module); - if (pModule == NULL) { - // TODO: error happen - ngx_sprintf(rt, "{\"error\":\"connot find module %s\"}", py_module); - goto ret; - } - pFunc = PyObject_GetAttrString(pModule, app_name); - if (pFunc == NULL) { - // TODO: error happen - Py_XDECREF(pFunc); - ngx_sprintf(rt, "{\"error\":\"connot find app\"}"); - goto ret; - } - if (!PyCallable_Check(pFunc)) { - // TODO: not function - Py_XDECREF(pFunc); - ngx_sprintf(rt, "{\"error\":\"app is not callable\"}"); - goto ret; - } - pArgs = PyTuple_New(0); - pValue = PyObject_CallObject(pFunc, pArgs); - Py_DECREF(pArgs); - py_ret = (u_char *) PyUnicode_AsUTF8(pValue); - if (pValue == NULL) { - Py_DECREF(pValue); - ngx_sprintf(rt, "{\"error\":\"result is NULL\"}"); - } - Py_XDECREF(pFunc); - Py_DECREF(pModule); - - rt = py_ret; - - ret: - return rt; - -} - -static ngx_int_t -ngx_http_asgi_handler(ngx_http_request_t *r) { - ngx_int_t rc; - ngx_buf_t *b; - ngx_chain_t out; - ngx_http_asgi_conf_t* cf = ngx_http_get_module_loc_conf(r, ngx_http_asgi_module); - ngx_uint_t content_length = 0; - - u_char *ngx_asgi_json = execute_python_script( - (char *)cf->py_module.data, - (char *)cf->app_name.data, - r->pool, - r->connection->log - ); - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); - content_length = ngx_strlen(ngx_asgi_json); - - /* we response to 'GET' requests only */ - if (!(r->method & (NGX_HTTP_GET))) { - return NGX_HTTP_NOT_ALLOWED; - } - - /* discard request body, since we don't need it here */ - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK) { - return rc; - } - - ngx_str_set(&r->headers_out.content_type, "application/json"); - - - /* allocate a buffer for your response body */ - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - /* attach this buffer to the buffer chain */ - out.buf = b; - out.next = NULL; - - /* adjust the pointers of the buffer */ - b->pos = ngx_asgi_json; - b->last = ngx_asgi_json + content_length; - b->memory = 1; /* this buffer is in memory */ - b->last_buf = 1; /* this is the last buffer in the buffer chain */ - - /* set the status line */ - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = content_length; - - /* send the headers of your response */ - rc = ngx_http_send_header(r); - - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - return rc; - } - - /* send the buffer chain of your response */ - return ngx_http_output_filter(r, &out); -} diff --git a/test/resource/nginx.test.conf b/test/resource/nginx.test.conf index a46e650..e69fccf 100644 --- a/test/resource/nginx.test.conf +++ b/test/resource/nginx.test.conf @@ -4,7 +4,7 @@ worker_processes 1; error_log logs/error.log info; events { - worker_connections 16; + worker_connections 4096; } http { -- Gitee From b91840c7fc99f71f3ada9d18e6198f761ff10daf Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 15:10:09 +0800 Subject: [PATCH 4/8] init asgi app when starting --- src/ngx_http_asgi_handler.c | 55 ++++++++++---------------------- src/ngx_http_asgi_handler.h | 2 ++ src/ngx_http_asgi_module.c | 62 +++++++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/ngx_http_asgi_handler.c b/src/ngx_http_asgi_handler.c index 39e8cad..307b5ca 100644 --- a/src/ngx_http_asgi_handler.c +++ b/src/ngx_http_asgi_handler.c @@ -8,46 +8,21 @@ #include static u_char * -execute_python_script(const char *py_module, const char *app_name, ngx_pool_t *pool, ngx_log_t *logger) { - u_char *rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); - PyObject *pModule, *pFunc, *pArgs, *pValue; - u_char * py_ret; - - pModule = PyImport_ImportModule(py_module); - if (pModule == NULL) { - // TODO: error happen - ngx_sprintf(rt, "{\"error\":\"connot find module %s\"}", py_module); - goto ret; - } - pFunc = PyObject_GetAttrString(pModule, app_name); - if (pFunc == NULL) { - // TODO: error happen - Py_XDECREF(pFunc); - ngx_sprintf(rt, "{\"error\":\"connot find app\"}"); - goto ret; - } - if (!PyCallable_Check(pFunc)) { - // TODO: not function - Py_XDECREF(pFunc); - ngx_sprintf(rt, "{\"error\":\"app is not callable\"}"); - goto ret; - } +execute_python_script(PyObject* asgi_app, ngx_pool_t *pool) { + u_char *rt = NULL; + PyObject *pArgs, *pValue; pArgs = PyTuple_New(0); - pValue = PyObject_CallObject(pFunc, pArgs); + pValue = PyObject_CallObject(asgi_app, pArgs); Py_DECREF(pArgs); - py_ret = (u_char *) PyUnicode_AsUTF8(pValue); if (pValue == NULL) { Py_DECREF(pValue); + rt = ngx_pcalloc(pool, (256) * sizeof(u_char)); ngx_sprintf(rt, "{\"error\":\"result is NULL\"}"); + } else { + rt = (u_char *) PyUnicode_AsUTF8(pValue); } - Py_XDECREF(pFunc); - Py_DECREF(pModule); - - rt = py_ret; - ret: return rt; - } ngx_int_t @@ -56,16 +31,18 @@ ngx_http_asgi_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_chain_t out; ngx_http_asgi_conf_t* cf = ngx_http_get_module_loc_conf(r, ngx_http_asgi_module); - ngx_uint_t content_length = 0; + + PyObject* asgi_app = cf->asgi_app; + if (asgi_app == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } u_char *ngx_asgi_json = execute_python_script( - (char *)cf->py_module.data, - (char *)cf->app_name.data, - r->pool, - r->connection->log + asgi_app, + r->pool ); - ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "should return JSON:%s:%i", ngx_asgi_json, strlen((char *)ngx_asgi_json)); - content_length = ngx_strlen(ngx_asgi_json); + + ngx_uint_t content_length = ngx_strlen(ngx_asgi_json); /* we response to 'GET' requests only */ if (!(r->method & (NGX_HTTP_GET))) { diff --git a/src/ngx_http_asgi_handler.h b/src/ngx_http_asgi_handler.h index 4990ed4..2efde07 100644 --- a/src/ngx_http_asgi_handler.h +++ b/src/ngx_http_asgi_handler.h @@ -4,6 +4,7 @@ */ #include +#include typedef struct{} ngx_http_asgi_main_conf_t; @@ -11,6 +12,7 @@ typedef struct { ngx_str_t py_module; ngx_str_t app_name; + PyObject* asgi_app; } ngx_http_asgi_conf_t; ngx_int_t ngx_http_asgi_handler(ngx_http_request_t *r); diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index a9fef2f..73ff60c 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -47,21 +47,6 @@ static ngx_http_module_t ngx_http_asgi_module_ctx = { NULL /* merge location configuration */ }; -ngx_module_t ngx_http_asgi_module = { - NGX_MODULE_V1, - &ngx_http_asgi_module_ctx, /* module context */ - ngx_http_asgi_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - static void * ngx_http_asgi_create_main_conf(ngx_conf_t *cf) { return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_main_conf_t)); @@ -101,7 +86,7 @@ ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { } Py_Initialize(); } - ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "Set ASGI app path: %s", params[1].data); + ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "Set ASGI app path: %s", params[1].data); return NGX_CONF_OK; } @@ -110,10 +95,53 @@ ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *params = cf->args->elts; if (params[1].len == 0 || params[2].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app' doesn't take empty parameters"); - return NGX_CONF_ERROR; + goto error; } ngx_http_asgi_conf_t* c = conf; c->py_module = params[1]; c->app_name = params[2]; + PyObject *module, *app; + module = PyImport_ImportModule((char *)params[1].data); + if (module == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "connot find module: %s", params[1].data); + goto module_error; + } + app = PyObject_GetAttrString(module, (char *)params[2].data); + if (app == NULL) { + Py_XDECREF(app); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "connot find ASGI app: %s in module: %s", params[2].data, params[1].data); + goto app_error; + } + if (!PyCallable_Check(app)) { + Py_XDECREF(app); + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ASGI app: %s in module: %s is not callable", params[2].data, params[1].data); + goto app_error; + } + + c->asgi_app = app; + + Py_DECREF(module); return NGX_CONF_OK; + + app_error: + Py_DECREF(module); + + module_error: + error: + return NGX_CONF_ERROR; } + +ngx_module_t ngx_http_asgi_module = { + NGX_MODULE_V1, + &ngx_http_asgi_module_ctx, /* module context */ + ngx_http_asgi_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; -- Gitee From bfd0813250c2002acc350d6e62dcb67327019e8e Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 15:35:44 +0800 Subject: [PATCH 5/8] format config --- test/resource/nginx.test.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/resource/nginx.test.conf b/test/resource/nginx.test.conf index e69fccf..c2be3ef 100644 --- a/test/resource/nginx.test.conf +++ b/test/resource/nginx.test.conf @@ -1,3 +1,4 @@ +# nginx config worker_processes 1; @@ -9,7 +10,7 @@ events { http { - asgi_app_path /home/rim99/Projects/cpp/nginx-http-asgi-module/test/resource; + asgi_app_path (YOUR_REPO_PATH)/test/resource; server { listen 8080; -- Gitee From 4f46b9b4a701e7f38b353f898bc888c20d600a96 Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 15:43:38 +0800 Subject: [PATCH 6/8] refacvtor loc config --- src/ngx_http_asgi_handler.h | 2 -- src/ngx_http_asgi_module.c | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ngx_http_asgi_handler.h b/src/ngx_http_asgi_handler.h index 2efde07..61b39c8 100644 --- a/src/ngx_http_asgi_handler.h +++ b/src/ngx_http_asgi_handler.h @@ -10,8 +10,6 @@ typedef struct{} ngx_http_asgi_main_conf_t; typedef struct { - ngx_str_t py_module; - ngx_str_t app_name; PyObject* asgi_app; } ngx_http_asgi_conf_t; diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 73ff60c..1f4650d 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -97,9 +97,6 @@ ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "'asgi_app' doesn't take empty parameters"); goto error; } - ngx_http_asgi_conf_t* c = conf; - c->py_module = params[1]; - c->app_name = params[2]; PyObject *module, *app; module = PyImport_ImportModule((char *)params[1].data); if (module == NULL) { @@ -118,6 +115,7 @@ ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { goto app_error; } + ngx_http_asgi_conf_t* c = conf; c->asgi_app = app; Py_DECREF(module); -- Gitee From c9d98ee9eec0fffabb3b910517b6fd431575da98 Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 15:47:11 +0800 Subject: [PATCH 7/8] remove useless config --- src/ngx_http_asgi_handler.h | 2 -- src/ngx_http_asgi_module.c | 8 +------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ngx_http_asgi_handler.h b/src/ngx_http_asgi_handler.h index 61b39c8..57e5d1b 100644 --- a/src/ngx_http_asgi_handler.h +++ b/src/ngx_http_asgi_handler.h @@ -6,8 +6,6 @@ #include #include -typedef struct{} ngx_http_asgi_main_conf_t; - typedef struct { PyObject* asgi_app; diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 1f4650d..7d5c3a4 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -12,7 +12,6 @@ #include static ngx_int_t ngx_http_asgi_init(ngx_conf_t *cf); -static void *ngx_http_asgi_create_main_conf(ngx_conf_t *cf); static void *ngx_http_asgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_asgi_set_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_asgi_set_app(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -39,7 +38,7 @@ static ngx_command_t ngx_http_asgi_commands[] = { static ngx_http_module_t ngx_http_asgi_module_ctx = { NULL, /* preconfiguration */ ngx_http_asgi_init, /* postconfiguration */ - ngx_http_asgi_create_main_conf,/* create main configuration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ @@ -47,11 +46,6 @@ static ngx_http_module_t ngx_http_asgi_module_ctx = { NULL /* merge location configuration */ }; -static void * -ngx_http_asgi_create_main_conf(ngx_conf_t *cf) { - return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_main_conf_t)); -} - static void * ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) { return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); -- Gitee From fa198911851104e13706c99208379805bc8fb709 Mon Sep 17 00:00:00 2001 From: rim99 Date: Tue, 5 Oct 2021 15:52:17 +0800 Subject: [PATCH 8/8] robustness --- src/ngx_http_asgi_module.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ngx_http_asgi_module.c b/src/ngx_http_asgi_module.c index 7d5c3a4..65b6609 100644 --- a/src/ngx_http_asgi_module.c +++ b/src/ngx_http_asgi_module.c @@ -48,7 +48,11 @@ static ngx_http_module_t ngx_http_asgi_module_ctx = { static void * ngx_http_asgi_create_loc_conf(ngx_conf_t *cf) { - return ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); + ngx_http_asgi_conf_t *c = ngx_pcalloc(cf->pool, sizeof(ngx_http_asgi_conf_t)); + if (c == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Init location config of ASGI module failed"); + } + return c; } static ngx_int_t -- Gitee