Skip to content

Commit a357b62

Browse files
committed
Working version.
1 parent e9ad8a0 commit a357b62

27 files changed

+8630
-703
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2016, Roman Arutyunyan
1+
Copyright (C) 2016-2017 Roman Arutyunyan
22
All rights reserved.
33

44
Redistribution and use in source and binary forms, with or without

README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.rst

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
*******************
2+
Nginx Python Module
3+
*******************
4+
5+
6+
Compatibility
7+
=============
8+
9+
- python version supported: 2.7
10+
- tested on recent Linux, FreeBSD and MacOS
11+
12+
13+
Build
14+
=====
15+
16+
Things to do after downloading nginx::
17+
18+
# static module
19+
> ./configure --add-module=/path/to/nginx-python-module
20+
21+
# dynamic module
22+
> ./configure --add-dynamic-module=/path/to/nginx-python-module
23+
24+
# sync-only version (no blocking operation substitution)
25+
> ./configure --add-module=/path/to/nginx-python-module
26+
--with-cc-opt=-DNGX_PYTHON_SYNC=1
27+
28+
# a specific Python installation can be used
29+
# by exporting the path to python-config
30+
> export PYTHON_CONFIG=/path/to/python-config
31+
32+
33+
Tests
34+
=====
35+
36+
Like in standard nginx tests, the following environment variables are supported
37+
38+
- ``TEST_NGINX_BINARY`` - path to the nginx binary
39+
- ``TEST_NGINX_CATLOG`` - dump error.log to stderr
40+
- ``TEST_NGINX_LEAVE`` - do not remove test directory
41+
42+
Running tests::
43+
44+
# run all tests
45+
> python t
46+
47+
# add verbosity with -v, get help with -h
48+
> python t -v
49+
50+
# run an individual test
51+
> python t/test_http_basic.py
52+
53+
54+
Directives
55+
==========
56+
57+
HTTP
58+
----
59+
60+
- ``python`` - execute Python code in config time
61+
- ``python_include`` - include and execute Python code in config time
62+
- ``python_stack_size`` - set stack size for unblocked code, default is 32k
63+
- ``python_set`` - create Python variable (one-line)
64+
- ``python_access`` - set up Python access handler (one-line, blocking ops)
65+
- ``python_log`` - set up Python log handler (one-line)
66+
- ``python_content`` - set up Python location content handler (one-line,
67+
blocking ops)
68+
69+
Stream
70+
------
71+
72+
- ``python`` - execute Python code in config time
73+
- ``python_include`` - include and execute Python code in config time
74+
- ``python_stack_size`` - set stack size for unblocked code, default is 32k
75+
- ``python_set`` - create Python variable (one-line)
76+
- ``python_access`` - set up Python access handler (one-line, blocking ops)
77+
- ``python_preread`` - set up Python access handler (one-line, blocking ops)
78+
- ``python_log`` - set up Python log handler (one-line)
79+
- ``python_content`` - set up Python server content handler (one-line,
80+
blocking ops)
81+
82+
83+
Objects and namespaces
84+
======================
85+
86+
default namespaces
87+
------------------
88+
89+
In HTTP default namespace the current HTTP request instance ``r`` is available.
90+
91+
- ``hi{}`` - input headers (readonly)
92+
- ``ho{}`` - output headers (read-write)
93+
- ``var{}`` - nginx variables (readonly)
94+
- ``arg{}`` - nginx arguments (readonly)
95+
- ``ctx{}`` - request dictionary (read-write)
96+
- ``status`` - HTTP status (read-write)
97+
- ``log(msg, level)`` - write a message to nginx error log with given level
98+
- ``sendHeader()`` - send HTTP header to client
99+
- ``send(data, flags)`` - send a piece of output body, optional flags are
100+
``SEND_LAST`` and ``SEND_FLUSH``
101+
102+
In Stream default namespace the current Stream session instance ``s`` is
103+
available.
104+
105+
- ``buf`` - preread/UDP buffer (readonly)
106+
- ``sock`` - client socket, I/O is allowed only at content phase
107+
- ``var{}`` - nginx variables (readonly)
108+
- ``ctx{}`` - session dictionary (read-write)
109+
- ``log(msg, level)`` - write a message to nginx error log with given level
110+
111+
ngx namespace
112+
-------------
113+
114+
In this namespace, standard constants are available
115+
116+
Standard nginx result codes
117+
118+
- ``OK``
119+
- ``ERROR``
120+
- ``AGAIN``
121+
- ``BUSY``
122+
- ``DONE``
123+
- ``DECLINED``
124+
- ``ABORT``
125+
126+
Log error levels
127+
128+
- ``LOG_EMERG``
129+
- ``LOG_ALERT``
130+
- ``LOG_CRIT``
131+
- ``LOG_ERR``
132+
- ``LOG_WARN``
133+
- ``LOG_NOTICE``
134+
- ``LOG_INFO``
135+
- ``LOG_DEBUG``
136+
137+
Send flags
138+
139+
- ``SEND_FLUSH``
140+
- ``SEND_LAST``
141+
142+
143+
Blocking operations
144+
===================
145+
146+
Nginx is a non-blocking server. Using blocking operations, while serving a
147+
request, will significantly decrease its performance. The nginx-python-module
148+
provides substitutions for common blocking operations in Python, making those
149+
changes transparent for user. That means, you can use common blocking Python
150+
operations, while their implementations will rely on Nginx non-blocking core.
151+
The list of classes and functions, unblocked by the module:
152+
153+
- ``time.sleep()`` function
154+
- ``socket.socket`` class
155+
- unconnected (UDP) sockets are not supported
156+
- standard Python SSL socket wrappers are not supported
157+
- ``socket.gethostbyname()`` and other resolve functions
158+
- nginx ``resolver`` directive in current location is required for these
159+
functions
160+
161+
162+
Examples
163+
========
164+
165+
Example #1::
166+
167+
# nginx.conf
168+
169+
events {
170+
}
171+
172+
http {
173+
python "import hashlib";
174+
175+
# md5($arg_foo)
176+
python_set $md5 "hashlib.md5(r.arg['foo']).hexdigest()";
177+
178+
server {
179+
listen 8000;
180+
location / {
181+
return 200 $md5;
182+
}
183+
}
184+
}
185+
186+
Example #2::
187+
188+
# nginx.conf
189+
190+
events {
191+
}
192+
193+
http {
194+
python_include inc.py;
195+
python_access "access(r)";
196+
197+
server {
198+
listen 8000;
199+
location / {
200+
python_content "content(r)";
201+
}
202+
}
203+
}
204+
205+
206+
# inc.py
207+
208+
import ngx
209+
import time
210+
import socket
211+
212+
def access(r):
213+
r.log('access phase', ngx.LOG_INFO)
214+
r.ctx['code'] = 221
215+
216+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
217+
s.connect(('127.0.0.1', 8001))
218+
s.settimeout(2)
219+
s.send('foo')
220+
r.ho['X-Out'] = s.recv(10)
221+
222+
def content(r):
223+
r.status = r.ctx['code']
224+
r.sendHeader()
225+
r.send('1234567890');
226+
r.send('abcdefgefg', ngx.SEND_LAST)
227+
228+
Example #3::
229+
230+
# nginx.conf
231+
232+
events {
233+
}
234+
235+
http {
236+
python_include inc.py;
237+
python_access "access(r)";
238+
239+
server {
240+
listen 8000;
241+
location / {
242+
root html;
243+
}
244+
}
245+
}
246+
247+
248+
# inc.py
249+
250+
import socket
251+
252+
# send each $request via UDP to 127.0.0.1:6000
253+
254+
ds = None
255+
256+
def access(r):
257+
global ds
258+
259+
if ds is None:
260+
ds = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
261+
ds.connect(('127.0.0.1', 6000))
262+
263+
ds.send(r.var['request'])
264+
265+
Example #4::
266+
267+
# nginx.conf
268+
269+
events {
270+
}
271+
272+
http {
273+
python_include inc.py;
274+
python_access "access(r)";
275+
276+
server {
277+
listen 8000;
278+
location / {
279+
root html;
280+
}
281+
}
282+
283+
server {
284+
listen 8001;
285+
location / {
286+
return 200 foo;
287+
}
288+
}
289+
}
290+
291+
292+
# inc.py
293+
294+
import httplib
295+
296+
def access(r):
297+
conn = httplib.HTTPConnection("127.0.0.1", 8001)
298+
conn.request('GET', '/')
299+
resp = conn.getresponse()
300+
301+
r.ho['x-status'] = resp.status;
302+
r.ho['x-reason'] = resp.reason;
303+
r.ho['x-body'] = resp.read()
304+
305+
Example #5::
306+
307+
# nginx.conf
308+
309+
events {
310+
}
311+
312+
stream {
313+
python_include inc.py;
314+
315+
server {
316+
listen 8000;
317+
python_content echo(s);
318+
}
319+
}
320+
321+
322+
# inc.py
323+
324+
def echo(s):
325+
while True:
326+
b = s.sock.recv(128)
327+
if len(b) == 0:
328+
return
329+
s.sock.sendall(b)

TODO

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- dynamic compile warning when compiling with stream

0 commit comments

Comments
 (0)