{"id":15192558,"url":"https://github.com/kingluo/lua-resty-ffi-graphql-resolver","last_synced_at":"2026-03-05T06:31:11.659Z","repository":{"id":176211846,"uuid":"654880561","full_name":"kingluo/lua-resty-ffi-graphql-resolver","owner":"kingluo","description":"The openresty graphql server library that encapsulates ariadne.","archived":false,"fork":false,"pushed_at":"2023-06-21T08:57:03.000Z","size":42,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-01T00:04:20.935Z","etag":null,"topics":["graphql-server","grapqhl","kafka","luajit","luajit-ffi","nginx","openresty","python3","restful-api","sql","webservice"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kingluo.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,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-06-17T08:07:59.000Z","updated_at":"2023-06-21T10:42:55.000Z","dependencies_parsed_at":"2023-08-19T13:15:31.595Z","dependency_job_id":null,"html_url":"https://github.com/kingluo/lua-resty-ffi-graphql-resolver","commit_stats":{"total_commits":1,"total_committers":1,"mean_commits":1.0,"dds":0.0,"last_synced_commit":"273fcd75e8a617985b45f513759951f5340c9719"},"previous_names":["kingluo/lua-resty-ffi-graphql-resolver"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kingluo/lua-resty-ffi-graphql-resolver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingluo%2Flua-resty-ffi-graphql-resolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingluo%2Flua-resty-ffi-graphql-resolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingluo%2Flua-resty-ffi-graphql-resolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingluo%2Flua-resty-ffi-graphql-resolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kingluo","download_url":"https://codeload.github.com/kingluo/lua-resty-ffi-graphql-resolver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kingluo%2Flua-resty-ffi-graphql-resolver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30112220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T03:40:26.266Z","status":"ssl_error","status_checked_at":"2026-03-05T03:39:15.902Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["graphql-server","grapqhl","kafka","luajit","luajit-ffi","nginx","openresty","python3","restful-api","sql","webservice"],"created_at":"2024-09-27T21:42:08.204Z","updated_at":"2026-03-05T06:31:11.602Z","avatar_url":"https://github.com/kingluo.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lua-resty-ffi-graphql-resolver\n\nThe openresty graphql server library that encapsulates [ariadne](https://ariadnegraphql.org/).\n\n![GraphQL Resolver Architecture](graphql_resolver.jpg)\n\n**Callflow example:**\n\n![GraphQL Resolver Call Flow](graphql_resolver_flow.svg)\n\n**Highlights:**\n\n* supports multiple data sources\n  * [x] RESTful\n  * [ ] PostgreSQL\n  * [ ] Kafka\n  * [ ] WebService\n  * any other datasources to be implemented...\n* fully asynchronous\n* multiple schema instances\n* fully dynamic\n  * create and delete schema\n  * dynamic resolver mapping\n* [jq](https://jqlang.github.io/jq/) expression to transform response body\n* zero code\n\n## Background\n\nGraphQL is popular. Can we embed graphql server into openresty? In this way,\nwe can not only enjoy the benefits brought by nginx high-performance proxy,\nbut also request multiple different upstreams to generate the response content of graphql query\nwithout independent graphql server.\n\n[Ariadne](https://github.com/mirumee/ariadne) is a brilliant python graphql server, which is schema-first and has simple but powerful APIs.\n\nWhy not encapsulate it so that we could reuse it in openresty?\n\n[lua-resty-ffi](https://github.com/kingluo/lua-resty-ffi) provides an efficient and generic API to do hybrid programming\nin openresty with mainstream languages (Go, Python, Java, Rust, Nodejs).\n\n**lua-resty-ffi-graphql-resolver = lua-resty-ffi + ariadne**\n\n## Synopsis\n\n**Schema Config:**\n\n* schema: graphql schema text\n* datasources\n  * `\u003cname\u003e` (fields other than @type is datasource specifc configuration fields)\n    * @type: datasource type: http|sql|webservice|kafka\n    * host: host name, including scheme, for http type only.\n    * verify: verify ssl server name or not, optional, for http type only.\n* resolvers\n  * `\u003cGraphQL Type Name\u003e`\n    * `\u003ctype field name\u003e` (fields other than datasource is datasource specifc configuration fields)\n      * datasource: reference name\n      * uri: uri path, for http type only.\n      * headers: request headers, optional, for http type only.\n      * method: request method, optional, for http type only.\n      * send_json_body: send graphql params in json body, or in uri arguemnts, optional, for http type only.\n      * jq: jq expression to transform the response body for custom graphql output, optional, for http type only.\n\n```lua\nlocal schema, err = graphql_resolver.new({\n    schema = \"\u003cgraphql scehma text\u003e\",\n    datasources = {\n        nghttp2 = {\n            [\"@type\"] = \"http\",\n            host = \"https://nghttp2.org\",\n            verify = true\n        },\n    },\n    resolvers = {\n        Query = {\n            get = {\n                datasource = \"nghttp2\",\n                uri = \"/httpbin/get\",\n                headers = {\n                    foo = \"xxx\",\n                    bar = \"yyy\"\n                },\n                method = \"post\",\n                send_json_body = true,\n                jq = \"{url,agent:.headers.\\\"user-agent\\\"}\"\n            }\n        }\n    }\n})\n```\n\n**Query:**\n\n* query: graphql query, mutation or subscription\n* variables: variables used in the query, optional\n\n```lua\nlocal ok, res, err = schema:query({\n    query = \"\u003cgraphql query string\u003e\",\n    variables = {\n        foo = \"bar\"\n    }\n})\n```\n\n**Query Result:**\n\nReturns a tuple with two items:\n* bool: True when no errors occurred, False otherwise.\n* dict: an JSON-serializable dict with query result (defining either data, error, or both keys) that should be returned to client.\n\n```lua\n{ true, {\n    data = {\n      get = {\n        origin = \"192.168.1.1\",\n        uuid = \"9fe7a61f-8c61-4299-b4a6-666788954b70-suffix\"\n      }\n    }\n  } }\n```\n\n## Demo\n\n### Setup lua-resty-ffi-graphql-resolver\n\n```bash\n# install lua-resty-ffi\n# https://github.com/kingluo/lua-resty-ffi#install-lua-resty-ffi-via-luarocks\n# set `OR_SRC` to your openresty source path\nluarocks config variables.OR_SRC /tmp/tmp.Z2UhJbO1Si/openresty-1.21.4.1\nluarocks install lua-resty-ffi\n\n# make lua-resty-ffi python loader library\napt install python3-dev python3-pip libffi-dev\ncd /opt\ngit clone https://github.com/kingluo/lua-resty-ffi\ncd /opt/lua-resty-ffi/examples/python\nmake\n\n# install deps\ncd /opt\ngit clone https://github.com/kingluo/lua-resty-ffi-graphql-resolver\ncd /opt/lua-resty-ffi-graphql-resolver\npip3 install -r requirements.txt\n\n# run nginx\ncd /opt/lua-resty-ffi-graphql-resolver/demo\nPATH=/opt/resty_ffi/nginx/sbin/:$PATH \\\nLD_LIBRARY_PATH=/opt/lua-resty-ffi/examples/python:/usr/local/lib/lua/5.1 \\\nPYTHONPATH=/opt/lua-resty-ffi-graphql-resolver \\\nnginx -p $PWD -c nginx.conf\n```\n\n### Create schema\n\n```bash\ncurl http://localhost:20000/create_schema -X POST -d '\n{\n    \"schema\": \"type Get{origin:String!uuid:String}type Query{get:Get}type Post{url:String!agent:String!}type Mutation{post(data:String!):Post}\",\n    \"datasources\": {\n        \"nghttp2\": {\n            \"@type\": \"http\",\n            \"host\": \"https://nghttp2.org\",\n            \"verify\": true\n        },\n        \"postman\": {\n            \"@type\": \"http\",\n            \"host\": \"https://postman-echo.com\"\n        }\n    },\n    \"resolvers\": {\n        \"Query\": {\n            \"get\": {\n                \"datasource\": \"nghttp2\",\n                \"uri\": \"/httpbin/get\",\n                \"headers\": {\n                    \"foo\": \"xxx\",\n                    \"bar\": \"yyy\"\n                }\n            }\n        },\n        \"Get\": {\n            \"uuid\": {\n                \"datasource\": \"nghttp2\",\n                \"uri\": \"/httpbin/uuid\",\n                \"jq\": \".uuid + \\\"-suffix\\\"\"\n            }\n        },\n        \"Mutation\": {\n            \"post\": {\n                \"datasource\": \"postman\",\n                \"uri\": \"/post\",\n                \"method\": \"post\",\n                \"send_json_body\": true,\n                \"jq\": \"{url,agent:.headers.\\\"user-agent\\\"}\"\n            }\n        }\n    }\n}' -s | jq\n```\n\nouput:\n\n```json\n{\n  \"schema\": 1\n}\n```\n\n### Query\n\n```bash\ncurl http://localhost:20000/query?schema=1 -X POST -d '\n{\n    \"query\": \"query Test{get{origin uuid}}\"\n}' -s | jq\n```\n\noutput:\n\n```json\n[\n  true,\n  {\n    \"data\": {\n      \"get\": {\n        \"uuid\": \"95dbdfd0-1fcb-4428-8567-3ed0bea9aa7e-suffix\",\n        \"origin\": \"192.168.1.1\"\n      }\n    }\n  }\n]\n```\n\n### Mutation\n\n```bash\ncurl http://localhost:20000/query?schema=1 -X POST -d '\n{\n    \"query\": \"mutation Test($data:String!){post(data:$data){url agent}}\",\n    \"variables\": {\n        \"data\": \"foobar\"\n    }\n}' -s | jq\n```\n\noutput:\n\n```json\n[\n  true,\n  {\n    \"data\": {\n      \"post\": {\n        \"agent\": \"python-httpx/0.23.1\",\n        \"url\": \"https://postman-echo.com/post\"\n      }\n    }\n  }\n]\n```\n\n### Close schema\n\n```bash\ncurl http://localhost:20000/close_schema?schema=1\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkingluo%2Flua-resty-ffi-graphql-resolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkingluo%2Flua-resty-ffi-graphql-resolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkingluo%2Flua-resty-ffi-graphql-resolver/lists"}