{"id":20839736,"url":"https://github.com/arut/nginx-python-module","last_synced_at":"2025-05-08T21:43:14.377Z","repository":{"id":49387043,"uuid":"79130946","full_name":"arut/nginx-python-module","owner":"arut","description":"Nginx Python Module","archived":false,"fork":false,"pushed_at":"2017-09-25T07:23:10.000Z","size":148,"stargazers_count":138,"open_issues_count":4,"forks_count":36,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-08T21:43:11.784Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arut.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-16T15:19:51.000Z","updated_at":"2024-10-28T09:31:51.000Z","dependencies_parsed_at":"2022-08-27T10:52:34.950Z","dependency_job_id":null,"html_url":"https://github.com/arut/nginx-python-module","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arut%2Fnginx-python-module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arut%2Fnginx-python-module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arut%2Fnginx-python-module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arut%2Fnginx-python-module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arut","download_url":"https://codeload.github.com/arut/nginx-python-module/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253153677,"owners_count":21862391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T01:14:19.677Z","updated_at":"2025-05-08T21:43:14.340Z","avatar_url":"https://github.com/arut.png","language":"C","funding_links":[],"categories":["Honourable mentions"],"sub_categories":[],"readme":"*******************\nNginx Python Module\n*******************\n\nThe module allows using Python in nginx both at configuration stage and in\nruntime.\n\n\nCompatibility\n=============\n\n- nginx version \u003e= 1.11.5 (HTTP-only version can be compiled with 1.11.2)\n- Python version: 2.7\n- tested on recent Linux, FreeBSD and MacOS\n\n\nBuild\n=====\n\nConfiguring nginx with the module::\n\n    # static module\n    $ ./configure --add-module=/path/to/nginx-python-module\n\n    # dynamic module\n    $ ./configure --add-dynamic-module=/path/to/nginx-python-module\n\n    # sync-only version (no blocking operations substitution)\n    $ ./configure --add-module=/path/to/nginx-python-module\n                  --with-cc-opt=-DNGX_PYTHON_SYNC=1\n\n    # a specific Python installation can be used by exporting\n    # the path to python-config prior to configuring\n    $ export PYTHON_CONFIG=/path/to/python-config\n\n\nTests\n=====\n\nLike in standard nginx tests, the following environment variables are supported\n\n- ``TEST_NGINX_BINARY`` - path to the nginx binary\n- ``TEST_NGINX_CATLOG`` - dump error.log to stderr\n- ``TEST_NGINX_LEAVE`` - do not remove test directory\n\nRunning tests::\n\n    # run all tests\n    $ python t\n    \n    # add verbosity with -v, get help with -h\n    $ python t -v\n\n    # run an individual test\n    $ python t/test_http_basic.py\n\n\nDirectives\n==========\n\n\nGlobal Scope\n------------\n\n- ``python`` - execute Python code in config time\n- ``python_include`` - include and execute Python code in config time\n- ``python_stack_size`` - set stack size for unblocked code, default is 32k\n\nHTTP Scope\n----------\n\n- ``python`` - execute Python code in config time\n- ``python_include`` - include and execute Python code in config time\n- ``python_set`` - create Python variable (one-line)\n- ``python_access`` - set up Python access handler (one-line, blocking ops)\n- ``python_log`` - set up Python log handler (one-line)\n- ``python_content`` - set up Python location content handler (one-line,\n  blocking ops)\n\nStream Scope\n------------\n\n- ``python`` - execute Python code in config time\n- ``python_include`` - include and execute Python code in config time\n- ``python_set`` - create Python variable (one-line)\n- ``python_access`` - set up Python access handler (one-line, blocking ops)\n- ``python_preread`` - set up Python access handler (one-line, blocking ops)\n- ``python_log`` - set up Python log handler (one-line)\n- ``python_content`` - set up Python server content handler (one-line,\n  blocking ops)\n\n\nObjects and namespaces\n======================\n\ndefault namespaces\n------------------\n\nIn HTTP default namespace the current HTTP request instance ``r`` is available.\n\n- ``hi{}`` - input headers (readonly)\n- ``ho{}`` - output headers (read-write)\n- ``var{}`` - nginx variables (readonly)\n- ``arg{}`` - nginx arguments (readonly)\n- ``ctx{}`` - request dictionary (read-write)\n- ``status`` - HTTP status (read-write)\n- ``log(msg, level)`` - write a message to nginx error log with given level\n- ``sendHeader()`` - send HTTP header to client\n- ``send(data, flags)`` - send a piece of output body, optional flags are\n  ``SEND_LAST`` and ``SEND_FLUSH``\n\nIn Stream default namespace the current Stream session instance ``s`` is\navailable.\n\n- ``buf`` - preread/UDP buffer (readonly)\n- ``sock`` - client socket, I/O is allowed only at content phase\n- ``var{}`` - nginx variables (readonly)\n- ``ctx{}`` - session dictionary (read-write)\n- ``log(msg, level)`` - write a message to nginx error log with given level\n\nngx namespace\n-------------\n\nIn this namespace, standard constants are available\n\nStandard nginx result codes\n\n- ``OK``\n- ``ERROR``\n- ``AGAIN``\n- ``BUSY``\n- ``DONE``\n- ``DECLINED``\n- ``ABORT``\n\nLog error levels\n\n- ``LOG_EMERG``\n- ``LOG_ALERT``\n- ``LOG_CRIT``\n- ``LOG_ERR``\n- ``LOG_WARN``\n- ``LOG_NOTICE``\n- ``LOG_INFO``\n- ``LOG_DEBUG``\n\nSend flags\n\n- ``SEND_FLUSH``\n- ``SEND_LAST``\n\n\nBlocking operations\n===================\n\nNginx is a non-blocking server.  Using blocking operations while serving client\nrequests, will significantly decrease its performance.  The nginx-python-module\nprovides unblocked substitutions for common blocking operations in Python, and\nmakes these changes transparent for user.  This means, you can use common\nblocking Python operations, while their implementations will rely on nginx\nnon-blocking core.  The list of classes and functions unblocked by the module:\n\n- ``socket.socket`` class.  Unconnected (UDP) sockets, as well as Python SSL\n  socket wrappers are not supported.\n- ``socket.gethostbyname()`` and other resolve functions.  The ``resolver``\n  directive in the current location is required for these functions.\n- ``time.sleep()`` function.\n\n\nDefault Python namespace\n========================\n\nFor each nginx configuration a new default Python namespace is created.  This\nnamespace is shared among all global, HTTP or Stream scopes in configuration\ntime, as well as HTTP requests and Stream sessions in runtime.  The namespace\ncan be initialized with the ``python`` and ``python_include`` directives, which\noperate at configuration time.\n\n\nExamples\n========\n\nRemote configuration\n--------------------\n\nLoading the essential part of nginx configuration file from a remote server::\n\n    # nginx.conf\n\n    python 'import urllib';\n    python 'urllib.URLopener().retrieve(\"http://127.0.0.1:8888/nginx.conf\", \"/tmp/nginx.conf\")';\n\n    include /tmp/nginx.conf;\n\nVariables\n---------\n::\n\n    # nginx.conf\n\n    events {}\n\n    http {\n        python \"import hashlib\";\n\n        # md5($arg_foo)\n        python_set $md5 \"hashlib.md5(r.arg['foo']).hexdigest()\";\n\n        server {\n            listen 8000;\n            location / {\n                return 200 $md5;\n            }\n        }\n    }\n\nPhase handlers\n--------------\n\nDynamic Python module is used in this example::\n\n    # nginx.conf\n\n    load_module modules/ngx_python_module.so;\n\n    events {}\n\n    http {\n        python_include inc.py;\n        python_access \"access(r)\";\n\n        server {\n            listen 8000;\n            location / {\n                python_content \"content(r)\";\n            }\n        }\n    }\n\n\n    # inc.py\n\n    import ngx\n    import time\n    import socket\n\n    def access(r):\n        r.log('access phase', ngx.LOG_INFO)\n        r.ctx['code'] = 221\n\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        s.connect(('127.0.0.1', 8001))\n        s.settimeout(2)\n        s.send('foo')\n        r.ho['X-Out'] = s.recv(10)\n\n    def content(r):\n        r.status = r.ctx['code']\n        r.sendHeader()\n        r.send('1234567890');\n        r.send('abcdefgefg', ngx.SEND_LAST)\n\nUDP socket\n----------\n::\n\n    # nginx.conf\n\n    events {}\n\n    http {\n        python_include inc.py;\n        python_access \"access(r)\";\n\n        server {\n            listen 8000;\n            location / {\n                root html;\n            }\n        }\n    }\n\n\n    # inc.py\n\n    import socket\n\n    # send each $request via UDP to 127.0.0.1:6000\n\n    ds = None\n\n    def access(r):\n        global ds\n\n        if ds is None:\n            ds = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n            ds.connect(('127.0.0.1', 6000))\n\n        ds.send(r.var['request'])\n\nHTTP request in runtime\n-----------------------\n::\n\n    # nginx.conf\n\n    events {}\n\n    http {\n        python_include inc.py;\n        python_access \"access(r)\";\n\n        server {\n            listen 8000;\n            location / {\n                root html;\n            }\n        }\n\n        server {\n            listen 8001;\n            location / {\n                return 200 foo;\n            }\n        }\n    }\n\n\n    # inc.py\n\n    import httplib\n\n    def access(r):\n        conn = httplib.HTTPConnection(\"127.0.0.1\", 8001)\n        conn.request('GET', '/')\n        resp = conn.getresponse()\n\n        r.ho['x-status'] = resp.status;\n        r.ho['x-reason'] = resp.reason;\n        r.ho['x-body'] = resp.read()\n\nEcho server\n-----------\n::\n\n    # nginx.conf\n\n    events {}\n\n    stream {\n        python_include inc.py;\n\n        server {\n            listen 8000;\n            python_content echo(s);\n        }\n    }\n\n\n    # inc.py\n\n    def echo(s):\n        while True:\n            b = s.sock.recv(128)\n            if len(b) == 0:\n                return\n            s.sock.sendall(b)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farut%2Fnginx-python-module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farut%2Fnginx-python-module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farut%2Fnginx-python-module/lists"}