{"id":13697105,"url":"https://github.com/tarantool/nginx_upstream_module","last_synced_at":"2025-10-11T07:33:57.203Z","repository":{"id":30493110,"uuid":"34047258","full_name":"tarantool/nginx_upstream_module","owner":"tarantool","description":"Tarantool NginX upstream module (REST, JSON API, websockets, load balancing)","archived":false,"fork":false,"pushed_at":"2021-03-02T19:22:36.000Z","size":2179,"stargazers_count":173,"open_issues_count":29,"forks_count":19,"subscribers_count":55,"default_branch":"master","last_synced_at":"2025-10-11T07:33:56.688Z","etag":null,"topics":["json-api","json-rpc","nginx","nginx-lua","rest-api","tarantool","tarantool-stored-procedures","upstream"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tarantool.png","metadata":{"files":{"readme":"README.md","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":"2015-04-16T09:40:46.000Z","updated_at":"2025-07-24T07:21:05.000Z","dependencies_parsed_at":"2022-08-17T18:10:15.219Z","dependency_job_id":null,"html_url":"https://github.com/tarantool/nginx_upstream_module","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/tarantool/nginx_upstream_module","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fnginx_upstream_module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fnginx_upstream_module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fnginx_upstream_module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fnginx_upstream_module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tarantool","download_url":"https://codeload.github.com/tarantool/nginx_upstream_module/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tarantool%2Fnginx_upstream_module/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279006622,"owners_count":26084131,"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","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["json-api","json-rpc","nginx","nginx-lua","rest-api","tarantool","tarantool-stored-procedures","upstream"],"created_at":"2024-08-02T18:00:52.678Z","updated_at":"2025-10-11T07:33:57.187Z","avatar_url":"https://github.com/tarantool.png","language":"C","readme":"\u003ca href=\"http://tarantool.org\"\u003e\r\n\t\u003cimg src=\"https://avatars2.githubusercontent.com/u/2344919?v=2\u0026s=250\" align=\"right\"\u003e\r\n\u003c/a\u003e\r\n\r\n# Tarantool NginX upstream module\r\n---------------------------------\r\nKey features:\r\n* Both nginx and Tarantool features accessible over HTTP(S).\r\n* Tarantool methods callable via JSON-RPC or REST.\r\n* Load balancing with elastic configuration.\r\n* Backup and fault tolerance.\r\n* Low overhead.\r\n\r\nSee more about:\r\n* [Tarantool](http://tarantool.org)\r\n* [nginx upstream](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream)\r\n\r\n# Limitations\r\n-------------\r\n1. WebSockets are not supported until Tarantool supports out-of-band replies.\r\n2. This module does not support Tarantool 1.6.x starting with 2.4.0.\r\n   Since then it uses Tarantool 1.7 protocol features.\r\n\r\n## Docker images\r\n----------------\r\nTarantool NginX upstream module:\r\nhttps://hub.docker.com/r/tarantool/tarantool-nginx\r\n\r\nTarantool:\r\nhttps://hub.docker.com/r/tarantool/tarantool\r\n\r\n## Status\r\n---------\r\n* v0.1.4 - Production ready.\r\n* v0.2.0 - Stable.\r\n* v0.2.1 - Production ready.\r\n* v0.2.2 - Stable.\r\n* v2.3.1 - Production ready.\r\n* v2.3.2 - production ready.\r\n* v2.3.7 - Production ready.\r\n* v2.4.0-beta - Beta.\r\n* v2.4.6-rc1 - Stable.\r\n* v2.5-rc{1,2} - Stable.\r\n* v2.5-stable - Stable.\r\n* v2.6-rc3 - Stable.\r\n\r\n## Contents\r\n-----------\r\n* [How to install](#how-to-install)\r\n  * [Build from source](#build-from-source)\r\n  * [Build via nginx 'configure'](#build-via-nginx-configure)\r\n  * [Install on Mac OS X](#install-on-mac-os-x)\r\n  * [Configure](#configure)\r\n* [Test run and notes for contributors](#test-run-and-notes-for-contributors)\r\n* [REST](#rest)\r\n* [JSON](#json)\r\n* [HTTP headers and status](#http-headers-and-status)\r\n* [Directives](#directives)\r\n  * [tnt_pass](#tnt_pass)\r\n  * [tnt_http_methods](#tnt_http_methods)\r\n  * [tnt_http_rest_methods](#tnt_http_rest_methods)\r\n  * [tnt_pass_http_request](#tnt_pass_http_request)\r\n  * [tnt_pass_http_request_buffer_size](#tnt_pass_http_request_buffer_size)\r\n  * [tnt_method](#tnt_method)\r\n  * [tnt_set_header](#tnt_set_header)\r\n  * [tnt_send_timeout](#tnt_send_timeout)\r\n  * [tnt_read_timeout](#tnt_read_timeout)\r\n  * [tnt_buffer_size](#tnt_buffer_size)\r\n  * [tnt_next_upstream](#tnt_next_upstream)\r\n  * [tnt_connect_timeout](#tnt_connect_timeout)\r\n  * [tnt_next_upstream](#tnt_next_upstream)\r\n  * [tnt_next_upstream_tries](#tnt_next_upstream_tries)\r\n  * [tnt_next_upstream_timeout](#tnt_next_upstream_timeout)\r\n  * [tnt_pure_result](#tnt_pure_result)\r\n  * [tnt_multireturn_skip_count](#tnt_multireturn_skip_count)\r\n  * [Format](#format)\r\n  * [tnt_insert](#tnt_insert)\r\n  * [tnt_replace](#tnt_replace)\r\n  * [tnt_delete](#tnt_delete)\r\n  * [tnt_select](#tnt_select)\r\n  * [tnt_select_limit_max](#tnt_select_limit_max)\r\n  * [tnt_allowed_spaces](#tnt_allowed_spaces)\r\n  * [tnt_allowed_indexes](#tnt_allowed_indexes)\r\n  * [tnt_update](#tnt_update)\r\n  * [tnt_upsert](#tnt_upsert)\r\n* [Performance tuning](#performance-tuning)\r\n* [Examples](#examples)\r\n* [Copyright \u0026 license](#copyright--license)\r\n* [See also](#see-also)\r\n* [Contacts](#contacts)\r\n\r\n## How to install\r\n-----------------\r\n\r\n### Build from source\r\n\r\n```bash\r\ngit clone https://github.com/tarantool/nginx_upstream_module.git nginx_upstream_module\r\ncd nginx_upstream_module\r\ngit submodule update --init --recursive\r\ngit clone https://github.com/nginx/nginx.git nginx\r\n\r\n# Ubuntu\r\napt-get install libpcre++0 gcc unzip libpcre3-dev zlib1g-dev libssl-dev libxslt-dev\r\n\r\nmake build-all\r\n```\r\n\r\n### Build via nginx 'configure'\r\n\r\n  Requirements (for details, see REPO_ROOT/Makefile)\r\n\r\n    libyajl \u003e= 2.0(https://lloyd.github.io/yajl/)\r\n    libmsgpuck \u003e= 2.0 (https://github.com/rtsisyk/msgpuck)\r\n\r\n    $ ./configure --add-module=REPO_ROOT \u0026\u0026 make\r\n\r\n### Install on Mac OS X\r\n\r\n```bash\r\nbrew tap denji/nginx\r\nbrew install nginx-full --with-tarantool-module\r\n```\r\n\r\n### Configure\r\n\r\n```nginx\r\n    ## Typical configuration, for more see http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream\r\n    upstream backend {\r\n        server 127.0.0.1:9999 max_fails=1 fail_timeout=30s;\r\n        server 127.0.0.1:10000;\r\n\r\n        # ...\r\n        server 127.0.0.1:10001 backup;\r\n\r\n        # ...\r\n    }\r\n\r\n    server {\r\n      location = /tnt {\r\n        tnt_pass backend;\r\n      }\r\n    }\r\n\r\n```\r\n\r\n\r\n[Back to contents](#contents)\r\n\r\n## Test run and notes for contributors\r\n\r\nThis paragraph is actual only if you choose [build from source](#build-from-source)\r\ninstallation. So that, nginx git repository should be placed into\r\n`nginx` directory within the module repository. But now, you should use\r\n`make configure-for-testing`. It points the path to the necessary for testing\r\nconfigs, so it is needed to run tests.\r\n\r\nTo run all tests with different nginx versions use `./test/auto.sh`. It\r\nwill checkout several nginx versions, rebuild nginx with the module and\r\nrun tests on each of those nginx versions.\r\n\r\nFor selective running, start:\r\n  1) nginx in other terminal with `./nginx/objs/nginx -c conf/nginx.conf`,\r\n  2) Tarantool in another terminal with `tarantool test/test.lua`,\r\n  3) run separate test file, e.g. `./test/basic_features.py`.\r\n\r\nIf you want to add new test, see examples: `*_features.py` files.\r\nDon't forget to include it to `test/run_all.sh`.\r\n\r\nYou can set `VERBOSE` environment variable to `True` to enable\r\ndebug info.\r\n\r\n[Back to contents](#contents)\r\n\r\n## REST\r\n-------\r\n\r\n**Note:** since v0.2.0\r\n\r\nWith this module, you can call Tarantool stored procedures via HTTP\r\nREST methods (GET, POST, PUT, PATCH, DELETE).\r\n\r\nExample:\r\n\r\n```nginx\r\n    upstream backend {\r\n      # Tarantool hosts\r\n      server 127.0.0.1:9999;\r\n    }\r\n\r\n    server {\r\n      # HTTP [GET | POST | PUT | PATCH | DELETE] /tnt_rest?q=1\u0026q=2\u0026q=3\r\n      location /tnt_rest {\r\n        # REST mode on\r\n        tnt_http_rest_methods get post put patch delete; # or all\r\n\r\n        # Pass http headers and uri\r\n        tnt_pass_http_request on;\r\n\r\n        # Module on\r\n        tnt_pass backend;\r\n      }\r\n    }\r\n```\r\n\r\n```lua\r\n-- Tarantool procedure\r\nfunction tnt_rest(req)\r\n req.headers -- http headers\r\n req.uri -- uri\r\n return { 'ok' }\r\nend\r\n```\r\n\r\n```bash\r\n $\u003e wget NGX_HOST/tnt_rest?arg1=1\u0026argN=N\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\n## JSON\r\n-------\r\n\r\n**Note:** since v0.1.4\r\n\r\nThe module expects JSON posted with HTTP POST, PUT (since v0.2.0),\r\nor PATCH (since v2.3.8) and carried in request body.\r\n\r\nServer HTTP statuses:\r\n\r\n* **OK** - response body contains a result or an error;\r\n  the error may appear only if something wrong happened within Tarantool,\r\n  for instance: 'method not found'.\r\n* **INTERNAL SERVER ERROR** - may appear in many cases,\r\n  most of them being 'out of memory' error.\r\n* **NOT ALLOWED** - in response to anything but a POST request.\r\n* **BAD REQUEST** - JSON parse error, empty request body, etc.\r\n* **BAD GATEWAY** - lost connection to Tarantool server(s).\r\n  Since both (i.e. json -\u003e tp and tp -\u003e json) parsers work\r\n  asynchronously, this error may appear if 'params' or 'method'\r\n  does not exists in the structure of the incoming JSON, please\r\n  see the protocol description for more details.\r\n\r\n  **Note:** this behavior will change in the future.\r\n\r\n### Input JSON form\r\n\r\n```\r\n[ { \"method\": STR, \"params\":[arg0 ... argN], \"id\": UINT }, ...N ]\r\n```\r\n\r\n* **method** - a string containing the name of the Tarantool method to be\r\n  invoked (i.e. Tarantool \"call\")\r\n* **params** - a structured array. Each element is an argument of the Tarantool\r\n  \"call\".\r\n* **id** - an identifier established by the Client. MUST contain an unsigned\r\n  number not greater than unsigned int. May be 0.\r\n\r\nThese all are required fields.\r\n\r\n### Output JSON form\r\n\r\n```\r\n[ { \"result\": JSON_RESULT_OBJECT, \"id\":UINT, \"error\": { \"message\": STR, \"code\": INT } }, ...N ]\r\n```\r\n\r\n* **result** - Tarantool execution result (a json object/array, etc).\r\n  Version 2.4.0+ outputs a raw result, i.e. ``JSON_RESULT_OBJECT``.\r\n  May be null or undefined.\r\n* **id** - DEPRECATED in 2.4.0+ - request id.\r\n  May be null or undefined.\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\n### Example\r\n\r\nFor instance, Tarantool has a stored procedure `echo`:\r\n\r\n```Lua\r\nfunction echo(a, b, c, d)\r\n  return a, b, c, d\r\nend\r\n```\r\n\r\nSyntax:\r\n\r\n```\r\n--\u003e data sent to Server\r\n\u003c-- data sent to Client\r\n```\r\n\r\nrpc call 1:\r\n```\r\n--\u003e { \"method\": \"echo\", \"params\": [42, 23], \"id\": 1 }\r\n\u003c-- { \"id\": 1, \"result\": [42, 23]\r\n```\r\n\r\nrpc call 2:\r\n```\r\n--\u003e { \"method\": \"echo\", \"params\": [ [ {\"hello\": \"world\"} ], \"!\" ], \"id\": 2 }\r\n\u003c-- { \"id\": 2, \"result\": [ {\"hello\": \"world\"} ], \"!\" ]}\r\n```\r\n\r\nrpc call of a non-existent method:\r\n```\r\n--\u003e { \"method\": \"echo_2\", \"id\": 1 }\r\n\u003c-- { \"error\": {\"code\": -32601, \"message\": \"Method not found\"}, \"id\": 1 }\r\n```\r\n\r\nrpc call with invalid JSON:\r\n```\r\n--\u003e { \"method\": \"echo\", \"params\": [1, 2, 3, __wrong__ ] }\r\n\u003c-- { \"error\": { \"code\": -32700, \"message\": \"Parse error\" } }\r\n```\r\n\r\nrpc call Batch:\r\n```\r\n--\u003e [\r\n      { \"method\": \"echo\", \"params\": [42, 23], \"id\": 1 },\r\n      { \"method\": \"echo\", \"params\": [ [ {\"hello\": \"world\"} ], \"!\" ], \"id\": 2 }\r\n]\r\n\u003c-- [\r\n      { \"id\": 1, \"result\": [42, 23]},\r\n      { \"id\": 2, \"result\" : [{\"hello\": \"world\"} ], \"!\" ]},\r\n]\r\n```\r\n\r\nrpc call Batch of a non-existent method:\r\n```\r\n--\u003e [\r\n      { \"method\": \"echo_2\", \"params\": [42, 23], \"id\": 1 },\r\n      { \"method\": \"echo\", \"params\": [ [ {\"hello\": \"world\"} ], \"!\" ], \"id\": 2 }\r\n]\r\n\u003c-- [\r\n      { \"error\": {\"code\": -32601, \"message\": \"Method not found\"}, \"id\": 1 },\r\n      {\"id\": 2, \"result\": [ {\"hello\": \"world\"} ], \"!\" ]}\r\n]\r\n```\r\n\r\nrpc call Batch with invalid JSON:\r\n```\r\n--\u003e [\r\n      { \"method\": \"echo\", \"params\": [42, 23, __wrong__], \"id\": 1 },\r\n      { \"method\": \"echo\", \"params\": [ [ {\"hello\": \"world\"} ], \"!\" ], \"id\": 2 }\r\n]\r\n\u003c-- { \"error\": { \"code\": -32700, \"message\": \"Parse error\" } }\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\n## HTTP headers and status\r\n--------------------------\r\n\r\nSometimes you have to set status or headers which came from Tarantool.\r\nFor this purpose, you have to use something like\r\n[ngx_lua](https://github.com/openresty/lua-nginx-module)\r\nor [ngx_perl](http://nginx.org/en/docs/http/ngx_http_perl_module.html), etc.\r\n\r\nWith the methods, you can also transform the result from `Tarantool` into\r\nsomething else.\r\n\r\nHere is an example with `ngx_lua`:\r\n\r\n```Lua\r\n  -- Tarantool, stored procedure\r\n  function foo(req, ...)\r\n    local status = 200\r\n    local headers = {\r\n      [\"X-Tarantool\"] = \"FROM_TNT\",\r\n    }\r\n    local body = 'It works!'\r\n    return status, headers, body\r\n  end\r\n```\r\n\r\n```nginx\r\n  # Nginx, configuration\r\n\r\n  # If you're experience an problem with lua-resty-core like\r\n  # https://github.com/openresty/lua-nginx-module/issues/1509\r\n  # it can be disabled by the following directive.\r\n  #\r\n  # lua_load_resty_core off;\r\n\r\n  # If you're not using lua-resty-core you may need to manually specify a path\r\n  # to cjson module. See the documentation:\r\n  # https://github.com/openresty/lua-nginx-module#lua_package_cpath\r\n  #\r\n  # lua_package_cpath \"/path/in/lua/cpath/format/?.so\";\r\n\r\n  upstream tnt_upstream {\r\n     server 127.0.0.1:9999;\r\n     keepalive 10000;\r\n  }\r\n\r\n  location /tnt_proxy {\r\n    internal;\r\n    tnt_method foo;\r\n    tnt_buffer_size 100k;\r\n    tnt_pass_http_request on parse_args;\r\n    tnt_pass tnt_upstream;\r\n  }\r\n\r\n  location /api {\r\n    default_type application/json;\r\n    rewrite_by_lua '\r\n\r\n       local cjson = require(\"cjson\")\r\n\r\n       local map = {\r\n         GET = ngx.HTTP_GET,\r\n         POST = ngx.HTTP_POST,\r\n         PUT = ngx.HTTP_PUT,\r\n         -- ...\r\n       }\r\n       -- hide `{\"params\": [...]}` from a user\r\n       ngx.req.read_body()\r\n       local body = ngx.req.get_body_data()\r\n       if body then\r\n            body = \"{\\\\\"params\\\\\": [\" .. body .. \"]}\"\r\n       end\r\n       local res = ngx.location.capture(\"/tnt_proxy\", {\r\n         args = ngx.var.args,\r\n         method = map[ngx.var.request_method],\r\n         body = body\r\n       })\r\n\r\n       if res.status == ngx.HTTP_OK then\r\n         local answ = cjson.decode(res.body)\r\n\r\n         -- Read reply\r\n         local result = answ[\"result\"]\r\n\r\n         if result ~= nil then\r\n           ngx.status = result[1]\r\n           for k, v in pairs(result[2]) do\r\n             ngx.header[k] = v\r\n           end\r\n\r\n           local body = result[3]\r\n           if type(body) == \"string\" then\r\n             ngx.header[\"content_type\"] = \"text/plain\"\r\n             ngx.print(body)\r\n           elseif type(body) == \"table\" then\r\n             local body = cjson.encode(body)\r\n             ngx.say(body)\r\n           else\r\n             ngx.status = 502\r\n             ngx.say(\"Unexpected response from Tarantool\")\r\n           end\r\n         else\r\n           ngx.status = 502\r\n           ngx.say(\"Tarantool does not work\")\r\n         end\r\n\r\n         -- Finalize execution\r\n         ngx.exit(ngx.OK)\r\n       else\r\n         ngx.status = res.status\r\n         ngx.say(res.body)\r\n       end\r\n       ';\r\n    }\r\n\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\n## Directives\r\n-------------\r\n\r\ntnt_pass\r\n--------\r\n**syntax:** *tnt_pass UPSTREAM*\r\n\r\n**default:** *no*\r\n\r\n**context:** *location*\r\n\r\nSpecify the Tarantool server backend.\r\n\r\n```nginx\r\n\r\n  upstream tnt_upstream {\r\n     127.0.0.1:9999\r\n  };\r\n\r\n  location = /tnt {\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n\r\n  location = /tnt_next_location {\r\n     tnt_pass tnt_upstream;\r\n  }\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_http_methods\r\n----------------\r\n**syntax:** *tnt_http_methods post, put, patch, delete, all*\r\n\r\n**default:** *post, delete*\r\n\r\n**context:** *location*\r\n\r\nAllow to accept one or many http methods.\r\nIf a method is allowed, the module expects [JSON](#json) carried in the request\r\nbody.\r\nIf `tnt_method` is not set, then the name of the Tarantool stored procedure is\r\nthe protocol [JSON](#json).\r\n\r\nExample:\r\n\r\n```nginx\r\n  location tnt {\r\n    tnt_http_methods delete;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n\r\n```bash\r\n  # Call tarantool_stored_procedure_name()\r\n  $\u003e wget --method=delete --body-data='{\"method\":\"lua_function\", \"params\": [], \"id\": 0}' NGINX_HOST/tnt\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_http_rest_methods\r\n---------------------\r\n**syntax:** *tnt_http_rest_methods get, post, put, patch, delete, all*\r\n\r\n**default:** *no*\r\n\r\n**context:** *location*\r\n\r\n**NOTICE:**\r\nThis does not restrict anything. The option just says to NGINX:\r\nuse this methods for allowing REST requests.\r\n\r\nIf you have a wish to set some methods as not allowed methods, then\r\nplease use \"if\" inside locations.\r\n\r\nFor example:\r\n```nginx\r\nif ($request_method !~ ^(GET|POST|HEAD)$) {\r\n    return 405 \"Please use HEAD, PATCH and so on\";\r\n}\r\n```\r\n\r\nAllow to accept one or more REST methods.\r\nIf `tnt_method` is not set, then the name of the Tarantool stored procedure is\r\nthe first part of the URL path.\r\n\r\nExample:\r\n\r\n```nginx\r\n  location tnt {\r\n    tnt_http_rest_methods get;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n\r\n```bash\r\n  # Call tarantool_stored_procedure_name()\r\n  $\u003e wget NGINX_HOST/tarantool_stored_procedure_name/some/mega/path?q=1\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_pass_http_request\r\n---------------------\r\n**syntax:** *tnt_pass_http_request [on|off|parse_args|unescape|pass_body|pass_headers_out|parse_urlencoded|pass_subrequest_uri]*\r\n\r\n**default:** *off*\r\n\r\n**context:** *location, location if*\r\n\r\nAllow to pass HTTP headers and queries to Tarantool stored procedures.\r\n\r\nExamples #1:\r\n\r\n```nginx\r\n  location tnt {\r\n    # Also, tnt_pass_http_request can be used together with JSON communication\r\n    tnt_http_rest_methods get;\r\n\r\n    # [on|of]\r\n    tnt_pass_http_request on;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n```lua\r\n  function tarantool_stored_procedure_name(req, ...)\r\n    req.headers -- lua table\r\n    req.query -- string\r\n    return { 'OK' }\r\n  end\r\n\r\n  -- With parse_args\r\n  function tarantool_stored_procedure_name_1(req, ...)\r\n    req.headers -- lua table\r\n    req.query -- string\r\n    req.args -- query args as lua table\r\n    return { 'OK' }\r\n  end\r\n\r\n  -- With pass_body\r\n  function tarantool_stored_procedure_name_2(req, ...)\r\n    req.body -- request body, type string\r\n  end\r\n```\r\n\r\nExamples #2 (pass_headers_out):\r\n\r\n```nginx\r\n  location @tnt {\r\n    tnt_http_rest_methods get;\r\n    tnt_pass_http_request on pass_headers_out;\r\n    tnt_method tarantool_stored_procedure_name;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n\r\n  location / {\r\n    add_header \"X-Req-time\" \"$request_time\";\r\n    proxy_pass http://backend;\r\n    post_action @tnt;\r\n  }\r\n```\r\n```lua\r\n  function tarantool_stored_procedure_name(req, ...)\r\n    req.headers -- lua table\r\n    req.headers['X-Req-time'] -- set by add_header\r\n    req.query -- string\r\n    return true\r\n  end\r\n```\r\n\r\nExamples #3 (parse_urlencoded):\r\n\r\n```nginx\r\n  location /tnt {\r\n    tnt_http_rest_methods post;\r\n    tnt_pass_http_request on parse_urlencoded;\r\n    tnt_method tarantool_stored_procedure_name;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n```lua\r\n  function tarantool_stored_procedure_name(req, ...)\r\n    req.headers -- a lua table\r\n    req.query -- a string\r\n    req.args.q -- 1\r\n    req.args_urlencoded.p -- 2\r\n    return true\r\n  end\r\n```\r\n\r\n```bash\r\n  # Call tarantool_stored_procedure_name()\r\n  $\u003e wget NGINX_HOST/tarantool_stored_procedure_name/some/mega/path?q=1 --post-data='p=2'\r\n```\r\n\r\nExamples #4 (pass_subrequest_uri):\r\n\r\n* Origin (unparsed) uri\r\n```nginx\r\n  location /web {\r\n    # Backend processing /web/foo and replying with X-Accel-Redirect to\r\n    # internal /tnt/bar\r\n    proxy_pass http://x-accel-redirect-backend;\r\n  }\r\n  location /tnt {\r\n    internal;\r\n    tnt_pass_http_request on;\r\n    tnt_method tarantool_xar_handler;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n```lua\r\n  function tarantool_xar_handler(req, ...)\r\n    print(req.uri) -- /web/foo\r\n    return true\r\n  end\r\n```\r\n* Subrequest uri\r\n```nginx\r\n  location /web {\r\n    # Backend processing /web/foo and replying with X-Accel-Redirect to\r\n    # internal /tnt/bar\r\n    proxy_pass http://x-accel-redirect-backend;\r\n  }\r\n  location /tnt {\r\n    internal;\r\n    tnt_pass_http_request on pass_subrequest_uri;\r\n    tnt_method tarantool_xar_handler;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n```\r\n```lua\r\n  function tarantool_xar_handler(req, ...)\r\n    print(req.uri) -- /tnt/bar\r\n    return true\r\n  end\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_pass_http_request_buffer_size\r\n---------------------------------\r\n**syntax:** *tnt_pass_http_request_buffer_size SIZE*\r\n\r\n**default:** *4k, 8k*\r\n\r\n**context:** *location*\r\n\r\nSpecify the size of the buffer used for `tnt_pass_http_request`.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_method\r\n----------\r\n**syntax:** *tnt_method STR*\r\n\r\n**default:** *no*\r\n\r\n**context:** *location, location if*\r\n\r\nSpecify the Tarantool call method. It can take a nginx's variable.\r\n\r\nExamples:\r\n\r\n```nginx\r\n  location tnt {\r\n    # Also tnt_pass_http_request can mix with JSON communication [[\r\n    tnt_http_rest_methods get;\r\n    tnt_method tarantool_stored_procedure_name;\r\n    #]]\r\n\r\n    # [on|of]\r\n    tnt_pass_http_request on;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n\r\n  location ~ /api/([-_a-zA-Z0-9/]+)/ {\r\n    # Also tnt_pass_http_request can mix with JSON communication [[\r\n    tnt_http_rest_methods get;\r\n    tnt_method $1;\r\n    #]]\r\n\r\n    # [on|of]\r\n    tnt_pass_http_request on;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n\r\n```\r\n```lua\r\n  function tarantool_stored_procedure_name(req, ...)\r\n    req.headers -- lua table\r\n    req.query -- string\r\n    return { 'OK' }\r\n  end\r\n\r\n  function call(req, ...)\r\n    req.headers -- lua table\r\n    req.query -- string\r\n    return req, ...\r\n  end\r\n```\r\n```bash\r\n  # OK Call tarantool_stored_procedure_name()\r\n  $\u003e wget NGINX_HOST/tarantool_stored_procedure_name/some/mega/path?q=1\r\n\r\n  # Error Call tarantool_stored_procedure_XXX()\r\n  $\u003e wget NGINX_HOST/tarantool_stored_procedure_XXX/some/mega/path?q=1\r\n\r\n  # OK Call api_function\r\n  $\u003e wget NGINX_HOST/api/call/path?q=1\r\n\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_set_header\r\n--------------\r\n**syntax:** *tnt_set_header STR STR*\r\n\r\n**default:** *no*\r\n\r\n**context:** *location, location if*\r\n\r\nAllows redefining or appending fields to the request header passed to the\r\nTarantool proxied server.\r\nThe value can contain text, variables, and their combinations.\r\n\r\nExamples:\r\n\r\n```nginx\r\n  location tnt {\r\n    # Also tnt_pass_http_request can mix with JSON communication [[\r\n    tnt_http_rest_methods get;\r\n    tnt_method tarantool_stored_procedure_name;\r\n    #]]\r\n\r\n    tnt_set_header X-Host $host;\r\n    tnt_set_header X-GEO-COUNTRY $geoip_country_code;\r\n\r\n    # [on|of]\r\n    tnt_pass_http_request on;\r\n    tnt_pass 127.0.0.1:9999;\r\n  }\r\n\r\n```\r\n```lua\r\n  function tarantool_stored_procedure_name(req, ...)\r\n    req.headers['X-Host'] -- a hostname\r\n    req.headers['X-GEO-COUNTRY'] -- a geo country\r\n    return { 'OK' }\r\n  end\r\n```\r\n```bash\r\n  # OK Call tarantool_stored_procedure_name()\r\n  $\u003e wget NGINX_HOST/tarantool_stored_procedure_name/some/mega/path?q=1\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_send_timeout\r\n----------------\r\n**syntax:** *tnt_send_timeout TIME*\r\n\r\n**default:** *60s*\r\n\r\n**context:** *http, server, location*\r\n\r\nThe timeout for sending TCP requests to the Tarantool server, in seconds by\r\ndefault.\r\n\r\nIt's wise to always explicitly specify the time unit to avoid confusion.\r\nTime units supported are:\r\n`s`(seconds), `ms`(milliseconds), `y`(years), `M`(months), `w`(weeks),\r\n`d`(days), `h`(hours), and `m`(minutes).\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_read_timeout\r\n-------------------\r\n**syntax:** *tnt_read_timeout TIME*\r\n\r\n**default:** *60s*\r\n\r\n**context:** *http, server, location*\r\n\r\nThe timeout for reading TCP responses from the Tarantool server, in seconds by\r\ndefault.\r\n\r\nIt's wise to always explicitly specify the time unit to avoid confusion.\r\nTime units supported are: `s`(seconds), `ms`(milliseconds), `y`(years),\r\n`M`(months), `w`(weeks), `d`(days), `h`(hours), and `m`(minutes).\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_connect_timeout\r\n-------------------\r\n**syntax:** *tnt_connect_timeout TIME*\r\n\r\n**default:** *60s*\r\n\r\n**context:** *http, server, location*\r\n\r\nThe timeout for connecting to the Tarantool server, in seconds by default.\r\n\r\nIt's wise to always explicitly specify the time unit to avoid confusion.\r\nTime units supported are: `s`(seconds), `ms`(milliseconds), `y`(years),\r\n`M`(months), `w`(weeks), `d`(days), `h`(hours), and `m`(minutes).\r\nThis time must be strictly less than 597 hours.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_buffer_size\r\n---------------\r\n**syntax:** *tnt_buffer_size SIZE*\r\n\r\n**default:** *4k, 8k*\r\n\r\n**context:** *http, server, location*\r\n\r\nThis buffer size is used for reading Tarantool replies,\r\nbut it's not required to be as big as the largest possible Tarantool reply.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_next_upstream\r\n--------------------\r\n**syntax:** *tnt_next_upstream [ error | timeout | invalid_response | off ]*\r\n\r\n**default:** *error timeout*\r\n\r\n**context:** *http, server, location*\r\n\r\nSpecify which failure conditions should cause the request to be forwarded to\r\nanother upstream server. Applies only when the value in [tnt_pass](#tnt_pass)\r\nis an upstream with two or more servers.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_next_upstream_tries\r\n-----------------------\r\n**syntax:** *tnt_next_upstream_tries SIZE*\r\n\r\n**default:** *0*\r\n\r\n**context:** *http, server, location*\r\n\r\nLimit the number of possible tries for passing a request to the next server.\r\nThe 0 value turns off this limitation.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_next_upstream_timeout\r\n-------------------------\r\n**syntax:** *tnt_next_upstream_timeout TIME*\r\n\r\n**default:** *0*\r\n\r\n**context:** *http, server, location*\r\n\r\nLimit the time during which a request can be passed to the next server.\r\nThe 0 value turns off this limitation.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_pure_result\r\n---------------\r\n**syntax:** *tnt_pure_result [on|off]*\r\n\r\n**default:** *off*\r\n\r\n**context:** *http, server, location*\r\n\r\nWhether to wrap Tarantool response or not.\r\n\r\nWhen this option is off:\r\n```\r\n{\"id\":0, \"result\": [ 1 ]}\r\n```\r\nWhen this option is on:\r\n```\r\n[[1]]\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_multireturn_skip_count\r\n--------------------------\r\n\r\n**DEPRECATED in 2.4.0+, RETURNED IN 2.5.0-rc2+**\r\n\r\n**syntax:** *tnt_multireturn_skip_count [0|1|2]*\r\n\r\n**default:** *0*\r\n\r\n**context:** *http, server, location*\r\n\r\n**Note:** Use this option wisely, it does not validate the outgoing JSON!\r\nFor details you can check this issue:\r\nhttps://github.com/tarantool/nginx_upstream_module/issues/102\r\n\r\nThe module will skip one or more multireturn parts when this option is \u003e 0.\r\n\r\nWhen it is set to 0:\r\n\r\n```\r\n{\"id\":0, \"result\": [[1]]}\r\n```\r\n\r\nWhen it is set to 1:\r\n```\r\n{\"id\":0, \"result\": [1]}\r\n```\r\n\r\nWhen it is set to 2:\r\n```\r\n{\"id\": 0, \"result\": 1}\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\nFormat\r\n------\r\n\r\n**syntax:** *tnt_{OPT} [ARGS] [FMT]*\r\n\r\nTarantool stores data in [tuples](https://tarantool.org/en/doc/1.7/book/box/data_model.html#tuple).\r\nA tuple is a list of elements. Each element is a value or an object,\r\nand each element should have a strong type.\r\nThe tuple format is called [MsgPack](https://en.wikipedia.org/wiki/MessagePack),\r\nit's like JSON in a binary format.\r\n\r\nThe main goal of Format (see [FMT] above) is to enable conversion between\r\na query string and MsgPack without losing type information or value.\r\n\r\nThe syntax is: `{QUERY_ARG_NAME}=%{FMT_TYPE}`\r\n\r\nPlease look carefully for yours url encoding!\r\n\r\nA good example is (also see examples [tnt_update](#tnt_update) and [tnt_upsert](#tnt_upsert)):\r\n```\r\nHTTP GET ... /url?space_id=512\u0026value=some+string\r\nit could be matched by using the following format 'space_id=%%space_id,value=%s'\r\n```\r\nAlso this works with HTTP forms, i.e. HTTP POST, HTTP PUT and so on.\r\n\r\nHere is a full list of {FMT_TYPE} types:\r\n\r\n```\r\nTUPLES\r\n\r\n%n - int64\r\n%f - float\r\n%d - double\r\n%s - string\r\n%b - boolean\r\n\r\nSpecial types\r\n\r\n%%space_id - space_id\r\n%%idx_id - index_id\r\n%%off - [select](#tnt_select) offset\r\n%%lim - [select](#tnt_select) limit\r\n%%it - [select](#tnt_select) iterator type, allowed values are:\r\n                             eq,req,all,lt,le,ge,gt,all_set,any_set,\r\n                             all_non_set,overlaps,neighbor\r\n\r\nKEYS (for [tnt_update](#tnt_update))\r\n\r\n%kn - int64\r\n%kf - float\r\n%kd - double\r\n%ks - string\r\n%kb - boolean\r\n\r\nOperations (for [tnt_upsert](#tnt_upsert))\r\n\r\n%on - int64\r\n%of - float\r\n%od - double\r\n%os - string\r\n%ob - boolean\r\n\r\n```\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_insert\r\n----------\r\n**syntax:** *tnt_insert [SIZE or off] [FMT]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing an insert query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is a [format](#format) string.\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\nExamples can be found at:\r\n\r\n* `simple_rest_client.py`\r\n* `simple_rest_client.sh`\r\n\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_replace\r\n-----------\r\n**syntax:** *tnt_replace [SIZE or off] [FMT]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing a replace query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is a [format](#format) string.\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_delete\r\n----------\r\n**syntax:** *tnt_delete [SIZE or off] [SIZE or off] [FMT]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing a delete query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is an index id.\r\n* The third argument is a [format](#format) string.\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_select\r\n----------\r\n**syntax:** *tnt_select [SIZE or off] [SIZE or off] [SIZE] [SIZE] [ENUM] [FMT]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing a select query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is an index id.\r\n* The third argument is an offset.\r\n* The fourth argument is an limit.\r\n* The fifth argument is an iterator type, allowed values are:\r\n  `eq`, `req`, `all`, `lt` ,`le`,`ge`, `gt`, `all_set`, `any_set`,\r\n  `all_non_set`, `overlaps`, `neighbor`.\r\n* The six argument is a [format](#format) string.\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_select_limit_max\r\n--------------------\r\n**syntax:** *tnt_select_limit_max [SIZE]*\r\n\r\n**default:** *100*\r\n\r\n**context:** *server, location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis is a constraint to avoid *large selects*. This is the maximum number\r\nof returned tuples per select operation. If the client reaches this limit, then\r\nthe client gets an error on its side.\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_allowed_spaces\r\n------------------\r\n**syntax:** *tnt_allowed_spaces [STR]*\r\n\r\n**default:** **\r\n\r\n**context:** *server, location, location if*\r\n\r\nThis is a constraint to prohibit access to some spaces. The directive takes an\r\narray of Tarantool space id-s (numbers), and each space in the list is allowed\r\nto access from the client side.\r\n\r\nExample:\r\n\r\n```\r\nlocation {\r\n  ...\r\n  tnt_allowed_spaces 512,523;\r\n  tnt_insert off \"s=%%space_id,i=%%idx_id\";\r\n}\r\n```\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_allowed_indexes\r\n-------------------\r\n**syntax:** *tnt_allowed_indexes [STR]*\r\n\r\n**default:** **\r\n\r\n**context:** *server, location, location if*\r\n\r\nThis directive works like [tnt_allowed_spaces], but for indexes.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_update\r\n----------\r\n**syntax:** *tnt_update [SIZE or off] [KEYS] [FMT]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing an update query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is a [KEYS (for UPDATE)](#format) string.\r\nit has special request form: [OPERATION_TYPE],[FIELDNO],[VALUE]\r\n```\r\nPossible OPERATION_TYPE (char) are:\r\n + for addition (values must be numeric)\r\n - for subtraction (values must be numeric)\r\n \u0026 for bitwise AND (values must be unsigned numeric)\r\n | for bitwise OR (values must be unsigned numeric)\r\n ^ for bitwise XOR (values must be unsigned numeric)\r\n : for string splice\r\n ! for insertion\r\n # for deletion\r\n = for assignment\r\n\r\nFIELDNO (number) -  what field the operation will apply to. The field number can\r\nbe negative, meaning the position from the end of tuple. (#tuple + negative field number + 1)\r\n\r\nVALUE (int64, float, double, string, boolean) – what value will be applied\r\n\r\nMore details could be found here [tarantool.org] (https://tarantool.org/en/doc/1.7/book/box/box_space.html?highlight=update#lua-function.space_object.update)\r\n```\r\nBefore go further and start use this feature please read an example for this\r\nsection [1].\r\n\r\n* The third argument is a [format](#format) string.\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\n[Back to contents](#contents)\r\n\r\ntnt_upsert\r\n----------\r\n**syntax:** *tnt_upsert [SIZE or off] [FMT] [OPERATIONS]*\r\n\r\n**default:** *None*\r\n\r\n**context:** *location, location if*\r\n\r\n**HTTP methods** *GET, POST, PUT, PATCH, DELETE*\r\n\r\n**Content-Typer** *default, application/x-www-form-urlencoded*\r\n\r\nThis directive allows executing an upsert query with Tarantool.\r\n\r\n* The first argument is a space id.\r\n* The second argument is a [format](#format) string.\r\n* The third argument is a [OPERATIONS (for UPSERT)](#format) string.\r\nit has special request form: [OPERATION_TYPE],[FIELDNO],[VALUE]\r\n```\r\nPossible OPERATION_TYPE (char) are:\r\n + for addition (values must be numeric)\r\n - for subtraction (values must be numeric)\r\n \u0026 for bitwise AND (values must be unsigned numeric)\r\n | for bitwise OR (values must be unsigned numeric)\r\n ^ for bitwise XOR (values must be unsigned numeric)\r\n : for string splice\r\n ! for insertion\r\n # for deletion\r\n = for assignment\r\n\r\nFIELDNO (number) -  what field the operation will apply to. The field number can\r\nbe negative, meaning the position from the end of tuple. (#tuple + negative field number + 1)\r\n\r\nVALUE (int64, float, double, string, boolean) – what value will be applied\r\n\r\nMore details could be found here [tarantool.org] (https://tarantool.org/en/doc/1.7/book/box/box_space.html?highlight=update#box-space-upsert)\r\n```\r\n\r\nBefore go further and start use this feature please read an example for this\r\nsection [1].\r\n\r\n[1] Example\r\n\r\nExamples can be found at:\r\n\r\n* `examples/simple_rest_client.py`\r\n* `examples/simple_rest_client.sh`\r\n\r\nReturns HTTP code 4XX if client's request doesn't well formatted. It means, that\r\nthis error raised if some of values missed or has wrong type.\r\n\r\nReturns HTTP code 5XX if upstream is dead (no ping).\r\n\r\nAlso it can return an HTTP code 200 with an error formatted in JSON.\r\nIt happens when Tarantool can't issue a query.\r\n\r\nHere is a description:\r\n```\r\n {\"error\": { \"message\": STR, \"code\": INT } }\r\n```\r\n\r\n* **error** - a structured object which contains an internal error message.\r\n  This field exists only if an internal error occurred, for instance:\r\n  \"too large request\", \"input json parse error\", etc.\r\n\r\n  If this field exists, the input message was _probably_ not passed to\r\n  the Tarantool backend.\r\n\r\n  See \"message\"/\"code\" fields for details.\r\n\r\n\r\n[Back to contents](#contents)\r\n\r\n## Examples\r\n-----------\r\n\r\nPython test: `test/basic_features.py`, `test/v20_feautres.py`, `nginx.dev.conf`.\r\n\r\nClient-side javascript example: `example/echo.html`, `example/echo.lua`.\r\n\r\n[Back to contents](#contents)\r\n\r\n## Performance tuning\r\n---------------------\r\n\r\n* Use [HttpUpstreamKeepaliveModule](http://wiki.nginx.org/HttpUpstreamKeepaliveModule).\r\n  * Use [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive).\r\n  * Use [keepalive_requests](http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests).\r\n* Use multiple instances of Tarantool servers on your multi-core machines.\r\n* Turn off unnecessary logging in Tarantool and NginX.\r\n* Tune Linux network.\r\n* Tune nginx buffers.\r\n\r\n[Back to contents](#contents)\r\n\r\n## Copyright \u0026 license\r\n----------------------\r\n\r\n[LICENSE](https://github.com/tarantool/nginx_upstream_module/blob/master/LICENSE)\r\n\r\n[Back to contents](#contents)\r\n\r\n## See also\r\n-----------\r\n\r\n* [Tarantool](http://tarantool.org) homepage.\r\n* [lua-resty-tarantool](https://github.com/perusio/lua-resty-tarantool)\r\n* Tarantool [protocol](http://tarantool.org/doc/dev_guide/box-protocol.html?highlight=protocol)\r\n\r\n[Back to contents](#contents)\r\n\r\n## Contacts\r\n\r\nPlease report bugs at https://github.com/tarantool/nginx_upstream_module/issues.\r\n\r\nWe also warmly welcome your feedback in the discussion mailing list,\r\ntarantool@googlegroups.com\r\n\r\n[Back to contents](#contents)\r\n","funding_links":[],"categories":["Connectors","Tools"],"sub_categories":["Administration","Interface Description"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarantool%2Fnginx_upstream_module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftarantool%2Fnginx_upstream_module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarantool%2Fnginx_upstream_module/lists"}