├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── config ├── src ├── ngx_http_python_code.c ├── ngx_http_python_code.h ├── ngx_http_python_directive.c ├── ngx_http_python_directive.h ├── ngx_http_python_handler.c ├── ngx_http_python_handler.h ├── ngx_http_python_module.c ├── ngx_http_python_module.h ├── ngx_http_python_output.c ├── ngx_http_python_output.h ├── ngx_python_uthread.c ├── ngx_python_uthread.h └── python │ ├── python_ngx.c │ ├── python_ngx.h │ ├── python_ngx_request.c │ └── python_ngx_request.h ├── t └── library │ └── hello.py └── travis └── compile.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | addons: 4 | apt: 5 | packages: 6 | - locales 7 | - language-pack-de 8 | - re2c 9 | - libgmp-dev 10 | - libicu-dev 11 | - libmcrypt-dev 12 | - libtidy-dev 13 | - libenchant-dev 14 | - libaspell-dev 15 | - libpspell-dev 16 | - librecode-dev 17 | - libsasl2-dev 18 | - libxpm-dev 19 | - libt1-dev 20 | - cpanminus 21 | compiler: 22 | - gcc 23 | cache: 24 | - apt 25 | env: 26 | - PYTHON_SRC_VERSION=2.7.13 27 | NGINX_SRC_VERSION=1.7.12 28 | - PYTHON_SRC_VERSION=2.7.13 29 | NGINX_SRC_VERSION=1.8.1 30 | - PYTHON_SRC_VERSION=2.7.13 31 | NGINX_SRC_VERSION=1.9.15 32 | - PYTHON_SRC_VERSION=2.7.13 33 | NGINX_SRC_VERSION=1.10.2 34 | - PYTHON_SRC_VERSION=2.7.13 35 | NGINX_SRC_VERSION=1.11.8 36 | install: 37 | - sudo cpanm -n Test::Nginx 38 | before_script: 39 | - ./travis/compile.sh 40 | script: 41 | - echo ngx_python -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2016-2017, rryqszq4 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ngx_python 2 | ========== 3 | [![Build Status](https://travis-ci.org/rryqszq4/ngx_python.svg?branch=master)](https://travis-ci.org/rryqszq4/ngx_python) 4 | [![license](https://img.shields.io/badge/license-BSD--2--Clause-blue.svg)](https://github.com/rryqszq4/ngx_python/blob/master/LICENSE) 5 | 6 | [ngx_python](https://github.com/rryqszq4/ngx_python) - Embedded python for nginx-module. Another name is python-nginx-module. 7 | 8 | Requirement 9 | ----------- 10 | - python 2.7.* 11 | - nginx-1.6.3+ 12 | 13 | Installation 14 | ------- 15 | ```sh 16 | $ git clone https://github.com/rryqszq4/ngx_python.git 17 | 18 | $ wget 'http://nginx.org/download/nginx-1.6.3.tar.gz' 19 | $ tar -zxvf nginx-1.6.3.tar.gz 20 | $ cd nginx-1.6.3 21 | 22 | $ export PYTHON_INC=/path/to/python/include/python2.7 23 | $ export PYTHON_BIN=/path/to/python/bin 24 | 25 | $ ./configure --user=www --group=www \ 26 | --prefix=/path/to/nginx \ 27 | --add-module=/path/to/ngx_python 28 | $ make 29 | $ make install 30 | ``` 31 | 32 | Synopsis 33 | -------- 34 | nginx config: 35 | ```nginx 36 | user www www; 37 | worker_processes 4; 38 | 39 | events { 40 | worker_connections 1024; 41 | } 42 | 43 | http { 44 | include mime.types; 45 | default_type application/octet-stream; 46 | 47 | keepalive_timeout 65; 48 | 49 | server { 50 | listen 80; 51 | server_name localhost; 52 | 53 | location /content_by_python { 54 | content_by_python " 55 | from time import time,ctime 56 | import ngx 57 | 58 | ngx.echo('Hello, Ngx_Python at ' + ctime(time()) + '\\n') 59 | 60 | a = [1,2,3,4,5] 61 | ngx.echo(a) 62 | 63 | ngx.echo('\\n'+str(type(a))) 64 | "; 65 | } 66 | 67 | location /content_by_python_file { 68 | content_by_python_file /ngx_python/t/library/hello.py; 69 | } 70 | } 71 | } 72 | ``` 73 | 74 | execute: 75 | 76 | ```sh 77 | $ curl http://localhost/content_by_python 78 | Hello, ngx_python at Thu Dec 1 00:38:02 2016 79 | [1, 2, 3, 4, 5] 80 | 81 | 82 | $ curl http://localhost/content_by_python_file 83 | Hello, Ngx_Python 84 | 85 | ``` 86 | 87 | Copyright and License 88 | --------------------- 89 | BSD 2-Clause License 90 | 91 | Copyright (c) 2016-2017, rryqszq4 92 | All rights reserved. 93 | 94 | Redistribution and use in source and binary forms, with or without 95 | modification, are permitted provided that the following conditions are met: 96 | 97 | * Redistributions of source code must retain the above copyright notice, this 98 | list of conditions and the following disclaimer. 99 | 100 | * Redistributions in binary form must reproduce the above copyright notice, 101 | this list of conditions and the following disclaimer in the documentation 102 | and/or other materials provided with the distribution. 103 | 104 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 105 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 106 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 107 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 108 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 109 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 110 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 111 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 112 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 113 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 114 | 115 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_python_module 2 | HTTP_MODULES="$HTTP_MODULES ngx_http_python_module" 3 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_python_module.c \ 4 | $ngx_addon_dir/src/ngx_http_python_code.c \ 5 | $ngx_addon_dir/src/ngx_http_python_directive.c \ 6 | $ngx_addon_dir/src/ngx_http_python_handler.c \ 7 | $ngx_addon_dir/src/python/python_ngx.c \ 8 | " 9 | 10 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_python_module.h \ 11 | $ngx_addon_dir/src/ngx_http_python_code.h \ 12 | $ngx_addon_dir/src/ngx_http_python_directive.h \ 13 | $ngx_addon_dir/src/ngx_http_python_handler.h \ 14 | $ngx_addon_dir/src/python/python_ngx.h \ 15 | " 16 | 17 | CORE_INCS="$CORE_INCS $PYTHON_INC " 18 | 19 | CORE_LIBS="$CORE_LIBS `$PYTHON_BIN/python-config --ldflags` " 20 | 21 | #CORE_INCS="$CORE_INCS /usr/local/include/python2.7 " 22 | 23 | #CORE_LIBS="$CORE_LIBS `/usr/local/bin/python-config --ldflags` " -------------------------------------------------------------------------------- /src/ngx_http_python_code.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include "ngx_http_python_module.h" 8 | #include "ngx_http_python_code.h" 9 | 10 | ngx_http_python_code_t * 11 | ngx_http_python_code_from_file(ngx_pool_t *pool, ngx_str_t *code_file_path) 12 | { 13 | ngx_http_python_code_t *code; 14 | size_t len; 15 | u_char *p; 16 | 17 | code = ngx_pcalloc(pool, sizeof(* code)); 18 | 19 | if (code == NULL) { 20 | return NGX_CONF_UNSET_PTR; 21 | } 22 | 23 | len = ngx_strlen((char *)code_file_path->data); 24 | if (len == 0){ 25 | return NGX_CONF_UNSET_PTR; 26 | }else if (code_file_path->data[0] == '/' || code_file_path->data[0] == '$'){ 27 | code->code.file = ngx_pcalloc(pool, len + 1); 28 | if (code->code.file == NULL){ 29 | return NGX_CONF_UNSET_PTR; 30 | } 31 | ngx_cpystrn((u_char *)code->code.file, (u_char *)code_file_path->data, code_file_path->len + 1); 32 | }else { 33 | code->code.file = ngx_pcalloc(pool, ngx_cycle->conf_prefix.len + len + 1); 34 | if (code->code.file == NULL){ 35 | return NGX_CONF_UNSET_PTR; 36 | } 37 | p = ngx_cpystrn((u_char *)code->code.file, (u_char *)ngx_cycle->conf_prefix.data, ngx_cycle->conf_prefix.len + 1); 38 | ngx_cpystrn(p, (u_char *)code_file_path->data, code_file_path->len + 1); 39 | } 40 | code->code_type = NGX_HTTP_PYTHON_CODE_TYPE_FILE; 41 | return code; 42 | } 43 | 44 | 45 | ngx_http_python_code_t * 46 | ngx_http_python_code_from_string(ngx_pool_t *pool, ngx_str_t *code_str) 47 | { 48 | ngx_http_python_code_t *code; 49 | size_t len; 50 | 51 | code = ngx_pcalloc(pool, sizeof(*code)); 52 | if (code == NULL){ 53 | return NGX_CONF_UNSET_PTR; 54 | } 55 | 56 | len = ngx_strlen(code_str->data); 57 | code->code.string = ngx_pcalloc(pool, len + 1); 58 | if (code->code.string == NULL){ 59 | return NGX_CONF_UNSET_PTR; 60 | } 61 | ngx_cpystrn((u_char *)code->code.string, code_str->data, len + 1); 62 | code->code_type = NGX_HTTP_PYTHON_CODE_TYPE_STRING; 63 | return code; 64 | } 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/ngx_http_python_code.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef NGX_HTTP_PYTHON_CODE_H 8 | #define NGX_HTTP_PYTHON_CODE_H 9 | 10 | #include 11 | 12 | extern ngx_http_request_t *ngx_python_request; 13 | 14 | typedef enum code_type_t { 15 | NGX_HTTP_PYTHON_CODE_TYPE_FILE, 16 | NGX_HTTP_PYTHON_CODE_TYPE_STRING 17 | } code_type_t; 18 | 19 | typedef struct ngx_http_python_code_t { 20 | union code { 21 | char *file; 22 | char *string; 23 | } code; 24 | code_type_t code_type; 25 | } ngx_http_python_code_t; 26 | 27 | typedef struct ngx_http_python_rputs_chain_list_t { 28 | ngx_chain_t **last; 29 | ngx_chain_t *out; 30 | } ngx_http_python_rputs_chain_list_t; 31 | 32 | typedef struct ngx_http_python_ctx_t { 33 | ngx_http_python_rputs_chain_list_t *rputs_chain; 34 | unsigned request_body_more : 1; 35 | 36 | ngx_int_t exit_code; 37 | 38 | } ngx_http_python_ctx_t; 39 | 40 | 41 | ngx_http_python_code_t *ngx_http_python_code_from_file(ngx_pool_t *pool, ngx_str_t *code_file_path); 42 | ngx_http_python_code_t *ngx_http_python_code_from_string(ngx_pool_t *pool, ngx_str_t *code_str); 43 | 44 | #endif -------------------------------------------------------------------------------- /src/ngx_http_python_directive.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include "ngx_http_python_directive.h" 8 | #include "ngx_http_python_module.h" 9 | 10 | char * 11 | ngx_http_python_rewrite_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 12 | { 13 | ngx_http_python_main_conf_t *pmcf; 14 | ngx_http_python_loc_conf_t *plcf; 15 | ngx_str_t *value; 16 | ngx_http_python_code_t *code; 17 | 18 | if (cmd->post == NULL) { 19 | return NGX_CONF_ERROR; 20 | } 21 | 22 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 23 | plcf = conf; 24 | 25 | if (plcf->rewrite_handler != NULL){ 26 | return "is duplicated"; 27 | } 28 | 29 | value = cf->args->elts; 30 | 31 | code = ngx_http_python_code_from_file(cf->pool, &value[1]); 32 | if (code == NGX_CONF_UNSET_PTR){ 33 | return NGX_CONF_ERROR; 34 | } 35 | 36 | plcf->rewrite_file_code = code; 37 | plcf->rewrite_handler = cmd->post; 38 | pmcf->enabled_rewrite_handler = 1; 39 | 40 | return NGX_CONF_OK; 41 | } 42 | 43 | char * 44 | ngx_http_python_rewrite_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 45 | { 46 | ngx_http_python_main_conf_t *pmcf; 47 | ngx_http_python_loc_conf_t *plcf; 48 | ngx_str_t *value; 49 | ngx_http_python_code_t *code; 50 | 51 | if (cmd->post == NULL) { 52 | return NGX_CONF_ERROR; 53 | } 54 | 55 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 56 | plcf = conf; 57 | 58 | if (plcf->rewrite_handler != NULL){ 59 | return "is duplicated"; 60 | } 61 | 62 | value = cf->args->elts; 63 | 64 | code = ngx_http_python_code_from_string(cf->pool, &value[1]); 65 | if (code == NGX_CONF_UNSET_PTR){ 66 | return NGX_CONF_ERROR; 67 | } 68 | 69 | plcf->rewrite_inline_code = code; 70 | plcf->rewrite_handler = cmd->post; 71 | pmcf->enabled_rewrite_handler = 1; 72 | 73 | return NGX_CONF_OK; 74 | } 75 | 76 | char * 77 | ngx_http_python_access_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 78 | { 79 | ngx_http_python_main_conf_t *pmcf; 80 | ngx_http_python_loc_conf_t *plcf; 81 | ngx_str_t *value; 82 | ngx_http_python_code_t *code; 83 | 84 | if (cmd->post == NULL) { 85 | return NGX_CONF_ERROR; 86 | } 87 | 88 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 89 | plcf = conf; 90 | 91 | if (plcf->access_handler != NULL){ 92 | return "is duplicated"; 93 | } 94 | 95 | value = cf->args->elts; 96 | 97 | code = ngx_http_python_code_from_file(cf->pool, &value[1]); 98 | if (code == NGX_CONF_UNSET_PTR){ 99 | return NGX_CONF_ERROR; 100 | } 101 | 102 | plcf->access_file_code = code; 103 | plcf->access_handler = cmd->post; 104 | pmcf->enabled_access_handler = 1; 105 | 106 | return NGX_CONF_OK; 107 | } 108 | 109 | char * 110 | ngx_http_python_access_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 111 | { 112 | ngx_http_python_main_conf_t *pmcf; 113 | ngx_http_python_loc_conf_t *plcf; 114 | ngx_str_t *value; 115 | ngx_http_python_code_t *code; 116 | 117 | if (cmd->post == NULL) { 118 | return NGX_CONF_ERROR; 119 | } 120 | 121 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 122 | plcf = conf; 123 | 124 | if (plcf->access_handler != NULL){ 125 | return "is duplicated"; 126 | } 127 | 128 | value = cf->args->elts; 129 | 130 | code = ngx_http_python_code_from_string(cf->pool, &value[1]); 131 | if (code == NGX_CONF_UNSET_PTR){ 132 | return NGX_CONF_ERROR; 133 | } 134 | 135 | plcf->access_inline_code = code; 136 | plcf->access_handler = cmd->post; 137 | pmcf->enabled_access_handler = 1; 138 | 139 | return NGX_CONF_OK; 140 | } 141 | 142 | char * 143 | ngx_http_python_content_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 144 | { 145 | ngx_http_python_main_conf_t *pmcf; 146 | ngx_http_python_loc_conf_t *plcf; 147 | ngx_str_t *value; 148 | ngx_http_python_code_t *code; 149 | 150 | if (cmd->post == NULL) { 151 | return NGX_CONF_ERROR; 152 | } 153 | 154 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 155 | plcf = conf; 156 | 157 | if (plcf->content_handler != NULL){ 158 | return "is duplicated"; 159 | } 160 | 161 | value = cf->args->elts; 162 | 163 | code = ngx_http_python_code_from_file(cf->pool, &value[1]); 164 | if (code == NGX_CONF_UNSET_PTR){ 165 | return NGX_CONF_ERROR; 166 | } 167 | 168 | plcf->content_file_code = code; 169 | plcf->content_handler = cmd->post; 170 | pmcf->enabled_content_handler = 1; 171 | 172 | return NGX_CONF_OK; 173 | } 174 | 175 | char * 176 | ngx_http_python_content_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 177 | { 178 | ngx_http_python_main_conf_t *pmcf; 179 | ngx_http_python_loc_conf_t *plcf; 180 | ngx_str_t *value; 181 | ngx_http_python_code_t *code; 182 | 183 | if (cmd->post == NULL) { 184 | return NGX_CONF_ERROR; 185 | } 186 | 187 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 188 | plcf = conf; 189 | 190 | if (plcf->content_handler != NULL){ 191 | return "is duplicated"; 192 | } 193 | 194 | value = cf->args->elts; 195 | 196 | code = ngx_http_python_code_from_string(cf->pool, &value[1]); 197 | if (code == NGX_CONF_UNSET_PTR){ 198 | return NGX_CONF_ERROR; 199 | } 200 | 201 | plcf->content_inline_code = code; 202 | plcf->content_handler = cmd->post; 203 | pmcf->enabled_content_handler = 1; 204 | 205 | return NGX_CONF_OK; 206 | } 207 | 208 | char * 209 | ngx_http_python_log_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 210 | { 211 | ngx_http_python_main_conf_t *pmcf; 212 | ngx_http_python_loc_conf_t *plcf; 213 | ngx_str_t *value; 214 | ngx_http_python_code_t *code; 215 | 216 | if (cmd->post == NULL) { 217 | return NGX_CONF_ERROR; 218 | } 219 | 220 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 221 | plcf = conf; 222 | 223 | if (plcf->log_handler != NULL){ 224 | return "is duplicated"; 225 | } 226 | 227 | value = cf->args->elts; 228 | 229 | code = ngx_http_python_code_from_file(cf->pool, &value[1]); 230 | if (code == NGX_CONF_UNSET_PTR){ 231 | return NGX_CONF_ERROR; 232 | } 233 | 234 | plcf->log_file_code = code; 235 | plcf->log_handler = cmd->post; 236 | pmcf->enabled_log_handler = 1; 237 | 238 | return NGX_CONF_OK; 239 | } 240 | 241 | char * 242 | ngx_http_python_log_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 243 | { 244 | ngx_http_python_main_conf_t *pmcf; 245 | ngx_http_python_loc_conf_t *plcf; 246 | ngx_str_t *value; 247 | ngx_http_python_code_t *code; 248 | 249 | if (cmd->post == NULL) { 250 | return NGX_CONF_ERROR; 251 | } 252 | 253 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 254 | plcf = conf; 255 | 256 | if (plcf->log_handler != NULL){ 257 | return "is duplicated"; 258 | } 259 | 260 | value = cf->args->elts; 261 | 262 | code = ngx_http_python_code_from_string(cf->pool, &value[1]); 263 | if (code == NGX_CONF_UNSET_PTR){ 264 | return NGX_CONF_ERROR; 265 | } 266 | 267 | plcf->log_inline_code = code; 268 | plcf->log_handler = cmd->post; 269 | pmcf->enabled_log_handler = 1; 270 | 271 | return NGX_CONF_OK; 272 | } 273 | 274 | -------------------------------------------------------------------------------- /src/ngx_http_python_directive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef NGX_HTTP_PYTHON_DIRECTIVE_H 8 | #define NGX_HTTP_PYTHON_DIRECTIVE_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | char *ngx_http_python_rewrite_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 15 | char *ngx_http_python_rewrite_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 16 | 17 | char *ngx_http_python_access_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 18 | char *ngx_http_python_access_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 19 | 20 | char *ngx_http_python_content_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 21 | char *ngx_http_python_content_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 22 | 23 | char *ngx_http_python_log_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 24 | char *ngx_http_python_log_inline_phase(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/ngx_http_python_handler.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include 8 | 9 | 10 | 11 | #include "ngx_http_python_handler.h" 12 | #include "ngx_http_python_module.h" 13 | 14 | ngx_int_t ngx_http_python_rewrite_handler(ngx_http_request_t *r) 15 | { 16 | ngx_http_python_loc_conf_t *plcf; 17 | plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 18 | if (plcf->rewrite_handler == NULL){ 19 | return NGX_DECLINED; 20 | } 21 | return plcf->rewrite_handler(r); 22 | } 23 | 24 | ngx_int_t ngx_http_python_rewrite_file_handler(ngx_http_request_t *r) 25 | { 26 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 27 | ngx_http_python_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 28 | 29 | ngx_int_t rc; 30 | 31 | if (ctx == NULL){ 32 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 33 | if (ctx == NULL){ 34 | return NGX_ERROR; 35 | } 36 | } 37 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 38 | 39 | ctx->exit_code = NGX_DECLINED; 40 | 41 | ngx_python_request = r; 42 | 43 | FILE * fp = fopen(plcf->rewrite_file_code->code.file, "r"); 44 | 45 | PyRun_SimpleFile(fp, plcf->rewrite_file_code->code.file); 46 | 47 | ngx_http_python_rputs_chain_list_t *chain; 48 | 49 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 50 | rc = ctx->exit_code; 51 | 52 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 53 | chain = ctx->rputs_chain; 54 | 55 | if (ctx->rputs_chain == NULL){ 56 | return NGX_DECLINED; 57 | } 58 | 59 | if (!r->headers_out.status){ 60 | r->headers_out.status = NGX_HTTP_OK; 61 | } 62 | 63 | if (r->method == NGX_HTTP_HEAD){ 64 | rc = ngx_http_send_header(r); 65 | if (rc != NGX_OK){ 66 | return rc; 67 | } 68 | } 69 | 70 | if (chain != NULL){ 71 | (*chain->last)->buf->last_buf = 1; 72 | } 73 | 74 | rc = ngx_http_send_header(r); 75 | if (rc != NGX_OK){ 76 | return rc; 77 | } 78 | 79 | ngx_http_output_filter(r, chain->out); 80 | 81 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 82 | 83 | return NGX_OK; 84 | } 85 | 86 | if (rc == NGX_ERROR || rc > NGX_OK) { 87 | return rc; 88 | } 89 | 90 | return rc; 91 | } 92 | 93 | ngx_int_t ngx_http_python_rewrite_inline_handler(ngx_http_request_t *r) 94 | { 95 | //ngx_http_python_main_conf_t *pmcf = ngx_http_get_module_main_conf(r, ngx_http_python_module); 96 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 97 | 98 | ngx_int_t rc; 99 | ngx_http_python_ctx_t *ctx; 100 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 101 | 102 | if (ctx == NULL){ 103 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 104 | if (ctx == NULL){ 105 | return NGX_ERROR; 106 | } 107 | } 108 | 109 | ctx->request_body_more = 1; 110 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 111 | 112 | ctx->exit_code = NGX_DECLINED; 113 | 114 | ngx_python_request = r; 115 | 116 | PyRun_SimpleString(plcf->rewrite_inline_code->code.string); 117 | 118 | ngx_http_python_rputs_chain_list_t *chain; 119 | 120 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 121 | rc = ctx->exit_code; 122 | 123 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 124 | 125 | chain = ctx->rputs_chain; 126 | 127 | if (ctx->rputs_chain == NULL){ 128 | return NGX_DECLINED; 129 | } 130 | 131 | if (!r->headers_out.status){ 132 | r->headers_out.status = NGX_HTTP_OK; 133 | } 134 | 135 | if (r->method == NGX_HTTP_HEAD){ 136 | rc = ngx_http_send_header(r); 137 | if (rc != NGX_OK){ 138 | return rc; 139 | } 140 | } 141 | 142 | if (chain != NULL){ 143 | (*chain->last)->buf->last_buf = 1; 144 | } 145 | 146 | rc = ngx_http_send_header(r); 147 | if (rc != NGX_OK){ 148 | return rc; 149 | } 150 | 151 | ngx_http_output_filter(r, chain->out); 152 | 153 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 154 | 155 | return NGX_OK; 156 | 157 | } 158 | 159 | if (rc == NGX_ERROR || rc > NGX_OK) { 160 | return rc; 161 | } 162 | 163 | return rc; 164 | } 165 | 166 | ngx_int_t ngx_http_python_access_handler(ngx_http_request_t *r) 167 | { 168 | ngx_http_python_loc_conf_t *plcf; 169 | plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 170 | if (plcf->access_handler == NULL){ 171 | return NGX_DECLINED; 172 | } 173 | return plcf->access_handler(r); 174 | } 175 | 176 | ngx_int_t ngx_http_python_access_file_handler(ngx_http_request_t *r) 177 | { 178 | //ngx_http_python_main_conf_t *pmcf = ngx_http_get_module_main_conf(r, ngx_http_python_module); 179 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 180 | ngx_http_python_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 181 | 182 | ngx_int_t rc; 183 | 184 | if (ctx == NULL){ 185 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 186 | if (ctx == NULL){ 187 | return NGX_ERROR; 188 | } 189 | } 190 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 191 | 192 | ctx->exit_code = NGX_DECLINED; 193 | 194 | ngx_python_request = r; 195 | 196 | FILE * fp = fopen(plcf->access_file_code->code.file, "r"); 197 | 198 | PyRun_SimpleFile(fp, plcf->access_file_code->code.file); 199 | 200 | ngx_http_python_rputs_chain_list_t *chain; 201 | 202 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 203 | rc = ctx->exit_code; 204 | 205 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 206 | chain = ctx->rputs_chain; 207 | 208 | if (ctx->rputs_chain == NULL){ 209 | return NGX_DECLINED; 210 | } 211 | 212 | if (!r->headers_out.status){ 213 | r->headers_out.status = NGX_HTTP_OK; 214 | } 215 | 216 | if (r->method == NGX_HTTP_HEAD){ 217 | rc = ngx_http_send_header(r); 218 | if (rc != NGX_OK){ 219 | return rc; 220 | } 221 | } 222 | 223 | if (chain != NULL){ 224 | (*chain->last)->buf->last_buf = 1; 225 | } 226 | 227 | rc = ngx_http_send_header(r); 228 | if (rc != NGX_OK){ 229 | return rc; 230 | } 231 | 232 | ngx_http_output_filter(r, chain->out); 233 | 234 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 235 | 236 | return NGX_HTTP_OK; 237 | } 238 | 239 | if (rc == NGX_ERROR || rc > NGX_OK) { 240 | return rc; 241 | } 242 | 243 | return rc; 244 | } 245 | 246 | ngx_int_t ngx_http_python_access_inline_handler(ngx_http_request_t *r) 247 | { 248 | //ngx_http_python_main_conf_t *pmcf = ngx_http_get_module_main_conf(r, ngx_http_python_module); 249 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 250 | 251 | ngx_int_t rc; 252 | ngx_http_python_ctx_t *ctx; 253 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 254 | 255 | if (ctx == NULL){ 256 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 257 | if (ctx == NULL){ 258 | return NGX_ERROR; 259 | } 260 | } 261 | 262 | ctx->request_body_more = 1; 263 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 264 | 265 | ctx->exit_code = NGX_DECLINED; 266 | 267 | ngx_python_request = r; 268 | 269 | PyRun_SimpleString(plcf->access_inline_code->code.string); 270 | 271 | ngx_http_python_rputs_chain_list_t *chain; 272 | 273 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 274 | rc = ctx->exit_code; 275 | 276 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 277 | chain = ctx->rputs_chain; 278 | 279 | if (ctx->rputs_chain == NULL){ 280 | return NGX_DECLINED; 281 | } 282 | 283 | if (!r->headers_out.status){ 284 | r->headers_out.status = NGX_HTTP_OK; 285 | } 286 | 287 | if (r->method == NGX_HTTP_HEAD){ 288 | rc = ngx_http_send_header(r); 289 | if (rc != NGX_OK){ 290 | return rc; 291 | } 292 | } 293 | 294 | if (chain != NULL){ 295 | (*chain->last)->buf->last_buf = 1; 296 | } 297 | 298 | rc = ngx_http_send_header(r); 299 | if (rc != NGX_OK){ 300 | return rc; 301 | } 302 | 303 | ngx_http_output_filter(r, chain->out); 304 | 305 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 306 | 307 | return NGX_HTTP_OK; 308 | } 309 | 310 | if (rc == NGX_ERROR || rc > NGX_OK) { 311 | return rc; 312 | } 313 | 314 | return rc; 315 | } 316 | 317 | ngx_int_t 318 | ngx_http_python_content_handler(ngx_http_request_t *r) 319 | { 320 | ngx_http_python_loc_conf_t *plcf; 321 | plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 322 | if (plcf->content_handler == NULL){ 323 | return NGX_DECLINED; 324 | } 325 | return plcf->content_handler(r); 326 | } 327 | 328 | ngx_int_t 329 | ngx_http_python_content_file_handler(ngx_http_request_t *r) 330 | { 331 | 332 | //ngx_http_python_main_conf_t *pmcf = ngx_http_get_module_main_conf(r, ngx_http_python_module); 333 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 334 | ngx_http_python_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 335 | 336 | ngx_int_t rc; 337 | 338 | if (ctx == NULL){ 339 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 340 | if (ctx == NULL){ 341 | return NGX_ERROR; 342 | } 343 | } 344 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 345 | 346 | ctx->exit_code = NGX_OK; 347 | 348 | ngx_python_request = r; 349 | 350 | FILE * fp = fopen(plcf->content_file_code->code.file, "r"); 351 | 352 | PyRun_SimpleFile(fp, plcf->content_file_code->code.file); 353 | 354 | ngx_http_python_rputs_chain_list_t *chain; 355 | 356 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 357 | rc = ctx->exit_code; 358 | 359 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 360 | chain = ctx->rputs_chain; 361 | 362 | if (ctx->rputs_chain == NULL){ 363 | ngx_buf_t *b; 364 | ngx_str_t ns; 365 | u_char *u_str; 366 | ns.data = (u_char *)" "; 367 | ns.len = 1; 368 | 369 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 370 | chain->out = ngx_alloc_chain_link(r->pool); 371 | chain->last = &chain->out; 372 | 373 | b = ngx_calloc_buf(r->pool); 374 | (*chain->last)->buf = b; 375 | (*chain->last)->next = NULL; 376 | 377 | u_str = ngx_pstrdup(r->pool, &ns); 378 | //u_str[ns.len] = '\0'; 379 | (*chain->last)->buf->pos = u_str; 380 | (*chain->last)->buf->last = u_str + ns.len; 381 | (*chain->last)->buf->memory = 1; 382 | ctx->rputs_chain = chain; 383 | 384 | if (r->headers_out.content_length_n == -1){ 385 | r->headers_out.content_length_n += ns.len + 1; 386 | }else { 387 | r->headers_out.content_length_n += ns.len; 388 | } 389 | } 390 | 391 | //r->headers_out.content_type.len = sizeof("text/html") - 1; 392 | //r->headers_out.content_type.data = (u_char *)"text/html"; 393 | if (!r->headers_out.status){ 394 | r->headers_out.status = NGX_HTTP_OK; 395 | } 396 | 397 | if (r->method == NGX_HTTP_HEAD){ 398 | rc = ngx_http_send_header(r); 399 | if (rc != NGX_OK){ 400 | return rc; 401 | } 402 | } 403 | 404 | if (chain != NULL){ 405 | (*chain->last)->buf->last_buf = 1; 406 | } 407 | 408 | rc = ngx_http_send_header(r); 409 | if (rc != NGX_OK){ 410 | return rc; 411 | } 412 | 413 | ngx_http_output_filter(r, chain->out); 414 | 415 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 416 | 417 | return NGX_OK; 418 | } 419 | 420 | if (rc == NGX_ERROR || rc > NGX_OK) { 421 | return rc; 422 | } 423 | 424 | return NGX_OK; 425 | } 426 | 427 | ngx_int_t 428 | ngx_http_python_content_inline_handler(ngx_http_request_t *r) 429 | { 430 | 431 | //ngx_http_python_main_conf_t *pmcf = ngx_http_get_module_main_conf(r, ngx_http_python_module); 432 | ngx_http_python_loc_conf_t *plcf = ngx_http_get_module_loc_conf(r, ngx_http_python_module); 433 | 434 | ngx_int_t rc; 435 | ngx_http_python_ctx_t *ctx; 436 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 437 | 438 | if (ctx == NULL){ 439 | ctx = ngx_pcalloc(r->pool, sizeof(*ctx)); 440 | if (ctx == NULL){ 441 | return NGX_ERROR; 442 | } 443 | } 444 | 445 | ctx->request_body_more = 1; 446 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 447 | 448 | ctx->exit_code = NGX_OK; 449 | 450 | ngx_python_request = r; 451 | 452 | PyRun_SimpleString(plcf->content_inline_code->code.string); 453 | 454 | ngx_http_python_rputs_chain_list_t *chain; 455 | 456 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 457 | rc = ctx->exit_code; 458 | 459 | if (rc == NGX_OK || rc == NGX_HTTP_OK) { 460 | chain = ctx->rputs_chain; 461 | 462 | if (ctx->rputs_chain == NULL){ 463 | ngx_buf_t *b; 464 | ngx_str_t ns; 465 | u_char *u_str; 466 | ns.data = (u_char *)" "; 467 | ns.len = 1; 468 | 469 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 470 | chain->out = ngx_alloc_chain_link(r->pool); 471 | chain->last = &chain->out; 472 | 473 | b = ngx_calloc_buf(r->pool); 474 | (*chain->last)->buf = b; 475 | (*chain->last)->next = NULL; 476 | 477 | u_str = ngx_pstrdup(r->pool, &ns); 478 | //u_str[ns.len] = '\0'; 479 | (*chain->last)->buf->pos = u_str; 480 | (*chain->last)->buf->last = u_str + ns.len; 481 | (*chain->last)->buf->memory = 1; 482 | ctx->rputs_chain = chain; 483 | 484 | if (r->headers_out.content_length_n == -1){ 485 | r->headers_out.content_length_n += ns.len + 1; 486 | }else { 487 | r->headers_out.content_length_n += ns.len; 488 | } 489 | } 490 | 491 | //r->headers_out.content_type.len = sizeof("text/html") - 1; 492 | //r->headers_out.content_type.data = (u_char *)"text/html"; 493 | if (!r->headers_out.status){ 494 | r->headers_out.status = NGX_HTTP_OK; 495 | } 496 | 497 | if (r->method == NGX_HTTP_HEAD){ 498 | rc = ngx_http_send_header(r); 499 | if (rc != NGX_OK){ 500 | return rc; 501 | } 502 | } 503 | 504 | if (chain != NULL){ 505 | (*chain->last)->buf->last_buf = 1; 506 | } 507 | 508 | rc = ngx_http_send_header(r); 509 | if (rc != NGX_OK){ 510 | return rc; 511 | } 512 | 513 | ngx_http_output_filter(r, chain->out); 514 | 515 | ngx_http_set_ctx(r, NULL, ngx_http_python_module); 516 | 517 | return NGX_OK; 518 | } 519 | 520 | if (rc == NGX_ERROR || rc > NGX_OK) { 521 | return rc; 522 | } 523 | 524 | return NGX_OK; 525 | } 526 | 527 | 528 | 529 | -------------------------------------------------------------------------------- /src/ngx_http_python_handler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef NGX_HTTP_PYTHON_HANDLER_H 8 | #define NGX_HTTP_PYTHON_HANDLER_H 9 | 10 | #include 11 | #include 12 | 13 | #include "ngx_http_python_module.h" 14 | 15 | ngx_int_t ngx_http_python_rewrite_handler(ngx_http_request_t *r); 16 | ngx_int_t ngx_http_python_rewrite_file_handler(ngx_http_request_t *r); 17 | ngx_int_t ngx_http_python_rewrite_inline_handler(ngx_http_request_t *r); 18 | 19 | ngx_int_t ngx_http_python_access_handler(ngx_http_request_t *r); 20 | ngx_int_t ngx_http_python_access_file_handler(ngx_http_request_t *r); 21 | ngx_int_t ngx_http_python_access_inline_handler(ngx_http_request_t *r); 22 | 23 | ngx_int_t ngx_http_python_content_handler(ngx_http_request_t *r); 24 | ngx_int_t ngx_http_python_content_file_handler(ngx_http_request_t *r); 25 | ngx_int_t ngx_http_python_content_inline_handler(ngx_http_request_t *r); 26 | 27 | ngx_int_t ngx_http_python_log_handler(ngx_http_request_t *r); 28 | ngx_int_t ngx_http_python_log_file_handler(ngx_http_request_t *r); 29 | ngx_int_t ngx_http_python_log_inline_handler(ngx_http_request_t *r); 30 | 31 | #endif -------------------------------------------------------------------------------- /src/ngx_http_python_module.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "ngx_http_python_module.h" 16 | #include "ngx_http_python_directive.h" 17 | #include "ngx_http_python_handler.h" 18 | 19 | #include "python/python_ngx.h" 20 | 21 | static ngx_int_t ngx_http_python_init(ngx_conf_t *cf); 22 | static ngx_int_t ngx_http_python_handler_init(ngx_http_core_main_conf_t *cmcf, ngx_http_python_main_conf_t *pmcf); 23 | 24 | static void *ngx_http_python_create_main_conf(ngx_conf_t *cf); 25 | static char *ngx_http_python_init_main_conf(ngx_conf_t *cf, void *conf); 26 | 27 | static void *ngx_http_python_create_loc_conf(ngx_conf_t *cf); 28 | static char *ngx_http_python_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); 29 | 30 | static ngx_int_t ngx_http_python_init_worker(ngx_cycle_t *cycle); 31 | static void ngx_http_python_exit_worker(ngx_cycle_t *cycle); 32 | 33 | static ngx_command_t ngx_http_python_commands[] = { 34 | 35 | {ngx_string("rewrite_by_python_file"), 36 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 37 | |NGX_CONF_TAKE1, 38 | ngx_http_python_rewrite_phase, 39 | NGX_HTTP_LOC_CONF_OFFSET, 40 | 0, 41 | ngx_http_python_rewrite_file_handler 42 | }, 43 | 44 | {ngx_string("rewrite_by_python"), 45 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 46 | |NGX_CONF_TAKE1, 47 | ngx_http_python_rewrite_inline_phase, 48 | NGX_HTTP_LOC_CONF_OFFSET, 49 | 0, 50 | ngx_http_python_rewrite_inline_handler 51 | }, 52 | 53 | {ngx_string("access_by_python_file"), 54 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 55 | |NGX_CONF_TAKE1, 56 | ngx_http_python_access_phase, 57 | NGX_HTTP_LOC_CONF_OFFSET, 58 | 0, 59 | ngx_http_python_access_file_handler 60 | }, 61 | 62 | {ngx_string("access_by_python"), 63 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 64 | |NGX_CONF_TAKE1, 65 | ngx_http_python_access_inline_phase, 66 | NGX_HTTP_LOC_CONF_OFFSET, 67 | 0, 68 | ngx_http_python_access_inline_handler 69 | }, 70 | 71 | {ngx_string("content_by_python_file"), 72 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 73 | |NGX_CONF_TAKE1, 74 | ngx_http_python_content_phase, 75 | NGX_HTTP_LOC_CONF_OFFSET, 76 | 0, 77 | ngx_http_python_content_file_handler 78 | }, 79 | 80 | {ngx_string("content_by_python"), 81 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 82 | |NGX_CONF_TAKE1, 83 | ngx_http_python_content_inline_phase, 84 | NGX_HTTP_LOC_CONF_OFFSET, 85 | 0, 86 | ngx_http_python_content_inline_handler 87 | }, 88 | 89 | /*{ngx_string("log_by_python_file"), 90 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 91 | |NGX_CONF_TAKE1, 92 | ngx_http_python_log_phase, 93 | NGX_HTTP_LOC_CONF_OFFSET, 94 | 0, 95 | ngx_http_python_log_file_handler 96 | }, 97 | 98 | {ngx_string("log_by_python"), 99 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 100 | |NGX_CONF_TAKE1, 101 | ngx_http_python_log_inline_phase, 102 | NGX_HTTP_LOC_CONF_OFFSET, 103 | 0, 104 | ngx_http_python_log_inline_handler 105 | },*/ 106 | 107 | ngx_null_command 108 | 109 | }; 110 | 111 | static ngx_http_module_t ngx_http_python_module_ctx = { 112 | NULL, /* preconfiguration */ 113 | ngx_http_python_init, /* postconfiguration */ 114 | 115 | ngx_http_python_create_main_conf, /* create main configuration */ 116 | ngx_http_python_init_main_conf, /* init main configuration */ 117 | 118 | NULL, /* create server configuration */ 119 | NULL, /* merge server configuration */ 120 | 121 | ngx_http_python_create_loc_conf, /* create location configuration */ 122 | ngx_http_python_merge_loc_conf /* merge location configuration */ 123 | }; 124 | 125 | ngx_module_t ngx_http_python_module = { 126 | NGX_MODULE_V1, 127 | &ngx_http_python_module_ctx, /* module context */ 128 | ngx_http_python_commands, /* module directives */ 129 | NGX_HTTP_MODULE, /* module type */ 130 | NULL, /* init master */ 131 | NULL, /* init module */ 132 | ngx_http_python_init_worker, /* init process */ 133 | NULL, /* init thread */ 134 | NULL, /* exit thread */ 135 | ngx_http_python_exit_worker, /* exit process */ 136 | NULL, /* exit master */ 137 | NGX_MODULE_V1_PADDING 138 | }; 139 | 140 | static ngx_int_t 141 | ngx_http_python_init(ngx_conf_t *cf) 142 | { 143 | ngx_http_core_main_conf_t *cmcf; 144 | ngx_http_python_main_conf_t *pmcf; 145 | 146 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 147 | pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_python_module); 148 | 149 | ngx_python_request = NULL; 150 | 151 | if (ngx_http_python_handler_init(cmcf, pmcf) != NGX_OK){ 152 | return NGX_ERROR; 153 | } 154 | 155 | return NGX_OK; 156 | } 157 | 158 | static ngx_int_t 159 | ngx_http_python_handler_init(ngx_http_core_main_conf_t *cmcf, ngx_http_python_main_conf_t *pmcf) 160 | { 161 | ngx_int_t i; 162 | ngx_http_handler_pt *h; 163 | ngx_http_phases phase; 164 | ngx_http_phases phases[] = { 165 | //NGX_HTTP_POST_READ_PHASE, 166 | NGX_HTTP_REWRITE_PHASE, 167 | NGX_HTTP_ACCESS_PHASE, 168 | NGX_HTTP_CONTENT_PHASE, 169 | NGX_HTTP_LOG_PHASE, 170 | }; 171 | ngx_int_t phases_c; 172 | 173 | phases_c = sizeof(phases) / sizeof(ngx_http_phases); 174 | for (i = 0; i < phases_c; i++){ 175 | phase = phases[i]; 176 | switch (phase){ 177 | /*case NGX_HTTP_POST_READ_PHASE: 178 | if (pmcf->enabled_post_read_handler){ 179 | h = ngx_array_push(&cmcf->phases[phase].handlers); 180 | if (h == NULL){ 181 | return NGX_ERROR; 182 | } 183 | *h = ngx_http_python_post_read_handler; 184 | } 185 | break;*/ 186 | case NGX_HTTP_REWRITE_PHASE: 187 | if (pmcf->enabled_rewrite_handler){ 188 | h = ngx_array_push(&cmcf->phases[phase].handlers); 189 | if (h == NULL){ 190 | return NGX_ERROR; 191 | } 192 | *h = ngx_http_python_rewrite_handler; 193 | } 194 | break; 195 | case NGX_HTTP_ACCESS_PHASE: 196 | if (pmcf->enabled_access_handler){ 197 | h = ngx_array_push(&cmcf->phases[phase].handlers); 198 | if (h == NULL){ 199 | return NGX_ERROR; 200 | } 201 | *h = ngx_http_python_access_handler; 202 | } 203 | break; 204 | case NGX_HTTP_CONTENT_PHASE: 205 | if (pmcf->enabled_content_handler){ 206 | h = ngx_array_push(&cmcf->phases[phase].handlers); 207 | if (h == NULL){ 208 | return NGX_ERROR; 209 | } 210 | *h = ngx_http_python_content_handler; 211 | } 212 | break; 213 | /*case NGX_HTTP_LOG_PHASE: 214 | if (pmcf->enabled_log_handler){ 215 | h = ngx_array_push(&cmcf->phases[phase].handlers); 216 | if (h == NULL){ 217 | return NGX_ERROR; 218 | } 219 | *h = ngx_http_log_content_handler; 220 | } 221 | break;*/ 222 | default: 223 | break; 224 | } 225 | } 226 | 227 | return NGX_OK; 228 | } 229 | 230 | static void * 231 | ngx_http_python_create_main_conf(ngx_conf_t *cf) 232 | { 233 | ngx_http_python_main_conf_t *pmcf; 234 | 235 | pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_python_main_conf_t)); 236 | if (pmcf == NULL){ 237 | return NULL; 238 | } 239 | 240 | /*pmcf->state = ngx_pcalloc(cf->pool, sizeof(ngx_http_python_state_t)); 241 | if (pmcf->state == NULL){ 242 | return NULL; 243 | }*/ 244 | 245 | 246 | return pmcf; 247 | } 248 | 249 | static char * 250 | ngx_http_python_init_main_conf(ngx_conf_t *cf, void *conf) 251 | { 252 | return NGX_CONF_OK; 253 | } 254 | 255 | static void * 256 | ngx_http_python_create_loc_conf(ngx_conf_t *cf) 257 | { 258 | ngx_http_python_loc_conf_t *plcf; 259 | 260 | plcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_python_loc_conf_t)); 261 | if (plcf == NULL){ 262 | return NGX_CONF_ERROR; 263 | } 264 | 265 | plcf->rewrite_file_code = NGX_CONF_UNSET_PTR; 266 | plcf->rewrite_inline_code = NGX_CONF_UNSET_PTR; 267 | 268 | plcf->access_file_code = NGX_CONF_UNSET_PTR; 269 | plcf->access_inline_code = NGX_CONF_UNSET_PTR; 270 | 271 | plcf->content_file_code = NGX_CONF_UNSET_PTR; 272 | plcf->content_inline_code = NGX_CONF_UNSET_PTR; 273 | 274 | plcf->log_file_code = NGX_CONF_UNSET_PTR; 275 | plcf->log_inline_code = NGX_CONF_UNSET_PTR; 276 | 277 | return plcf; 278 | } 279 | 280 | static char * 281 | ngx_http_python_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) 282 | { 283 | //ngx_http_core_loc_conf_t *clcf; 284 | //clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); 285 | 286 | ngx_http_python_loc_conf_t *prev = parent; 287 | ngx_http_python_loc_conf_t *conf = child; 288 | 289 | prev->rewrite_file_code = conf->rewrite_file_code; 290 | prev->rewrite_inline_code = conf->rewrite_inline_code; 291 | 292 | prev->access_file_code = conf->access_file_code; 293 | prev->access_inline_code = conf->access_inline_code; 294 | 295 | prev->content_file_code = conf->content_file_code; 296 | prev->content_inline_code = conf->content_inline_code; 297 | 298 | prev->log_file_code = conf->log_file_code; 299 | prev->log_inline_code = conf->log_inline_code; 300 | 301 | return NGX_CONF_OK; 302 | } 303 | 304 | static ngx_int_t 305 | ngx_http_python_init_worker(ngx_cycle_t *cycle) 306 | { 307 | //ngx_http_python_main_conf_t *pmcf; 308 | 309 | //pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_python_module); 310 | 311 | Py_Initialize(); 312 | 313 | initNgx(); 314 | 315 | return NGX_OK; 316 | } 317 | 318 | static void 319 | ngx_http_python_exit_worker(ngx_cycle_t *cycle) 320 | { 321 | Py_Finalize(); 322 | } 323 | -------------------------------------------------------------------------------- /src/ngx_http_python_module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef NGX_HTTP_PYTHON_MODULE_H 8 | #define NGX_HTTP_PYTHON_MODULE_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "ngx_http_python_code.h" 16 | 17 | #define NGX_HTTP_PYTHON_MODULE_NAME "ngx_python" 18 | #define NGX_HTTP_PYTHON_MODULE_VERSION "0.0.1" 19 | 20 | extern ngx_module_t ngx_http_python_module; 21 | ngx_http_request_t *ngx_python_request; 22 | 23 | typedef struct { 24 | unsigned enabled_rewrite_handler:1; 25 | unsigned enabled_access_handler:1; 26 | unsigned enabled_content_handler:1; 27 | unsigned enabled_log_handler:1; 28 | } ngx_http_python_main_conf_t; 29 | 30 | typedef struct { 31 | ngx_http_python_code_t *rewrite_file_code; 32 | ngx_http_python_code_t *rewrite_inline_code; 33 | ngx_http_python_code_t *access_file_code; 34 | ngx_http_python_code_t *access_inline_code; 35 | ngx_http_python_code_t *content_file_code; 36 | ngx_http_python_code_t *content_inline_code; 37 | ngx_http_python_code_t *log_file_code; 38 | ngx_http_python_code_t *log_inline_code; 39 | 40 | ngx_int_t (*rewrite_handler)(ngx_http_request_t *r); 41 | ngx_int_t (*access_handler)(ngx_http_request_t *r); 42 | ngx_int_t (*content_handler)(ngx_http_request_t *r); 43 | ngx_int_t (*log_handler)(ngx_http_request_t *r); 44 | } ngx_http_python_loc_conf_t; 45 | 46 | #endif -------------------------------------------------------------------------------- /src/ngx_http_python_output.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | */ 4 | 5 | #include "ngx_http_python_module.h" 6 | #include "ngx_http_python_output.h" 7 | 8 | void 9 | ngx_http_python_set_output(ngx_http_request_t *r, char *buffer, int buffer_len) 10 | { 11 | ngx_buf_t *b; 12 | ngx_http_python_rputs_chain_list_t *chain; 13 | ngx_http_python_ctx_t *ctx; 14 | u_char *u_str; 15 | ngx_str_t ns; 16 | 17 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 18 | 19 | ns.data = (u_char *)buffer; 20 | ns.len = buffer_len; 21 | 22 | if (ctx->rputs_chain == NULL){ 23 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 24 | chain->out = ngx_alloc_chain_link(r->pool); 25 | chain->last = &chain->out; 26 | }else { 27 | chain = ctx->rputs_chain; 28 | (*chain->last)->next = ngx_alloc_chain_link(r->pool); 29 | chain->last = &(*chain->last)->next; 30 | } 31 | 32 | b = ngx_calloc_buf(r->pool); 33 | (*chain->last)->buf = b; 34 | (*chain->last)->next = NULL; 35 | 36 | u_str = ngx_pstrdup(r->pool, &ns); 37 | //u_str[ns.len] = '\0'; 38 | (*chain->last)->buf->pos = u_str; 39 | (*chain->last)->buf->last = u_str + ns.len; 40 | (*chain->last)->buf->memory = 1; 41 | ctx->rputs_chain = chain; 42 | 43 | if (r->headers_out.content_length_n == -1){ 44 | r->headers_out.content_length_n += ns.len + 1; 45 | }else { 46 | r->headers_out.content_length_n += ns.len; 47 | } 48 | } 49 | 50 | void 51 | ngx_http_python_check_output_empty(ngx_http_request_t *r) 52 | { 53 | ngx_http_python_rputs_chain_list_t *chain; 54 | ngx_http_python_ctx_t *ctx; 55 | 56 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 57 | 58 | chain = ctx->rputs_chain; 59 | 60 | if (ctx->rputs_chain == NULL){ 61 | ngx_buf_t *b; 62 | ngx_str_t ns; 63 | u_char *u_str; 64 | ns.data = (u_char *)" "; 65 | ns.len = 1; 66 | 67 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 68 | chain->out = ngx_alloc_chain_link(r->pool); 69 | chain->last = &chain->out; 70 | 71 | b = ngx_calloc_buf(r->pool); 72 | (*chain->last)->buf = b; 73 | (*chain->last)->next = NULL; 74 | 75 | u_str = ngx_pstrdup(r->pool, &ns); 76 | //u_str[ns.len] = '\0'; 77 | (*chain->last)->buf->pos = u_str; 78 | (*chain->last)->buf->last = u_str + ns.len; 79 | (*chain->last)->buf->memory = 1; 80 | ctx->rputs_chain = chain; 81 | 82 | if (r->headers_out.content_length_n == -1){ 83 | r->headers_out.content_length_n += ns.len + 1; 84 | }else { 85 | r->headers_out.content_length_n += ns.len; 86 | } 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/ngx_http_python_output.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | */ 4 | 5 | #ifndef NGX_HTTP_PYTHON_OUTPUT_H 6 | #define NGX_HTTP_PYTHON_OUTPUT_H 7 | 8 | #include 9 | #include 10 | 11 | void ngx_http_python_set_output(ngx_http_request_t *r, char *buffer, int buffer_len); 12 | 13 | void ngx_http_python_check_output_empty(ngx_http_request_t *r); 14 | 15 | #endif -------------------------------------------------------------------------------- /src/ngx_python_uthread.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include "ngx_python_uthread.h" 8 | 9 | static void ngx_python_uthread_routine(ngx_python_uthread_t *uthread); 10 | 11 | static void 12 | ngx_python_uthread_routine(ngx_python_uthread_t *uthread) 13 | { 14 | uthread->routine(uthread->data); 15 | } 16 | 17 | ngx_int_t 18 | ngx_python_uthread_create(ngx_python_uthread_t *uthread) 19 | { 20 | 21 | if (getcontext(&uthread->child) == -1) { 22 | return -1; 23 | } 24 | 25 | ngx_python_uthread_max++; 26 | uthread->id = ngx_python_uthread_max; 27 | uthread->status = PYTHON_UTHREAD_READY; 28 | 29 | uthread->child.uc_stack.ss_size = PYTHON_UTHREAD_STACK_SIZE; 30 | uthread->child.uc_stack.ss_sp = uthread->stack; 31 | uthread->child.uc_link = &uthread->main; 32 | 33 | makecontext(&uthread->child, (void (*)(void)) ngx_python_uthread_routine, 1, uthread); 34 | 35 | if (swapcontext(&uthread->main, &uthread->child) == -1) { 36 | return -1; 37 | } 38 | 39 | return 0; 40 | 41 | } 42 | 43 | ngx_int_t 44 | ngx_python_uthread_yield(ngx_python_uthread_t *uthread) 45 | { 46 | uthread->status = PYTHON_UTHREAD_RUNNING; 47 | 48 | if (swapcontext(&uthread->child, &uthread->main) == -1) { 49 | return -1; 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | ngx_int_t 56 | ngx_python_uthread_resume(ngx_python_uthread_t *uthread) 57 | { 58 | uthread->status = PYTHON_UTHREAD_SUSPEND; 59 | 60 | if (swapcontext(&uthread->main, &uthread->child) == -1) { 61 | return -1; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | 68 | ngx_uint_t 69 | ngx_python_uthread_id(ngx_python_uthread_t *uthread) 70 | { 71 | if (uthread->id) { 72 | return uthread->id; 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/ngx_python_uthread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef _NGX_PYTHON_UTHREAD_H_ 8 | #define _NGX_PYTHON_UTHREAD_H_ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #define PYTHON_UTHREAD_DEAD 0 16 | #define PYTHON_UTHREAD_READY 1 17 | #define PYTHON_UTHREAD_RUNNING 2 18 | #define PYTHON_UTHREAD_SUSPEND 3 19 | 20 | #define PYTHON_UTHREAD_STACK_SIZE 32*1024 21 | #define PYTHON_UTHREAD_MAX_SIZE 1024 22 | 23 | ngx_uint_t ngx_python_uthread_max; 24 | 25 | typedef struct ngx_python_uthread_s { 26 | 27 | ngx_uint_t id; 28 | ngx_int_t status; 29 | 30 | ucontext_t child; 31 | ucontext_t main; 32 | 33 | void *stack; 34 | size_t stack_size; 35 | 36 | void (*routine)(void *data); 37 | void *data; 38 | 39 | ngx_log_t *log; 40 | 41 | } ngx_python_uthread_t; 42 | 43 | ngx_int_t ngx_python_uthread_create(ngx_python_uthread_t *uthread); 44 | 45 | ngx_int_t ngx_python_uthread_yield(ngx_python_uthread_t *uthread); 46 | 47 | ngx_int_t ngx_python_uthread_resume(ngx_python_uthread_t *uthread); 48 | 49 | ngx_int_t ngx_python_uthread_destroy(ngx_python_uthread_t *uthread); 50 | 51 | ngx_uint_t ngx_python_uthread_id(ngx_python_uthread_t *uthread); 52 | 53 | #endif -------------------------------------------------------------------------------- /src/python/python_ngx.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include 8 | #include "python_ngx.h" 9 | #include "../ngx_http_python_module.h" 10 | #include "../ngx_http_python_code.h" 11 | 12 | static PyObject * 13 | ngx_echo(PyObject *self, PyObject *args) 14 | { 15 | PyObject *object; 16 | 17 | ngx_buf_t *b; 18 | ngx_http_python_rputs_chain_list_t *chain; 19 | ngx_http_python_ctx_t *ctx; 20 | ngx_http_request_t *r; 21 | u_char *u_str; 22 | ngx_str_t ns; 23 | 24 | r = ngx_python_request; 25 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 26 | 27 | if (!PyArg_ParseTuple(args, "O", &object)){ 28 | return NULL; 29 | } 30 | 31 | PyObject *s; 32 | s = PyObject_Str(object); 33 | 34 | ns.len = PyBytes_GET_SIZE(s); 35 | ns.data = (u_char *)PyBytes_AS_STRING(s); 36 | 37 | if (ctx->rputs_chain == NULL){ 38 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 39 | chain->out = ngx_alloc_chain_link(r->pool); 40 | chain->last = &chain->out; 41 | }else { 42 | chain = ctx->rputs_chain; 43 | (*chain->last)->next = ngx_alloc_chain_link(r->pool); 44 | chain->last = &(*chain->last)->next; 45 | } 46 | 47 | b = ngx_calloc_buf(r->pool); 48 | (*chain->last)->buf = b; 49 | (*chain->last)->next = NULL; 50 | 51 | u_str = ngx_pstrdup(r->pool, &ns); 52 | //u_str[ns.len] = '\0'; 53 | (*chain->last)->buf->pos = u_str; 54 | (*chain->last)->buf->last = u_str + ns.len; 55 | (*chain->last)->buf->memory = 1; 56 | ctx->rputs_chain = chain; 57 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 58 | 59 | if (r->headers_out.content_length_n == -1){ 60 | r->headers_out.content_length_n += ns.len + 1; 61 | }else { 62 | r->headers_out.content_length_n += ns.len; 63 | } 64 | 65 | return Py_BuildValue("i", r->headers_out.content_length_n); 66 | } 67 | 68 | static PyObject * 69 | ngx_print(PyObject *self, PyObject *args) 70 | { 71 | PyObject *object; 72 | 73 | ngx_buf_t *b; 74 | ngx_http_python_rputs_chain_list_t *chain; 75 | ngx_http_python_ctx_t *ctx; 76 | ngx_http_request_t *r; 77 | u_char *u_str; 78 | ngx_str_t ns; 79 | 80 | r = ngx_python_request; 81 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 82 | 83 | if (!PyArg_ParseTuple(args, "O", &object)){ 84 | return NULL; 85 | } 86 | 87 | PyObject *s; 88 | s = PyObject_Str(object); 89 | 90 | ns.len = PyBytes_GET_SIZE(s); 91 | ns.data = (u_char *)PyBytes_AS_STRING(s); 92 | 93 | if (ctx->rputs_chain == NULL){ 94 | chain = ngx_pcalloc(r->pool, sizeof(ngx_http_python_rputs_chain_list_t)); 95 | chain->out = ngx_alloc_chain_link(r->pool); 96 | chain->last = &chain->out; 97 | }else { 98 | chain = ctx->rputs_chain; 99 | (*chain->last)->next = ngx_alloc_chain_link(r->pool); 100 | chain->last = &(*chain->last)->next; 101 | } 102 | 103 | b = ngx_calloc_buf(r->pool); 104 | (*chain->last)->buf = b; 105 | (*chain->last)->next = NULL; 106 | 107 | u_str = ngx_pstrdup(r->pool, &ns); 108 | //u_str[ns.len] = '\0'; 109 | (*chain->last)->buf->pos = u_str; 110 | (*chain->last)->buf->last = u_str + ns.len; 111 | (*chain->last)->buf->memory = 1; 112 | 113 | *b->last++ = '\n'; 114 | 115 | ctx->rputs_chain = chain; 116 | ngx_http_set_ctx(r, ctx, ngx_http_python_module); 117 | 118 | if (r->headers_out.content_length_n == -1){ 119 | r->headers_out.content_length_n += ns.len + 1 + 1; 120 | }else { 121 | r->headers_out.content_length_n += ns.len + 1; 122 | } 123 | 124 | return Py_BuildValue("i", r->headers_out.content_length_n); 125 | } 126 | 127 | static PyObject * 128 | ngx_exit(PyObject *self, PyObject *args) 129 | { 130 | PyObject *exit_code = 0; 131 | 132 | ngx_http_python_ctx_t *ctx; 133 | ngx_http_request_t *r; 134 | 135 | r = ngx_python_request; 136 | ctx = ngx_http_get_module_ctx(r, ngx_http_python_module); 137 | 138 | if (!PyArg_ParseTuple(args, "l", &exit_code)){ 139 | return NULL; 140 | } 141 | 142 | ctx->exit_code = (ngx_int_t )(exit_code); 143 | 144 | return Py_BuildValue("l", exit_code); 145 | } 146 | 147 | static PyMethodDef NgxMethods[]={ 148 | {"echo", ngx_echo, METH_VARARGS, "ngx.echo"}, 149 | {"_print", ngx_print, METH_VARARGS, "ngx._print"}, 150 | {"exit", ngx_exit, METH_VARARGS, "ngx.exit"}, 151 | {NULL, NULL, 0, NULL} 152 | }; 153 | 154 | void initNgx() 155 | { 156 | PyObject *mo; 157 | 158 | mo = Py_InitModule("ngx",NgxMethods); 159 | 160 | PyModule_AddIntConstant(mo, "OK", NGX_OK); 161 | PyModule_AddIntConstant(mo, "ERROR", NGX_ERROR); 162 | PyModule_AddIntConstant(mo, "AGAIN", NGX_AGAIN); 163 | PyModule_AddIntConstant(mo, "BUSY", NGX_BUSY); 164 | PyModule_AddIntConstant(mo, "DONE", NGX_DONE); 165 | PyModule_AddIntConstant(mo, "DECLINED", NGX_DECLINED); 166 | PyModule_AddIntConstant(mo, "ABORT", NGX_ABORT); 167 | 168 | PyModule_AddIntConstant(mo, "LOG_STDERR", NGX_LOG_STDERR); 169 | PyModule_AddIntConstant(mo, "LOG_EMERG", NGX_LOG_EMERG); 170 | PyModule_AddIntConstant(mo, "LOG_ALERT", NGX_LOG_ALERT); 171 | PyModule_AddIntConstant(mo, "LOG_CRIT", NGX_LOG_CRIT); 172 | PyModule_AddIntConstant(mo, "LOG_ERR", NGX_LOG_ERR); 173 | PyModule_AddIntConstant(mo, "LOG_WARN", NGX_LOG_WARN); 174 | PyModule_AddIntConstant(mo, "LOG_NOTICE", NGX_LOG_NOTICE); 175 | PyModule_AddIntConstant(mo, "LOG_INFO", NGX_LOG_INFO); 176 | PyModule_AddIntConstant(mo, "LOG_DEBUG", NGX_LOG_DEBUG); 177 | 178 | } -------------------------------------------------------------------------------- /src/python/python_ngx.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef PYTHON_NGX_H 8 | #define PYTHON_NGX_H 9 | 10 | void initNgx(); 11 | 12 | #endif -------------------------------------------------------------------------------- /src/python/python_ngx_request.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #include 8 | #include "python_ngx_request.h" 9 | #include "../ngx_http_python_module.h" 10 | #include "../ngx_http_python_code.h" -------------------------------------------------------------------------------- /src/python/python_ngx_request.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright(c) 2016-2017 rryqszq4 3 | * 4 | * 5 | */ 6 | 7 | #ifndef PYTHON_NGX_REQUEST_H 8 | #define PYTHON_NGX_REQUEST_H 9 | 10 | void initNgxRequest(); 11 | 12 | #endif -------------------------------------------------------------------------------- /t/library/hello.py: -------------------------------------------------------------------------------- 1 | import ngx 2 | 3 | ngx.echo("Hello, Ngx_python\n") -------------------------------------------------------------------------------- /travis/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2016-2017, rryqszq4 3 | mkdir build 4 | cd build 5 | mkdir python 6 | mkdir nginx 7 | echo "python download ..." 8 | wget https://www.python.org/ftp/python/${PYTHON_SRC_VERSION}/Python-${PYTHON_SRC_VERSION}.tgz 9 | echo "python download ... done" 10 | tar -xf Python-${PYTHON_SRC_VERSION}.tgz 11 | 12 | PYTHON_SRC=`pwd`'/Python-'${PYTHON_SRC_VERSION} 13 | PYTHON_SRC_ROOT=`pwd`'/python' 14 | cd ${PYTHON_SRC} 15 | 16 | echo "python install ..." 17 | ./configure --prefix=${PYTHON_SRC_ROOT} 18 | make 19 | make install 20 | echo "python install ... done" 21 | 22 | cd .. 23 | echo "nginx download ..." 24 | wget http://nginx.org/download/nginx-${NGINX_SRC_VERSION}.tar.gz 25 | echo "nginx download ... done" 26 | tar xf nginx-${NGINX_SRC_VERSION}.tar.gz 27 | 28 | NGINX_SRC=`pwd`'/nginx-'${NGINX_SRC_VERSION} 29 | NGINX_SRC_ROOT=`pwd`'/nginx' 30 | cd ${NGINX_SRC} 31 | 32 | export PYTHON_INC=${PYTHON_SRC_ROOT}'/include/python2.7' 33 | export PYTHON_BIN=${PYTHON_SRC_ROOT}'/bin' 34 | 35 | ls ${PYTHON_SRC_ROOT} 36 | 37 | echo "nginx install ..." 38 | ./configure --prefix=${NGINX_SRC_ROOT} \ 39 | --add-module=../../../ngx_python 40 | make 41 | make install 42 | if [ $? -eq 0 ];then 43 | echo "nginx install ... done" 44 | echo "ngx_python compile success." 45 | else 46 | echo "ngx_python compile failed." 47 | exit 1 48 | fi 49 | #echo "nginx install ... done" 50 | #cd ../.. 51 | #echo "ngx_python compile success." --------------------------------------------------------------------------------