Skip to content

Commit 941a914

Browse files
author
Samuel
committed
add wsgi support
1 parent f7be8e8 commit 941a914

File tree

4 files changed

+194
-16
lines changed

4 files changed

+194
-16
lines changed

nginx/http/http.pyx

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
from cpython cimport Py_INCREF, Py_DECREF
2-
from .nginx_core cimport ngx_log_error, NGX_LOG_CRIT, NGX_AGAIN, from_nginx_str
3-
from .ngx_http cimport ngx_http_request_t, ngx_http_core_run_phases
4-
from .ngx_http cimport ngx_http_get_module_ctx, ngx_http_set_ctx
2+
from .nginx_core cimport (
3+
ngx_log_error,
4+
NGX_LOG_CRIT,
5+
NGX_AGAIN,
6+
from_nginx_str,
7+
ngx_calloc,
8+
ngx_free,
9+
ngx_memcpy,
10+
)
11+
from .ngx_http cimport (
12+
ngx_http_request_t,
13+
ngx_http_core_run_phases,
14+
ngx_http_get_module_ctx,
15+
ngx_http_set_ctx,
16+
ngx_http_send_header,
17+
ngx_list_push,
18+
ngx_table_elt_t,
19+
ngx_str_set,
20+
ngx_http_output_filter,
21+
ngx_chain_t,
22+
ngx_buf_t,
23+
ngx_calloc_buf,
24+
)
525

626
import traceback
727

@@ -17,6 +37,8 @@ cdef class Request:
1737
public str extension
1838
public str unparsed_uri
1939
public str method_name
40+
public str content_type
41+
public str content_length
2042
public str http_protocol
2143

2244
def __init__(self, *args):
@@ -37,17 +59,82 @@ cdef class Request:
3759
return self.future.result()
3860
return NGX_AGAIN
3961

62+
def send_header(self):
63+
return ngx_http_send_header(self.request)
64+
65+
def add_response_header(self, key, value):
66+
cdef:
67+
ngx_table_elt_t *h
68+
char *cstr
69+
char *csource
70+
bytes key_data, value_data
71+
h = ngx_list_push(&self.request.headers_out.headers)
72+
if h == NULL:
73+
raise MemoryError()
74+
h.hash = 1
75+
76+
key_data = str(key).encode('iso8859-1')
77+
cstr = <char *>ngx_calloc(sizeof(char) * len(key_data), self.request.connection.log)
78+
h.key.len = len(key_data)
79+
csource = key_data
80+
ngx_memcpy(cstr, csource, len(key_data))
81+
h.key.data = cstr
82+
83+
value_data = str(value).encode('iso8859-1')
84+
cstr = <char *>ngx_calloc(sizeof(char) * len(value_data), self.request.connection.log)
85+
h.value.len = len(value_data)
86+
csource = value_data
87+
ngx_memcpy(cstr, csource, len(value_data))
88+
h.value.data = cstr
89+
90+
def send_response(self, pos):
91+
cdef:
92+
ngx_chain_t out
93+
ngx_buf_t *b
94+
bytes data = pos
95+
char* cstr = data
96+
b = ngx_calloc_buf(self.request.pool)
97+
if b == NULL:
98+
raise MemoryError
99+
b.last_buf = 1
100+
b.last_in_chain = 1
101+
b.memory = 1
102+
b.pos = cstr
103+
b.last = b.pos + len(data)
104+
105+
out.buf = b
106+
out.next = NULL
107+
108+
return ngx_http_output_filter(self.request, &out)
109+
110+
property response_status:
111+
def __get__(self):
112+
return self.request.headers_out.status
113+
114+
def __set__(self, value):
115+
self.request.headers_out.status = value
116+
117+
property response_content_length:
118+
def __get__(self):
119+
if self.request.headers_out.content_length:
120+
return self.request.headers_out.content_length.value
121+
122+
def __set__(self, value):
123+
self.request.headers_out.content_length.value = value
124+
40125
def __repr__(self):
41126
return f'Request({self.method_name} {self.uri})'
42127

43128
def __str__(self):
44129
return f''' request_line: {self.request_line}
45-
uri: {self.uri}
46-
args: {self.args}
47-
extension: {self.extension}
48-
unparsed_uri: {self.unparsed_uri}
49-
method_name: {self.method_name}
50-
http_protocol: {self.http_protocol}'''
130+
uri: {self.uri}
131+
args: {self.args}
132+
extension: {self.extension}
133+
unparsed_uri: {self.unparsed_uri}
134+
method_name: {self.method_name}
135+
content_type: {self.content_type}
136+
content_length: {self.content_length}
137+
http_protocol: {self.http_protocol}'''
51138

52139
@staticmethod
53140
cdef Request from_ptr(ngx_http_request_t *request):
@@ -67,6 +154,12 @@ http_protocol: {self.http_protocol}'''
67154
new_req.unparsed_uri = from_nginx_str(request.unparsed_uri)
68155
new_req.method_name = from_nginx_str(request.method_name)
69156
new_req.http_protocol = from_nginx_str(request.http_protocol)
157+
if request.headers_in.content_type:
158+
new_req.content_type = from_nginx_str(
159+
request.headers_in.content_type.value)
160+
if request.headers_in.content_length:
161+
new_req.content_length = from_nginx_str(
162+
request.headers_in.content_length.value)
70163

71164
ngx_http_set_ctx(request, <void *>new_req, ngx_python_module)
72165
return new_req

nginx/http/module.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import asyncio
2+
import io
3+
import sys
4+
import functools
25

36
from . import log
47
from .._nginx import run_phases
@@ -13,14 +16,48 @@ def __init__(self):
1316
def init_process(self):
1417
self.loop = asyncio.get_event_loop()
1518

19+
def start_response(self, request, status, response_headers, exc_info=None):
20+
request.response_status = int(status.split(maxsplit=1)[0])
21+
for key, value in response_headers:
22+
request.add_response_header(key, value)
23+
1624
def post_read(self, request):
17-
if request._started():
18-
log.debug('post_read end')
19-
return request._result()
25+
environ = {
26+
'REQUEST_METHOD': request.method_name,
27+
'SCRIPT_NAME': None,
28+
'PATH_INFO': request.uri,
29+
'QUERY_STRING': request.args,
30+
'CONTENT_TYPE': request.content_type,
31+
'CONTENT_LENGTH': request.content_length,
32+
'SERVER_NAME': 'localhost',
33+
'SERVER_PORT': '8080',
34+
'SERVER_PROTOCOL': request.http_protocol,
35+
'wsgi.input': io.BytesIO(),
36+
'wsgi.errors': sys.stderr,
37+
'wsgi.version': (1, 0),
38+
'wsgi.multithread': False,
39+
'wsgi.multiprocess': True,
40+
'wsgi.run_once': True,
41+
}
42+
if environ.get('HTTPS', 'off') in ('on', '1'):
43+
environ['wsgi.url_scheme'] = 'https'
2044
else:
21-
log.debug('post_read request:\n%s', request)
22-
return request._start(self.loop.create_task(
23-
self._post_read_async(request)))
45+
environ['wsgi.url_scheme'] = 'http'
46+
from myapp import app
47+
resp = app(environ, functools.partial(
48+
self.start_response, request))
49+
request.send_header()
50+
rv = 404
51+
for pos in resp:
52+
rv = request.send_response(pos)
53+
return rv
54+
# if request._started():
55+
# log.debug('post_read end')
56+
# return request._result()
57+
# else:
58+
# log.debug('post_read request:\n%s', request)
59+
# return request._start(self.loop.create_task(
60+
# self._post_read_async(request)))
2461

2562
async def _post_read_async(self, request):
2663
try:

nginx/nginx_core.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ cdef extern from "ngx_core.h":
4040

4141
void *ngx_calloc(size_t size, ngx_log_t *log)
4242
void ngx_free(void *p)
43+
void *ngx_memcpy(void *dst, const void *src, size_t n)
4344
void ngx_log_error(ngx_uint_t level,
4445
ngx_log_t *log,
4546
ngx_err_t err,

nginx/ngx_http.pxd

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,39 @@
1-
from .nginx_core cimport ngx_str_t, ngx_module_t, ngx_log_t
1+
from .nginx_core cimport ngx_str_t, ngx_module_t, ngx_log_t, ngx_uint_t, ngx_int_t
22

33

44
cdef extern from "ngx_http.h":
5+
6+
ctypedef struct ngx_table_elt_t:
7+
ngx_uint_t hash
8+
ngx_str_t key
9+
ngx_str_t value
10+
11+
ctypedef struct ngx_list_t:
12+
pass
13+
14+
ctypedef struct ngx_http_headers_in_t:
15+
ngx_table_elt_t *content_type
16+
ngx_table_elt_t *content_length
17+
18+
ctypedef struct ngx_http_headers_out_t:
19+
ngx_uint_t status
20+
ngx_table_elt_t *content_length
21+
ngx_list_t headers
22+
23+
ctypedef struct ngx_chain_t:
24+
ngx_buf_t *buf
25+
ngx_chain_t *next
26+
27+
ctypedef struct ngx_buf_t:
28+
unsigned last_buf
29+
unsigned last_in_chain
30+
unsigned memory
31+
char *pos
32+
char *last
33+
34+
ctypedef struct ngx_pool_t:
35+
pass
36+
537
ctypedef struct ngx_connection_t:
638
ngx_log_t *log
739

@@ -14,9 +46,24 @@ cdef extern from "ngx_http.h":
1446
ngx_str_t unparsed_uri
1547
ngx_str_t method_name
1648
ngx_str_t http_protocol
49+
ngx_pool_t *pool
50+
ngx_http_headers_in_t headers_in
51+
ngx_http_headers_out_t headers_out
1752

1853
void ngx_http_core_run_phases(ngx_http_request_t *request)
1954
void *ngx_http_get_module_ctx(ngx_http_request_t *request,
2055
ngx_module_t module)
2156
void ngx_http_set_ctx(ngx_http_request_t *request, void *ctx,
2257
ngx_module_t module)
58+
59+
void ngx_http_send_header(ngx_http_request_t *r)
60+
61+
ngx_table_elt_t *ngx_list_push(ngx_list_t *list)
62+
63+
void ngx_str_set(ngx_str_t *str, char *text)
64+
65+
ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *input)
66+
67+
ngx_buf_t *ngx_calloc_buf(ngx_pool_t *pool)
68+
69+

0 commit comments

Comments
 (0)