{"id":20695095,"url":"https://github.com/ibm-cloud-architecture/tutorial-istio-envoy-lua-filters","last_synced_at":"2025-04-22T20:02:07.365Z","repository":{"id":50351747,"uuid":"192025055","full_name":"ibm-cloud-architecture/tutorial-istio-envoy-lua-filters","owner":"ibm-cloud-architecture","description":null,"archived":false,"fork":false,"pushed_at":"2023-12-03T06:38:12.000Z","size":61,"stargazers_count":73,"open_issues_count":1,"forks_count":24,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T18:22:06.603Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibm-cloud-architecture.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":"2019-06-15T01:51:56.000Z","updated_at":"2025-02-10T16:43:53.000Z","dependencies_parsed_at":"2022-08-31T08:01:59.649Z","dependency_job_id":null,"html_url":"https://github.com/ibm-cloud-architecture/tutorial-istio-envoy-lua-filters","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibm-cloud-architecture","download_url":"https://codeload.github.com/ibm-cloud-architecture/tutorial-istio-envoy-lua-filters/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250315982,"owners_count":21410473,"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-17T00:08:00.544Z","updated_at":"2025-04-22T20:02:07.306Z","avatar_url":"https://github.com/ibm-cloud-architecture.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"In this example, we show how a Lua filter can be used with the Envoy\nproxy. The Envoy proxy [configuration](./envoy.yaml) includes a lua\nfilter that contains two functions namely\n`envoy_on_request(request_handle)` and\n`envoy_on_response(response_handle)` as documented\n[here](https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/lua_filter).\n\n\n\n# Usage\n1. `docker-compose pull`\n2. `docker-compose up --build`\n3. `curl -v localhost:8000`\n\n## Sample Output:\n\nCurl output should include our headers:\n\n```\n# \u003cb\u003e curl -v localhost:8000\u003c/b\u003e\n* Rebuilt URL to: localhost:8000/\n*   Trying 127.0.0.1...\n* Connected to localhost (127.0.0.1) port 8000 (#0)\n\u003e GET / HTTP/1.1\n\u003e Host: localhost:8000\n\u003e User-Agent: curl/7.47.0\n\u003e Accept: */*\n\u003e\n\u003c HTTP/1.1 200 OK\n\u003c x-powered-by: Express\n\u003c content-type: application/json; charset=utf-8\n\u003c content-length: 544\n\u003c etag: W/\"220-PQ/ZOdrX2lwANTIy144XG4sc/sw\"\n\u003c date: Thu, 31 May 2018 15:29:56 GMT\n\u003c x-envoy-upstream-service-time: 2\n\u003c response-body-size: 544            \u003c-- This is added to the response header by our Lua script. --\u003c\n\u003c server: envoy\n\u003c\n```\n```json\n{\n  \"path\": \"/\",\n  \"headers\": {\n    \"host\": \"localhost:8000\",\n    \"user-agent\": \"curl/7.47.0\",\n    \"accept\": \"*/*\",\n    \"x-forwarded-proto\": \"http\",\n    \"x-request-id\": \"0adbf0d3-8dfd-452f-a80a-1d6aa2ab06e2\",\n    \"foo\": \"bar\",                    \u003c-- This is added to the request header by our Lua script. --\u003c\n    \"x-envoy-expected-rq-timeout-ms\": \"15000\",\n    \"content-length\": \"0\"\n  },\n  \"method\": \"GET\",\n  \"body\": \"\",\n  \"fresh\": false,\n  \"hostname\": \"localhost\",\n  \"ip\": \"::ffff:172.18.0.2\",\n  \"ips\": [],\n  \"protocol\": \"http\",\n  \"query\": {},\n  \"subdomains\": [],\n  \"xhr\": false,\n  \"os\": {\n    \"hostname\": \"5ad758105577\"\n  }\n```\n```\n* Connection #0 to host localhost left intact\n}\n```\n\n## Additional Examples\n\nTo run the examples change directory and run normal docker-compose up/down assuming you already pull and build\n\nRun the example 1:\n```bash\ncd example-1-query\ndocker-compose up\n```\n\n### Example 1: Query Param\n[example-1-query](./example-1-query)\n\nParse a query parameter and add the value as a header into the request\n\nSend the request `curl \"localhost:8000/api?locale=us\"`\n\nThe value `us` is included in the request header `locale` going out from the proxy to the web service\n```json\n{\n  \"path\": \"/api\",\n  \"headers\": {\n    \"host\": \"localhost:8000\",\n    \"user-agent\": \"curl/7.54.0\",\n    \"locale\": \"us\",\n  },\n  \"method\": \"GET\",\n  \"body\": \"\",\n  \"protocol\": \"http\",\n  \"query\": {\n    \"locale\": \"us\"\n  },\n}\n```\n\n### Example 2: Load external lua library\n[example-2-lib](./example-2-lib)\n\nLoads the library [./example-2-lib/uuid.lua](./example-2-lib/uuid.lua)\n\nAdds a header with a random uuid if the header is not already present in the request\n\nSend the request\n```bash\ncurl \"localhost:8000/api/v1\"\n```\n\nThe random uuid is included in the request header `correlationid` going out from the proxy to the web service\n```json\n{\n  \"path\": \"/api\",\n  \"headers\": {\n    \"host\": \"localhost:8000\",\n    \"user-agent\": \"curl/7.54.0\",\n    \"correlationid\": \"GEN-cbb297c0-14a9-46bc-c691-1d0ef9b42df9\"\n  },\n  \"method\": \"GET\",\n  \"body\": \"\",\n  \"protocol\": \"http\"\n}\n```\n\n### Example 3: Parse body JSON\n[example-3-json](./example-3-json)\n\nLoads the library [./example-3-json/JSON.lua](./example-3-json/JSON.lua)\n\nAdds a header using the value from the body if the header is not already present in the request.\n\nSend the request POST with an `application/json` body:\n```bash\ncurl -d '{\"correlationid\":\"GEN-00000000-1111-2222-3333-444444444444\"}' \\\n-H \"Content-Type:application/json\" \\\nhttp://localhost:8000\n```\n\nThe value from the body field `correlationid` is included in the request header `correlationid` going out from the proxy to the web service\n```json\n{\n  \"path\": \"/\",\n  \"headers\": {\n    \"host\": \"localhost:8000\",\n    \"user-agent\": \"curl/7.54.0\",\n    \"accept\": \"*/*\",\n    \"content-type\": \"application/json\",\n    \"content-length\": \"60\",\n    \"correlationid\": \"GEN-00000000-1111-2222-3333-444444444444\"\n  },\n  \"method\": \"POST\",\n  \"body\": \"{\\\"correlationid\\\":\\\"GEN-00000000-1111-2222-3333-444444444444\\\"}\",\n  \"protocol\": \"http\",\n}\n```\n\n### Example 4: Full Example\n[example-4-full](./example-4-full)\n\nFull complex example parsing headers, query, body, and generating uuid\n\nLoads the libraries:\n- [./example-2-lib/uuid.lua](./example-2-lib/uuid.lua)\n- [./example-3-json/JSON.lua](./example-3-json/JSON.lua)\n\n\nDetects if any of the headers (`locale`,`brand`,`systemid`,`correlationid`) are missing, tries to add the header with the value from query parameter or body json.\n\nIf correlationid is not present at all then a new value is generated using a random uuid.\n\nSend the request POST with an `application/json` body:\n```bash\ncurl -d '{\"systemid\":\"FFEE\"}' \\\n-H \"Content-Type:application/json\" \\\n\"http://localhost:8000/api/v1?brand=acme\u0026locale=en-us\"\n```\n\nThe request will include all the missing headers going from the proxy to the web service.\n```json\n{\n\"locale\": \"en-us\",\n\"brand\": \"acme\",\n\"systemid\": \"FFEE\",\n\"correlationid\": \"GEN-cbb297c0-14a9-46bc-c691-1d0ef9b42df9\"\n}\n```\nFull request echo back from web service:\n```json\n{\n  \"path\": \"/api/v1\",\n  \"headers\": {\n    \"host\": \"localhost:8000\",\n    \"user-agent\": \"curl/7.54.0\",\n    \"accept\": \"*/*\",\n    \"content-type\": \"application/json\",\n    \"content-length\": \"19\",\n    \"locale\": \"en-us\",\n    \"brand\": \"acme\",\n    \"systemid\": \"FFEE\",\n    \"correlationid\": \"GEN-cbb297c0-14a9-46bc-c691-1d0ef9b42df9\",\n  },\n  \"method\": \"POST\",\n  \"body\": \"{\\\"systemid\\\":\\\"FFEE\\\"}\",\n  \"protocol\": \"http\",\n  \"query\": {\n    \"brand\": \"acme\",\n    \"locale\": \"en-us\"\n  },\n}\n```\n\n### Example 5: Kubernetes Example\n[example-5-kubernetes](./example-5-kubernetes)\n\nThis example shows how to store the lua files in a ConfigMap, then mounting in envoy container\n\nDeploy config-map, deployment, and services\n```bash\ncd example-5-kubernetes/\nkubectl apply -k .\n```\n\nOpen a port forward to reach the envoy provice service\n```bash\nkubectl port-forward service/envoy-service 8000:80\n```\n\nNow send a request similar as example 4:\n```bash\ncurl -d '{\"systemid\":\"FFEE\"}' \\\n-H \"Content-Type:application/json\" \\\n\"http://localhost:8000/api/v1?brand=acme\u0026locale=en-us\"\n```\n\n### Example 6: Istio Example\n[example-6-istio](./example-6-istio)\n\nThis example shows how to store the lua files in a ConfigMap, then mounting in envoy container\n\nDeploy config-map, deployment, and services\n```bash\ncd example-6-istio/\nkubectl apply -f .\n```\n\nUpdate the deployment `istio-ingressgateway` to add the lua files\n```\nkubectl edit deployment istio-ingressgateway -n istio-system\n```\nAdd the volumenMounts in the corresponding section in the container `proxy`\n```yaml\nvolumeMounts:\n- mountPath: /var/lib/lua\n  name: config-volume-lua\n```\nAdd the volume in the corresponding section in the container `proxy`\n```yaml\nvolumes:\n- name: config-volume-lua\n  configMap:\n    name: lua-libs\n    items:\n    - key: JSON.lua\n      path: JSON.lua\n    - key: uuid.lua\n      path: uuid.lua\n```\n\nOpen a port forward to reach the `istio-ingressgateway`\n```bash\nkubectl port-forward service/istio-ingressgateway 8000:80 -n istio-system\n```\n\nNow send a request similar as example 4:\n```bash\ncurl -v -d '{\"systemid\":\"FFEE\"}' \\\n-H \"Content-Type:application/json\" \\\n\"http://localhost:8000/api/v1?brand=acme\u0026locale=en-us\"\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-cloud-architecture%2Ftutorial-istio-envoy-lua-filters/lists"}