├── .busted ├── .circleci └── config.yml ├── .codeclimate.yml ├── .codecov.yml ├── .dockerignore ├── .env ├── .gitattributes ├── .github ├── CODEOWNERS ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── workflows │ ├── fast-forward-branch.yaml │ ├── link_check.yaml │ └── tagRelease.yml ├── .gitignore ├── .gitmodules ├── .lgtm ├── .luacheckrc ├── .luacov ├── .mailmap ├── 3scale-gateway-openshift-template.yml ├── 3scale-portal-endpoint-secret.yml ├── Brewfile ├── CHANGELOG.md ├── Containerfile ├── Dangerfile ├── Dockerfile ├── Dockerfile.devel ├── LICENSE ├── MAINTAINERS ├── Makefile ├── NOTICE ├── README.md ├── Vagrantfile ├── benchmark ├── ips.lua ├── regexpify.lua └── template.lua ├── bin ├── apicast ├── busted └── busted.lua ├── config-5.1.lua ├── dependencies ├── container-entrypoint └── rpm-specs │ ├── gateway-rockspecs-native │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── gateway-rockspecs-native.spec │ ├── licenses.xml │ └── source_rocks │ │ ├── luafilesystem-1.8.0-1.src.rock │ │ └── lyaml-6.2.3-1.src.rock │ ├── gateway-rockspecs │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── gateway-rockspecs.spec │ ├── licenses.xml │ ├── rockspecs │ └── source_rocks │ │ ├── argparse-0.6.0-1.src.rock │ │ ├── date-2.2-2.src.rock │ │ ├── inspect-3.1.1-0.src.rock │ │ ├── jsonschema-0.8-0.src.rock │ │ ├── liquid-0.2.0-2.src.rock │ │ ├── lua-resty-env-0.4.0-1.src.rock │ │ ├── lua-resty-execvp-0.1.1-1.src.rock │ │ ├── lua-resty-http-0.17.1-0.src.rock │ │ ├── lua-resty-ipmatcher-0.6.1-0.src.rock │ │ ├── lua-resty-iputils-0.3.0-1.src.rock │ │ ├── lua-resty-jit-uuid-0.0.7-1.src.rock │ │ ├── lua-resty-jwt-0.2.3-1.src.rock │ │ ├── lua-resty-openssl-1.5.1-1.src.rock │ │ ├── lua-resty-url-0.3.5-1.src.rock │ │ ├── lua-rover-scm-1.src.rock │ │ ├── net-url-0.9-1.src.rock │ │ ├── nginx-lua-prometheus-0.20181120-2.src.rock │ │ ├── penlight-1.13.1-1.src.rock │ │ └── router-2.1-0.src.rock │ ├── luarocks │ ├── luarocks-3.9.1-dynamic_libdir.patch │ └── luarocks.spec │ ├── openresty-pcre │ ├── openresty-pcre.spec │ └── sources │ │ └── pcre-8.44 │ │ ├── 132html │ │ ├── AUTHORS │ │ ├── CMakeLists.txt │ │ ├── COPYING │ │ ├── ChangeLog │ │ ├── CheckMan │ │ ├── CleanTxt │ │ ├── Detrail │ │ ├── HACKING │ │ ├── INSTALL │ │ ├── LICENCE │ │ ├── Makefile.am │ │ ├── Makefile.in │ │ ├── NEWS │ │ ├── NON-AUTOTOOLS-BUILD │ │ ├── NON-UNIX-USE │ │ ├── PrepareRelease │ │ ├── README │ │ ├── RunGrepTest │ │ ├── RunTest │ │ ├── RunTest.bat │ │ ├── aclocal.m4 │ │ ├── ar-lib │ │ ├── cmake │ │ ├── COPYING-CMAKE-SCRIPTS │ │ ├── FindEditline.cmake │ │ ├── FindPackageHandleStandardArgs.cmake │ │ └── FindReadline.cmake │ │ ├── compile │ │ ├── config-cmake.h.in │ │ ├── config.guess │ │ ├── config.h.generic │ │ ├── config.h.in │ │ ├── config.sub │ │ ├── configure │ │ ├── configure.ac │ │ ├── depcomp │ │ ├── dftables.c │ │ ├── doc │ │ ├── html │ │ │ ├── NON-AUTOTOOLS-BUILD.txt │ │ │ ├── README.txt │ │ │ ├── index.html │ │ │ ├── pcre-config.html │ │ │ ├── pcre.html │ │ │ ├── pcre16.html │ │ │ ├── pcre32.html │ │ │ ├── pcre_assign_jit_stack.html │ │ │ ├── pcre_compile.html │ │ │ ├── pcre_compile2.html │ │ │ ├── pcre_config.html │ │ │ ├── pcre_copy_named_substring.html │ │ │ ├── pcre_copy_substring.html │ │ │ ├── pcre_dfa_exec.html │ │ │ ├── pcre_exec.html │ │ │ ├── pcre_free_study.html │ │ │ ├── pcre_free_substring.html │ │ │ ├── pcre_free_substring_list.html │ │ │ ├── pcre_fullinfo.html │ │ │ ├── pcre_get_named_substring.html │ │ │ ├── pcre_get_stringnumber.html │ │ │ ├── pcre_get_stringtable_entries.html │ │ │ ├── pcre_get_substring.html │ │ │ ├── pcre_get_substring_list.html │ │ │ ├── pcre_jit_exec.html │ │ │ ├── pcre_jit_stack_alloc.html │ │ │ ├── pcre_jit_stack_free.html │ │ │ ├── pcre_maketables.html │ │ │ ├── pcre_pattern_to_host_byte_order.html │ │ │ ├── pcre_refcount.html │ │ │ ├── pcre_study.html │ │ │ ├── pcre_utf16_to_host_byte_order.html │ │ │ ├── pcre_utf32_to_host_byte_order.html │ │ │ ├── pcre_version.html │ │ │ ├── pcreapi.html │ │ │ ├── pcrebuild.html │ │ │ ├── pcrecallout.html │ │ │ ├── pcrecompat.html │ │ │ ├── pcrecpp.html │ │ │ ├── pcredemo.html │ │ │ ├── pcregrep.html │ │ │ ├── pcrejit.html │ │ │ ├── pcrelimits.html │ │ │ ├── pcrematching.html │ │ │ ├── pcrepartial.html │ │ │ ├── pcrepattern.html │ │ │ ├── pcreperform.html │ │ │ ├── pcreposix.html │ │ │ ├── pcreprecompile.html │ │ │ ├── pcresample.html │ │ │ ├── pcrestack.html │ │ │ ├── pcresyntax.html │ │ │ ├── pcretest.html │ │ │ └── pcreunicode.html │ │ ├── index.html.src │ │ ├── pcre-config.1 │ │ ├── pcre-config.txt │ │ ├── pcre.3 │ │ ├── pcre.txt │ │ ├── pcre16.3 │ │ ├── pcre32.3 │ │ ├── pcre_assign_jit_stack.3 │ │ ├── pcre_compile.3 │ │ ├── pcre_compile2.3 │ │ ├── pcre_config.3 │ │ ├── pcre_copy_named_substring.3 │ │ ├── pcre_copy_substring.3 │ │ ├── pcre_dfa_exec.3 │ │ ├── pcre_exec.3 │ │ ├── pcre_free_study.3 │ │ ├── pcre_free_substring.3 │ │ ├── pcre_free_substring_list.3 │ │ ├── pcre_fullinfo.3 │ │ ├── pcre_get_named_substring.3 │ │ ├── pcre_get_stringnumber.3 │ │ ├── pcre_get_stringtable_entries.3 │ │ ├── pcre_get_substring.3 │ │ ├── pcre_get_substring_list.3 │ │ ├── pcre_jit_exec.3 │ │ ├── pcre_jit_stack_alloc.3 │ │ ├── pcre_jit_stack_free.3 │ │ ├── pcre_maketables.3 │ │ ├── pcre_pattern_to_host_byte_order.3 │ │ ├── pcre_refcount.3 │ │ ├── pcre_study.3 │ │ ├── pcre_utf16_to_host_byte_order.3 │ │ ├── pcre_utf32_to_host_byte_order.3 │ │ ├── pcre_version.3 │ │ ├── pcreapi.3 │ │ ├── pcrebuild.3 │ │ ├── pcrecallout.3 │ │ ├── pcrecompat.3 │ │ ├── pcrecpp.3 │ │ ├── pcredemo.3 │ │ ├── pcregrep.1 │ │ ├── pcregrep.txt │ │ ├── pcrejit.3 │ │ ├── pcrelimits.3 │ │ ├── pcrematching.3 │ │ ├── pcrepartial.3 │ │ ├── pcrepattern.3 │ │ ├── pcreperform.3 │ │ ├── pcreposix.3 │ │ ├── pcreprecompile.3 │ │ ├── pcresample.3 │ │ ├── pcrestack.3 │ │ ├── pcresyntax.3 │ │ ├── pcretest.1 │ │ ├── pcretest.txt │ │ ├── pcreunicode.3 │ │ └── perltest.txt │ │ ├── install-sh │ │ ├── libpcre.pc.in │ │ ├── libpcre16.pc.in │ │ ├── libpcre32.pc.in │ │ ├── libpcrecpp.pc.in │ │ ├── libpcreposix.pc.in │ │ ├── ltmain.sh │ │ ├── m4 │ │ ├── ax_pthread.m4 │ │ ├── libtool.m4 │ │ ├── ltoptions.m4 │ │ ├── ltsugar.m4 │ │ ├── ltversion.m4 │ │ ├── lt~obsolete.m4 │ │ └── pcre_visibility.m4 │ │ ├── makevp.bat │ │ ├── makevp_c.txt │ │ ├── makevp_l.txt │ │ ├── missing │ │ ├── pcre-config.in │ │ ├── pcre.h.generic │ │ ├── pcre.h.in │ │ ├── pcre16_byte_order.c │ │ ├── pcre16_chartables.c │ │ ├── pcre16_compile.c │ │ ├── pcre16_config.c │ │ ├── pcre16_dfa_exec.c │ │ ├── pcre16_exec.c │ │ ├── pcre16_fullinfo.c │ │ ├── pcre16_get.c │ │ ├── pcre16_globals.c │ │ ├── pcre16_jit_compile.c │ │ ├── pcre16_maketables.c │ │ ├── pcre16_newline.c │ │ ├── pcre16_ord2utf16.c │ │ ├── pcre16_printint.c │ │ ├── pcre16_refcount.c │ │ ├── pcre16_string_utils.c │ │ ├── pcre16_study.c │ │ ├── pcre16_tables.c │ │ ├── pcre16_ucd.c │ │ ├── pcre16_utf16_utils.c │ │ ├── pcre16_valid_utf16.c │ │ ├── pcre16_version.c │ │ ├── pcre16_xclass.c │ │ ├── pcre32_byte_order.c │ │ ├── pcre32_chartables.c │ │ ├── pcre32_compile.c │ │ ├── pcre32_config.c │ │ ├── pcre32_dfa_exec.c │ │ ├── pcre32_exec.c │ │ ├── pcre32_fullinfo.c │ │ ├── pcre32_get.c │ │ ├── pcre32_globals.c │ │ ├── pcre32_jit_compile.c │ │ ├── pcre32_maketables.c │ │ ├── pcre32_newline.c │ │ ├── pcre32_ord2utf32.c │ │ ├── pcre32_printint.c │ │ ├── pcre32_refcount.c │ │ ├── pcre32_string_utils.c │ │ ├── pcre32_study.c │ │ ├── pcre32_tables.c │ │ ├── pcre32_ucd.c │ │ ├── pcre32_utf32_utils.c │ │ ├── pcre32_valid_utf32.c │ │ ├── pcre32_version.c │ │ ├── pcre32_xclass.c │ │ ├── pcre_byte_order.c │ │ ├── pcre_chartables.c.dist │ │ ├── pcre_compile.c │ │ ├── pcre_config.c │ │ ├── pcre_dfa_exec.c │ │ ├── pcre_exec.c │ │ ├── pcre_fullinfo.c │ │ ├── pcre_get.c │ │ ├── pcre_globals.c │ │ ├── pcre_internal.h │ │ ├── pcre_jit_compile.c │ │ ├── pcre_jit_test.c │ │ ├── pcre_maketables.c │ │ ├── pcre_newline.c │ │ ├── pcre_ord2utf8.c │ │ ├── pcre_printint.c │ │ ├── pcre_refcount.c │ │ ├── pcre_scanner.cc │ │ ├── pcre_scanner.h │ │ ├── pcre_scanner_unittest.cc │ │ ├── pcre_string_utils.c │ │ ├── pcre_stringpiece.cc │ │ ├── pcre_stringpiece.h.in │ │ ├── pcre_stringpiece_unittest.cc │ │ ├── pcre_study.c │ │ ├── pcre_tables.c │ │ ├── pcre_ucd.c │ │ ├── pcre_valid_utf8.c │ │ ├── pcre_version.c │ │ ├── pcre_xclass.c │ │ ├── pcrecpp.cc │ │ ├── pcrecpp.h │ │ ├── pcrecpp_internal.h │ │ ├── pcrecpp_unittest.cc │ │ ├── pcrecpparg.h.in │ │ ├── pcredemo.c │ │ ├── pcregexp.pas │ │ ├── pcregrep.c │ │ ├── pcreposix.c │ │ ├── pcreposix.h │ │ ├── pcretest.c │ │ ├── perltest.pl │ │ ├── sljit │ │ ├── sljitConfig.h │ │ ├── sljitConfigInternal.h │ │ ├── sljitExecAllocator.c │ │ ├── sljitLir.c │ │ ├── sljitLir.h │ │ ├── sljitNativeARM_32.c │ │ ├── sljitNativeARM_64.c │ │ ├── sljitNativeARM_T2_32.c │ │ ├── sljitNativeMIPS_32.c │ │ ├── sljitNativeMIPS_64.c │ │ ├── sljitNativeMIPS_common.c │ │ ├── sljitNativePPC_32.c │ │ ├── sljitNativePPC_64.c │ │ ├── sljitNativePPC_common.c │ │ ├── sljitNativeSPARC_32.c │ │ ├── sljitNativeSPARC_common.c │ │ ├── sljitNativeTILEGX-encoder.c │ │ ├── sljitNativeTILEGX_64.c │ │ ├── sljitNativeX86_32.c │ │ ├── sljitNativeX86_64.c │ │ ├── sljitNativeX86_common.c │ │ └── sljitUtils.c │ │ ├── test-driver │ │ ├── testdata │ │ ├── grepbinary │ │ ├── grepfilelist │ │ ├── grepinput │ │ ├── grepinput3 │ │ ├── grepinput8 │ │ ├── grepinputv │ │ ├── grepinputx │ │ ├── greplist │ │ ├── grepoutput │ │ ├── grepoutput8 │ │ ├── grepoutputN │ │ ├── greppatN4 │ │ ├── saved16 │ │ ├── saved16BE-1 │ │ ├── saved16BE-2 │ │ ├── saved16LE-1 │ │ ├── saved16LE-2 │ │ ├── saved32 │ │ ├── saved32BE-1 │ │ ├── saved32BE-2 │ │ ├── saved32LE-1 │ │ ├── saved32LE-2 │ │ ├── saved8 │ │ ├── testinput1 │ │ ├── testinput10 │ │ ├── testinput11 │ │ ├── testinput12 │ │ ├── testinput13 │ │ ├── testinput14 │ │ ├── testinput15 │ │ ├── testinput16 │ │ ├── testinput17 │ │ ├── testinput18 │ │ ├── testinput19 │ │ ├── testinput2 │ │ ├── testinput20 │ │ ├── testinput21 │ │ ├── testinput22 │ │ ├── testinput23 │ │ ├── testinput24 │ │ ├── testinput25 │ │ ├── testinput26 │ │ ├── testinput3 │ │ ├── testinput4 │ │ ├── testinput5 │ │ ├── testinput6 │ │ ├── testinput7 │ │ ├── testinput8 │ │ ├── testinput9 │ │ ├── testinputEBC │ │ ├── testoutput1 │ │ ├── testoutput10 │ │ ├── testoutput11-16 │ │ ├── testoutput11-32 │ │ ├── testoutput11-8 │ │ ├── testoutput12 │ │ ├── testoutput13 │ │ ├── testoutput14 │ │ ├── testoutput15 │ │ ├── testoutput16 │ │ ├── testoutput17 │ │ ├── testoutput18-16 │ │ ├── testoutput18-32 │ │ ├── testoutput19 │ │ ├── testoutput2 │ │ ├── testoutput20 │ │ ├── testoutput21-16 │ │ ├── testoutput21-32 │ │ ├── testoutput22-16 │ │ ├── testoutput22-32 │ │ ├── testoutput23 │ │ ├── testoutput24 │ │ ├── testoutput25 │ │ ├── testoutput26 │ │ ├── testoutput3 │ │ ├── testoutput3A │ │ ├── testoutput3B │ │ ├── testoutput4 │ │ ├── testoutput5 │ │ ├── testoutput6 │ │ ├── testoutput7 │ │ ├── testoutput8 │ │ ├── testoutput9 │ │ ├── testoutputEBC │ │ ├── valgrind-jit.supp │ │ ├── wintestinput3 │ │ └── wintestoutput3 │ │ └── ucp.h │ ├── openresty-zlib │ └── openresty-zlib.spec │ └── openresty │ ├── openresty.spec │ └── patches │ ├── openresty-1.21.4_01-use-local-dependencies.patch │ ├── openresty-1.21.4_02-add-extra-flags.patch │ ├── openresty-1.21.4_03-add-TARGET_STRIP-for-luajit.patch │ └── openresty-1.21.4_04-bump-nginx-version.patch ├── dev-environments ├── camel-proxy │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ └── docker-compose.yml ├── grpc │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── docker-compose.yml │ └── echoserver.Dockerfile ├── http-proxy-plain-http-upstream │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── docker-compose.yml │ ├── tinyproxy.Dockerfile │ └── tinyproxy.conf ├── https-proxy-upstream-tlsv1.3 │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── cert │ │ └── Makefile │ ├── docker-compose.yml │ ├── tinyproxy.Dockerfile │ └── tinyproxy.conf ├── keycloak-env │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ └── docker-compose.yml ├── listen-tls │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── cert │ │ └── Makefile │ └── docker-compose.yml ├── mtls │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── cert │ │ ├── Makefile │ │ ├── intermediate.cnf │ │ └── root-ca.cnf │ ├── docker-compose.yml │ ├── docker-entrypoint.sh │ └── ocsp.Dockerfile ├── opentelemetry-instrumented-gateway │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── docker-compose.yml │ └── otel.toml ├── plain-http-upstream │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ └── docker-compose.yml └── upstream-tlsv1.3 │ ├── Makefile │ ├── README.md │ ├── apicast-config.json │ ├── cert │ └── Makefile │ └── docker-compose.yml ├── doc ├── build.md ├── config.ld ├── configuration.md ├── development.md ├── dns-resolver.md ├── grpc.md ├── integration-tests.md ├── liquid_conditions.md ├── management-api.md ├── oidc.md ├── overview.md ├── parameters.md ├── performance.md ├── policies.md ├── policies_list │ ├── 3.10.0 │ │ └── policies.json │ ├── 3.11.0 │ │ └── policies.json │ ├── 3.11.1 │ │ └── policies.json │ ├── 3.12.0 │ │ └── policies.json │ ├── 3.13.2 │ │ └── policies.json │ ├── 3.14.0 │ │ └── policies.json │ ├── 3.15.0 │ │ └── policies.json │ ├── 3.16.0 │ │ └── policies.json │ ├── 3.3.0 │ │ └── policies.json │ ├── 3.4.0 │ │ └── policies.json │ ├── 3.5.0 │ │ └── policies.json │ ├── 3.6.0 │ │ └── policies.json │ ├── 3.7.0 │ │ └── policies.json │ ├── 3.8.0 │ │ └── policies.json │ └── 3.9.0 │ │ └── policies.json ├── policy-development.md ├── policy_tutorial │ ├── DEV_ENV_SETUP.md │ ├── POLICY_IMPLEMENTATION.md │ ├── POLICY_RUN_LOCALLY.md │ ├── POLICY_SCAFFOLD.md │ ├── README.md │ ├── apicast │ │ ├── examples │ │ │ └── configuration │ │ │ │ └── hello_world_config.json │ │ ├── gateway │ │ │ └── src │ │ │ │ └── apicast │ │ │ │ └── policy │ │ │ │ └── hello_world │ │ │ │ ├── apicast-policy.json │ │ │ │ ├── hello_world.lua │ │ │ │ └── init.lua │ │ └── spec │ │ │ └── policy │ │ │ └── hello_world │ │ │ └── hello_world_spec.lua │ └── img │ │ ├── apicast-dev-container-mount.png │ │ ├── nginx-phases.png │ │ └── policy_layout.png ├── profiling.md ├── prometheus-metrics.md ├── unittests.md └── why.md ├── docker-compose-devel-volmount-default.yml ├── docker-compose-devel-volmount-mac.yml ├── docker-compose-devel.yml ├── docker-compose.benchmark.yml ├── docker-compose.prove.yml ├── docker-compose.yml ├── examples ├── add-ssl │ ├── README.md │ └── cert │ │ ├── server.crt │ │ └── server.key ├── configuration │ ├── README.md │ ├── echo.json │ ├── example-config.json │ ├── local.json │ ├── multiservice.json │ └── standalone.yml ├── custom-config │ ├── README.md │ └── echo.conf ├── custom-module │ ├── README.md │ ├── blacklist.lua │ └── verbose.lua ├── opentracing │ ├── apicast-config.json │ └── jaeger-config.json ├── policies │ ├── README.md │ ├── example.json │ ├── ngx-example │ │ └── 1.0.0 │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── ngx_example.lua │ ├── rate_limit_configuration.lua │ └── token_introspection_configuration.lua ├── policy_chain │ ├── README.md │ └── configuration.lua ├── scaffold │ └── policy │ │ ├── gateway │ │ └── src │ │ │ └── apicast │ │ │ └── policy │ │ │ └── {{policy.file}} │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── {{policy.file}}.lua │ │ ├── spec │ │ └── policy │ │ │ └── {{policy.name}} │ │ │ └── {{policy.name}}_spec.lua │ │ └── t │ │ └── apicast-policy-{{policy.file}}.t └── ssl-verification │ ├── README.md │ ├── badssl.json │ └── proxy_ssl.conf ├── fixtures └── config.json ├── gateway ├── Makefile ├── Roverfile ├── Roverfile.lock ├── apicast-scm-1.rockspec ├── apicast.d │ ├── buffers.conf │ ├── location.d │ │ └── .keep │ └── proxy_ssl.conf ├── bin │ ├── apicast │ ├── apicast_cli.lua │ ├── container-entrypoint │ └── run ├── conf.d │ ├── apicast.conf │ ├── backend.conf │ ├── echo.conf │ ├── http2.conf │ ├── management.conf │ ├── opentelemetry │ │ ├── otel.conf.liquid │ │ └── otel.example.toml │ └── upstream_shared.conf ├── conf │ ├── ca-bundle.crt │ ├── nginx.conf.liquid │ ├── proxy.conf │ ├── server.crt │ └── server.key ├── config-5.1.lua ├── config │ ├── development.lua │ ├── production.lua │ ├── sandbox.lua │ ├── staging.lua │ └── standalone.lua ├── cpanfile ├── cpanfile.snapshot ├── http.d │ ├── apicast.conf.liquid │ ├── core.conf │ ├── init.conf │ ├── lua_capture_error_log.conf │ ├── shdict.conf │ ├── ssl.conf │ ├── standalone.conf.liquid │ └── upstream.conf ├── libexec │ ├── boot │ ├── boot.lua │ ├── keycloak │ └── run ├── main.d │ └── .keep ├── sites.d │ └── .gitkeep └── src │ ├── apicast │ ├── backend │ │ └── cache_handler.lua │ ├── backend_client.lua │ ├── balancer.lua │ ├── cli.lua │ ├── cli │ │ ├── command │ │ │ ├── console.lua │ │ │ ├── generate.lua │ │ │ ├── generate │ │ │ │ └── policy.lua │ │ │ ├── push_policy.lua │ │ │ └── start.lua │ │ ├── environment.lua │ │ └── template.lua │ ├── conditions │ │ ├── condition.lua │ │ └── operation.lua │ ├── configuration.lua │ ├── configuration │ │ └── service.lua │ ├── configuration_loader.lua │ ├── configuration_loader │ │ ├── data_url.lua │ │ ├── file.lua │ │ ├── mock.lua │ │ ├── oidc.lua │ │ ├── remote_v1.lua │ │ └── remote_v2.lua │ ├── configuration_parser.lua │ ├── configuration_store.lua │ ├── errors.lua │ ├── executor.lua │ ├── gc.lua │ ├── http_proxy.lua │ ├── linked_list.lua │ ├── loader.lua │ ├── management.lua │ ├── mapping_rule.lua │ ├── mapping_rules_matcher.lua │ ├── metrics │ │ ├── 3scale_backend_calls.lua │ │ ├── updater.lua │ │ └── upstream.lua │ ├── oauth.lua │ ├── oauth │ │ └── oidc.lua │ ├── policy.lua │ ├── policy │ │ ├── 3scale_batcher │ │ │ ├── 3scale_batcher.lua │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── auths_cache.lua │ │ │ ├── init.lua │ │ │ ├── keys_helper.lua │ │ │ ├── metrics.lua │ │ │ ├── reporter.lua │ │ │ ├── reports_batch.lua │ │ │ ├── reports_batcher.lua │ │ │ └── transaction.lua │ │ ├── 3scale_referrer │ │ │ ├── 3scale_referrer.lua │ │ │ ├── apicast-policy.json │ │ │ └── init.lua │ │ ├── apicast │ │ │ ├── apicast-policy.json │ │ │ ├── apicast.lua │ │ │ └── init.lua │ │ ├── caching │ │ │ ├── apicast-policy.json │ │ │ ├── caching.lua │ │ │ └── init.lua │ │ ├── camel │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── camel.lua │ │ │ └── init.lua │ │ ├── clear_context │ │ │ ├── clear_context.lua │ │ │ └── init.lua │ │ ├── conditional │ │ │ ├── README.md │ │ │ ├── conditional.lua │ │ │ └── init.lua │ │ ├── content_caching │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── content_caching.lua │ │ │ ├── init.lua │ │ │ └── rule.lua │ │ ├── cors │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── cors.lua │ │ │ └── init.lua │ │ ├── custom_metrics │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── custom_metrics.lua │ │ │ └── init.lua │ │ ├── default_credentials │ │ │ ├── apicast-policy.json │ │ │ ├── default_credentials.lua │ │ │ └── init.lua │ │ ├── echo │ │ │ ├── apicast-policy.json │ │ │ ├── echo.lua │ │ │ └── init.lua │ │ ├── fapi │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── fapi.lua │ │ │ └── init.lua │ │ ├── find_service │ │ │ ├── find_service.lua │ │ │ ├── host_based_finder.lua │ │ │ ├── init.lua │ │ │ └── path_based_finder.lua │ │ ├── grpc │ │ │ ├── apicast-policy.json │ │ │ ├── grpc.lua │ │ │ └── init.lua │ │ ├── headers │ │ │ ├── apicast-policy.json │ │ │ ├── headers.lua │ │ │ └── init.lua │ │ ├── http_proxy │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── proxy.lua │ │ ├── ip_check │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── client_ip.lua │ │ │ ├── init.lua │ │ │ └── ip_check.lua │ │ ├── jwt_claim_check │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── jwt_claim_check.lua │ │ │ └── readme.md │ │ ├── jwt_parser │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── jwt_parser.lua │ │ ├── keycloak_role_check │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── keycloak_role_check.lua │ │ ├── liquid_context_debug │ │ │ ├── apicast-policy.json │ │ │ ├── context_content.lua │ │ │ ├── init.lua │ │ │ └── liquid_context_debug.lua │ │ ├── load_configuration │ │ │ ├── init.lua │ │ │ └── load_configuration.lua │ │ ├── local_chain │ │ │ ├── init.lua │ │ │ └── local_chain.lua │ │ ├── logging │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── logging.lua │ │ │ └── readme.md │ │ ├── maintenance_mode │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── maintenance_mode.lua │ │ ├── management │ │ │ ├── init.lua │ │ │ └── management.lua │ │ ├── manifest-schema.json │ │ ├── nginx_filters │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── nginx_filters.lua │ │ ├── nginx_metrics │ │ │ ├── init.lua │ │ │ └── nginx_metrics.lua │ │ ├── ngx_variable.lua │ │ ├── oauth_mtls │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── oauth_mtls.lua │ │ ├── on_failed │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── on_failed.lua │ │ ├── payload_limits │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── payload_limit.lua │ │ ├── phase_logger │ │ │ ├── init.lua │ │ │ └── phase_logger.lua │ │ ├── rate_limit │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── rate_limit.lua │ │ │ └── redis_shdict.lua │ │ ├── rate_limit_headers │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── cache.lua │ │ │ ├── cache_entry.lua │ │ │ ├── countdown_counter.lua │ │ │ ├── init.lua │ │ │ └── rate_limit_headers.lua │ │ ├── request_unbuffered │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── request_unbuffered.lua │ │ ├── retry │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── retry.lua │ │ ├── rewrite_url_captures │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── named_args_matcher.lua │ │ │ └── rewrite_url_captures.lua │ │ ├── routing │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── request.lua │ │ │ ├── routing.lua │ │ │ ├── routing_operation.lua │ │ │ ├── rule.lua │ │ │ └── upstream_selector.lua │ │ ├── soap │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── soap.lua │ │ ├── standalone │ │ │ ├── configuration.lua │ │ │ ├── init.lua │ │ │ └── standalone.lua │ │ ├── statuscode_overwrite │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── code_overwrite.lua │ │ │ └── init.lua │ │ ├── tls │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── tls.lua │ │ ├── tls_validation │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── ocsp_validation.lua │ │ │ └── tls_validation.lua │ │ ├── token_introspection │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ ├── token_introspection.lua │ │ │ └── tokens_cache.lua │ │ ├── upstream │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── upstream.lua │ │ ├── upstream_connection │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── upstream_connection.lua │ │ ├── upstream_mtls │ │ │ ├── Readme.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── upstream_mtls.lua │ │ ├── url_rewriting │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── url_rewriting.lua │ │ └── websocket │ │ │ ├── README.md │ │ │ ├── apicast-policy.json │ │ │ ├── init.lua │ │ │ └── websocket.lua │ ├── policy_chain.lua │ ├── policy_config_validator.lua │ ├── policy_loader.lua │ ├── policy_manifests_loader.lua │ ├── policy_order_checker.lua │ ├── policy_pusher.lua │ ├── prometheus.lua │ ├── proxy.lua │ ├── query_params.lua │ ├── template_string.lua │ ├── threescale_utils.lua │ ├── upstream.lua │ ├── usage.lua │ ├── user_agent.lua │ ├── util.lua │ └── version.lua │ └── resty │ ├── balancer.lua │ ├── balancer │ ├── random.lua │ └── round_robin.lua │ ├── concurrent │ ├── event.lua │ ├── executor.lua │ ├── future.lua │ ├── immediate_executor.lua │ ├── safe_task_executor.lua │ ├── timer_pool_executor.lua │ └── timer_task.lua │ ├── coroutines.lua │ ├── counter.lua │ ├── ctx.lua │ ├── data_url.lua │ ├── file.lua │ ├── http │ ├── proxy.lua │ ├── request_reader.lua │ ├── response_writer.lua │ └── uri_escape.lua │ ├── http_authorization.lua │ ├── http_ng.lua │ ├── http_ng │ ├── backend │ │ ├── async_resty.lua │ │ ├── cache.lua │ │ ├── resty.lua │ │ └── test.lua │ ├── cache_store.lua │ ├── headers.lua │ ├── request.lua │ └── response.lua │ ├── limit │ └── count-inc.lua │ ├── log │ └── log.lua │ ├── mime.lua │ ├── oidc │ ├── discovery.lua │ └── jwk.lua │ ├── resolver.lua │ ├── resolver │ ├── cache.lua │ ├── dns_client.lua │ ├── http.lua │ └── socket.lua │ ├── sandbox.lua │ ├── synchronization.lua │ ├── tls.lua │ ├── url_helper.lua │ └── yaml.lua ├── luarocks.config ├── markdown-lint-check-config.json ├── openresty.repo ├── openshift ├── apicast-template.yml └── portal-secret-template.yml ├── package.json ├── rockspec ├── schema.json ├── script ├── install │ ├── apicast.sh │ ├── centos.sh │ ├── circleci.sh │ ├── luarocks.sh │ ├── openresty.sh │ └── utilities.sh ├── luacov ├── profiling │ ├── configs │ │ ├── echo_config.lua │ │ └── profile_apicast_config.json │ └── profile.lua ├── prove ├── redis ├── redis.lua ├── reorder-tests ├── resolver ├── resolver.lua ├── test ├── traces │ ├── Readme.md │ └── leaked.st └── wrk-report.lua ├── site_config.lua ├── spec ├── backend │ └── cache_handler_spec.lua ├── backend_client_spec.lua ├── balancer_spec.lua ├── ci_reporter.lua ├── cli │ ├── environment_spec.lua │ └── template_spec.lua ├── conditions │ ├── condition_spec.lua │ └── operation_spec.lua ├── configuration │ └── service_spec.lua ├── configuration_loader │ ├── data_url_spec.lua │ ├── file_spec.lua │ ├── mock_spec.lua │ ├── oidc_spec.lua │ ├── remote_v1_spec.lua │ └── remote_v2_spec.lua ├── configuration_loader_spec.lua ├── configuration_parser_spec.lua ├── configuration_spec.lua ├── configuration_store_spec.lua ├── errors_spec.lua ├── examples │ └── custom-module │ │ └── blacklist_spec.lua ├── executor_spec.lua ├── fake_backend_helper.lua ├── fixtures │ ├── certs.lua │ ├── echo.conf │ ├── oidc │ │ └── jwk │ │ │ ├── forgerock.apicast.json │ │ │ └── forgerock.json │ ├── policies │ │ └── test │ │ │ ├── 1.0.0-0 │ │ │ ├── apicast-policy.json │ │ │ ├── dependency.lua │ │ │ ├── init.lua │ │ │ └── test.lua │ │ │ └── 2.0.0-0 │ │ │ ├── apicast-policy.json │ │ │ ├── dependency.lua │ │ │ └── init.lua │ └── standalone │ │ ├── invalid.json │ │ ├── invalid.txt │ │ ├── invalid.yml │ │ ├── valid.json │ │ └── valid.yml ├── gc_spec.lua ├── http_proxy_spec.lua ├── jwt_helper.lua ├── linked_list_spec.lua ├── luassert_helper.lua ├── management_spec.lua ├── mapping_rule_spec.lua ├── mapping_rules_matcher_spec.lua ├── metrics │ ├── 3scale_backend_calls_spec.lua │ └── upstream_spec.lua ├── ngx_helper.lua ├── oauth │ └── oidc_spec.lua ├── policy │ ├── 3scale_batcher │ │ ├── 3scale_batcher_spec.lua │ │ ├── auths_cache_spec.lua │ │ ├── keys_helper_spec.lua │ │ ├── reporter_spec.lua │ │ ├── reports_batch_spec.lua │ │ └── reports_batcher_spec.lua │ ├── 3scale_referrer │ │ └── 3scale_referrer_spec.lua │ ├── apicast │ │ └── apicast_spec.lua │ ├── caching │ │ └── caching_spec.lua │ ├── camel │ │ └── camel_spec.lua │ ├── clear_context │ │ └── clear_context_spec.lua │ ├── conditional │ │ └── conditional_spec.lua │ ├── content_caching │ │ ├── content_caching_spec.lua │ │ └── rule_spec.lua │ ├── cors │ │ └── cors_spec.lua │ ├── custom_metrics │ │ └── custom_metrics_spec.lua │ ├── default_credentials │ │ └── default_credentials_spec.lua │ ├── echo │ │ └── echo_spec.lua │ ├── fapi │ │ └── fapi_spec.lua │ ├── find_service │ │ ├── find_service_spec.lua │ │ ├── host_based_finder_spec.lua │ │ └── path_based_finder_spec.lua │ ├── headers │ │ └── headers_spec.lua │ ├── http_proxy │ │ └── http_proxy_spec.lua │ ├── ip_check │ │ ├── client_ip_spec.lua │ │ └── ip_check_spec.lua │ ├── jwt_claim_check │ │ └── jwt_claim_check_spec.lua │ ├── jwt_parser │ │ └── jwt_parser_spec.lua │ ├── keycloak_role_check │ │ └── keycloak_role_check_spec.lua │ ├── liquid_context_debug │ │ ├── context_content_spec.lua │ │ └── liquid_context_debug_spec.lua │ ├── load_configuration │ │ └── load_configuration_spec.lua │ ├── local_chain │ │ └── local_chain_spec.lua │ ├── logging │ │ └── logging_spec.lua │ ├── maintenance_mode │ │ └── maintenance_mode_spec.lua │ ├── management │ │ └── management_spec.lua │ ├── ngx_variable_spec.lua │ ├── oauth_mtls │ │ └── oauth_mtls_spec.lua │ ├── rate_limit │ │ ├── rate_limit_spec.lua │ │ └── redis_shdict_spec.lua │ ├── rate_limit_headers │ │ ├── cache_entry_spec.lua │ │ ├── cache_spec.lua │ │ └── countdown_counter_spec.lua │ ├── retry │ │ └── retry_spec.lua │ ├── rewrite_url_captures │ │ ├── named_args_matcher_spec.lua │ │ └── rewrite_url_captures_spec.lua │ ├── routing │ │ ├── request_spec.lua │ │ ├── routing_operation_spec.lua │ │ ├── routing_spec.lua │ │ └── upstream_selector_spec.lua │ ├── soap │ │ └── soap_spec.lua │ ├── standalone │ │ ├── configuration_spec.lua │ │ └── standalone_spec.lua │ ├── statuscode_overwrite │ │ └── statuscode_overwrite_spec.lua │ ├── tls │ │ └── tls_spec.lua │ ├── tls_validation │ │ └── tls_validation_spec.lua │ ├── token_introspection │ │ ├── token_introspection_spec.lua │ │ └── tokens_cache_spec.lua │ ├── upstream │ │ └── upstream_spec.lua │ ├── upstream_connection │ │ └── upstream_connection_spec.lua │ ├── upstream_mtls │ │ └── upstream_mtls_spec.lua │ └── url_rewriting │ │ └── url_rewriting_spec.lua ├── policy_chain_spec.lua ├── policy_config_validator_spec.lua ├── policy_loader_spec.lua ├── policy_manifests_loader_spec.lua ├── policy_order_checker_spec.lua ├── policy_pusher_spec.lua ├── policy_spec.lua ├── prometheus_spec.lua ├── proxy_spec.lua ├── query_params_spec.lua ├── resty │ ├── balancer_spec.lua │ ├── concurrent │ │ ├── event_spec.lua │ │ ├── executor_spec.lua │ │ ├── future_spec.lua │ │ ├── immediate_executor_spec.lua │ │ ├── safe_task_executor_spec.lua │ │ ├── timer_pool_executor_spec.lua │ │ └── timer_task_spec.lua │ ├── counter_spec.lua │ ├── data_url_spec.lua │ ├── file_spec.lua │ ├── http │ │ ├── proxy_spec.lua │ │ └── uri_escape_spec.lua │ ├── http_authorization_spec.lua │ ├── http_ng │ │ ├── backend │ │ │ ├── async_resty_spec.lua │ │ │ ├── cache_spec.lua │ │ │ ├── resty_spec.lua │ │ │ └── test_spec.lua │ │ ├── cache_store_spec.lua │ │ ├── headers_spec.lua │ │ ├── request_spec.lua │ │ └── response_spec.lua │ ├── http_ng_spec.lua │ ├── limit │ │ └── count-inc_spec.lua │ ├── mime_spec.lua │ ├── oidc │ │ ├── discovery_spec.lua │ │ └── jwk_spec.lua │ ├── resolver │ │ ├── cache_spec.lua │ │ ├── dns_client_spec.lua │ │ ├── http_spec.lua │ │ └── socket_spec.lua │ ├── resolver_spec.lua │ ├── url_helper_spec.lua │ └── yaml_spec.lua ├── spec_helper.lua ├── ssl_helper.lua ├── synchronization_spec.lua ├── template_string_spec.lua ├── threescale_utils_spec.lua ├── upstream_spec.lua ├── usage_spec.lua ├── user_agent_spec.lua └── util_spec.lua ├── t ├── apicast-async-reporting.t ├── apicast-bin.t ├── apicast-blackbox.t ├── apicast-caching.t ├── apicast-http2.t ├── apicast-log.t ├── apicast-mapping-rules.t ├── apicast-oidc.t ├── apicast-path-routing.t ├── apicast-policies-order.t ├── apicast-policy-3scale-batcher-blackbox.t ├── apicast-policy-3scale-batcher.t ├── apicast-policy-3scale-referrer.t ├── apicast-policy-caching.t ├── apicast-policy-camel.t ├── apicast-policy-chains-crash.t ├── apicast-policy-chains.t ├── apicast-policy-conditional.t ├── apicast-policy-content-caching.t ├── apicast-policy-cors.t ├── apicast-policy-custom-metrics.t ├── apicast-policy-default-credentials.t ├── apicast-policy-fapi.t ├── apicast-policy-headers.t ├── apicast-policy-http-proxy.t ├── apicast-policy-invalid-config.t ├── apicast-policy-ip-check.t ├── apicast-policy-jwt-claim-check.t ├── apicast-policy-jwt_parser.t ├── apicast-policy-keycloak-role-check.t ├── apicast-policy-liquid-context-debug.t ├── apicast-policy-logging.t ├── apicast-policy-maintenance-mode.t ├── apicast-policy-management.t ├── apicast-policy-nginx_filters.t ├── apicast-policy-oauth-mtls.t ├── apicast-policy-on_failed.t ├── apicast-policy-payload_limits.t ├── apicast-policy-rate-limit.t ├── apicast-policy-rate_limit_headers.t ├── apicast-policy-request-unbuffered.t ├── apicast-policy-retry.t ├── apicast-policy-rewrite-url-captures.t ├── apicast-policy-routing.t ├── apicast-policy-soap.t ├── apicast-policy-standalone.t ├── apicast-policy-statuscode_overwrite.t ├── apicast-policy-tls.t ├── apicast-policy-tls_validation.t ├── apicast-policy-token-introspection.t ├── apicast-policy-upstream-connection.t ├── apicast-policy-upstream.t ├── apicast-policy-upstream_mtls.t ├── apicast-policy-url-rewriting.t ├── apicast-policy-websocket.t ├── apicast-request-logs.t ├── apicast-syslog.t ├── apicast-upstream-balancer.t ├── apicast.t ├── backend-cache-handler.t ├── backend.t ├── balancer.t ├── configuration-loading-boot-remote.t ├── configuration-loading-boot-staging.t ├── configuration-loading-boot-with-config.t ├── configuration-loading-boot-without-config.t ├── configuration-loading-filter-services-by-url.t ├── configuration-loading-from-service-list.t ├── configuration-loading-lazy.t ├── configuration-loading-with-oidc.t ├── configuration-loading-with-service-version.t ├── configuration-store-cache-limit.t ├── custom-config.t ├── deprecation-warnings.t ├── fixtures │ ├── CA │ │ ├── Makefile │ │ ├── ca-bundle.crt │ │ ├── client.crt │ │ ├── client.key │ │ ├── crl.pem │ │ ├── crl │ │ │ ├── crlnumber │ │ │ ├── index.txt │ │ │ ├── index.txt.attr │ │ │ ├── index.txt.old │ │ │ └── serial │ │ ├── crl_openssl.conf │ │ ├── files.pl │ │ ├── intermediate-ca.crt │ │ ├── intermediate-ca.key │ │ ├── no_good_one.pem │ │ ├── revoked_client.crt │ │ ├── revoked_client.key │ │ ├── root-ca.crt │ │ ├── root-ca.key │ │ ├── server.crt │ │ └── server.key │ ├── certs │ │ ├── ec256_private_key.pem │ │ ├── ec256_public_key.pem │ │ ├── ec521_private_key.pem │ │ └── ec521_public_key.pem │ ├── client.crt │ ├── client.key │ ├── configs │ │ └── without_nginx_metrics.lua │ ├── echo.json │ ├── mutual_ssl.pl │ ├── ocsp │ │ ├── README.md │ │ ├── ca-key.pem │ │ ├── ca.csr │ │ ├── ca.pem │ │ ├── cfssl │ │ │ ├── ca_csr.json │ │ │ ├── cfssl_config.json │ │ │ ├── intermediate_ca_csr.json │ │ │ ├── leaf_csr.json │ │ │ └── ocsp_csr.json │ │ ├── chain.pem │ │ ├── client-key.pem │ │ ├── client.csr │ │ ├── client.pem │ │ ├── files.pl │ │ ├── intermediate_ca-key.pem │ │ ├── intermediate_ca.csr │ │ ├── intermediate_ca.pem │ │ ├── ocsp-key.pem │ │ ├── ocsp-response-good-response.der │ │ ├── ocsp-response-revoked-response.der │ │ ├── ocsp.csr │ │ ├── ocsp.pem │ │ ├── server-key.pem │ │ ├── server.csr │ │ ├── server.pem │ │ └── wrong-issuer-order-chain.pem │ ├── otel.toml │ ├── passwords.file │ ├── policies │ │ ├── deny │ │ │ └── 1.0.0 │ │ │ │ ├── apicast-policy.json │ │ │ │ ├── deny.lua │ │ │ │ └── init.lua │ │ ├── error_policy │ │ │ └── 1.0.0 │ │ │ │ ├── apicast-policy.json │ │ │ │ ├── error_policy.lua │ │ │ │ └── init.lua │ │ ├── example_policy │ │ │ └── 1.0.0 │ │ │ │ ├── apicast-policy.json │ │ │ │ ├── example_policy.lua │ │ │ │ └── init.lua │ │ └── https │ │ │ └── builtin │ │ │ └── init.lua │ ├── policies_endpoint_test │ │ └── policies │ │ │ ├── example1 │ │ │ └── 1.0.0 │ │ │ │ ├── apicast-policy.json │ │ │ │ ├── example1.lua │ │ │ │ └── init.lua │ │ │ └── example2 │ │ │ └── 1.0.0 │ │ │ ├── apicast-policy.json │ │ │ ├── example2.lua │ │ │ └── init.lua │ ├── proxy.lua │ ├── rsa.pem │ ├── rsa.pub │ ├── server.crt │ ├── server.key │ ├── tls.pl │ └── upstream.json ├── helpers │ └── request.lua ├── http-keepalive-timeout.t ├── http-proxy.t ├── http_proxy.pl ├── large-client-header-buffers.t ├── liquid.t ├── listen-https.t ├── management-policies-endpoint-custom.t ├── management-policies-endpoint.t ├── management.t ├── mutual-ssl.t ├── opentelemetry.t ├── policies.pl ├── prometheus-metrics.t ├── proxy-buffers.t ├── proxy-protocol.t ├── resolver.t ├── resty-ctx.t ├── sanity.t └── spec.json └── yarn.lock /.busted: -------------------------------------------------------------------------------- 1 | local path = require('pl.path') 2 | local root = path.currentdir() 3 | 4 | local ci = os.getenv('CI') 5 | 6 | local all = { 7 | helper = path.join(root, 'spec/spec_helper.lua'), 8 | } 9 | local default = { 10 | verbose = true, 11 | ['shuffle-tests'] = true, 12 | ['shuffle-files'] = true, 13 | 14 | lpath = path.join(root, 'spec/?.lua;') .. path.join(root, 'gateway/src/?.lua;'), 15 | } 16 | 17 | if ci then 18 | default.output = 'spec.ci_reporter' 19 | end 20 | 21 | return { 22 | _all = all, 23 | default = default, 24 | } 25 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | luacheck: 4 | enabled: true 5 | checks: 6 | LC631: 7 | enabled: false 8 | config: 9 | max_cyclomatic_complexity: 7 10 | shellcheck: 11 | enabled: true 12 | checks: 13 | SC1008: 14 | enabled: false 15 | exclude_paths: 16 | - local 17 | - node_modules 18 | ratings: 19 | paths: 20 | - "**.sh" 21 | - "**.lua" 22 | - "**/bin/*" 23 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: master 3 | comment: off 4 | ignore: 5 | - spec 6 | - t 7 | - bin/busted.lua 8 | - examples 9 | 10 | coverage: 11 | status: 12 | project: 13 | default: 14 | target: auto 15 | threshold: 3% 16 | patch: 17 | default: 18 | target: auto 19 | threshold: 3% 20 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | lua_modules 4 | .DS_Store 5 | t/servroot* 6 | log 7 | .idea 8 | *.swp 9 | tmp 10 | .vagrant 11 | /.docker 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | CHANGELOG.md merge=union 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # APIcast Core team owns everything. 2 | * @3scale/apicast-core 3 | 4 | # But documentation is also owned by the documentation team. 5 | /doc/ @3scale/documentation 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | [provide a description of the issue] 2 | 3 | 4 | ##### Version 5 | 6 | [provide output of the `nginx -V` or `openresty -V` command from openshift/local terminal] 7 | [provide timestamp of the docker image from `docker inspect --format='{{.Created}}' quay.io/3scale/apicast:master` ] 8 | 9 | ##### Steps To Reproduce 10 | 11 | 1. [step 1 (json configuration file, if applies)] 12 | 2. [step 2 (curl commands to reproduce, if applies)] 13 | 3. [step 3] 14 | 15 | ##### Current Result 16 | 17 | ##### Expected Result 18 | 19 | ##### Additional Information 20 | 21 | * [Gist with minimal reproducible configuration, see guidelines for contributing for details] 22 | * [Gist with nginx log output] 23 | -------------------------------------------------------------------------------- /.github/workflows/fast-forward-branch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Fast-forward between branches 3 | "on": 4 | workflow_dispatch: 5 | inputs: 6 | ref: 7 | description: 'The branch name or commit to fast-forward from' 8 | default: 'master' 9 | type: string 10 | to_branch: 11 | description: 'The branch name to fast-forward to' 12 | default: 'managed-services' 13 | type: string 14 | jobs: 15 | fast-forward: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | ref: ${{ github.event.inputs.ref }} 21 | fetch-depth: 0 22 | - run: | 23 | git fetch origin ${{ github.event.inputs.ref }}:${{ github.event.inputs.to_branch }} 24 | git push origin ${{ github.event.inputs.to_branch }} 25 | -------------------------------------------------------------------------------- /.github/workflows/link_check.yaml: -------------------------------------------------------------------------------- 1 | name: link-check 2 | 3 | on: [push, pull_request] 4 | permissions: 5 | contents: read 6 | pull-requests: read 7 | statuses: write 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: read 13 | pull-requests: read 14 | statuses: write 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: 14 20 | 21 | - name: Test 22 | run: | 23 | npm install -g yarn 24 | make test-doc 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | luacov.*.out 2 | local/ 3 | t/servroot*/ 4 | doc/lua/ 5 | node_modules 6 | .vagrant/ 7 | apicast/logs/ 8 | *.rock 9 | # explicitly allow some source rocks as dependencies 10 | !dependencies/rpm-specs/gateway-rockspecs-native/source_rocks/*.src.rock 11 | !dependencies/rpm-specs/gateway-rockspecs/source_rocks/*.src.rock 12 | lua_modules/ 13 | tmp/benchmark/ 14 | .bash_history 15 | .cache/ 16 | .cpanm 17 | /vendor/cache 18 | /tmp/ 19 | .gitconfig 20 | .idea/ 21 | .vscode/ -------------------------------------------------------------------------------- /.lgtm: -------------------------------------------------------------------------------- 1 | approvals = 1 2 | pattern = "(?i):shipit:|:\\+1:|👍|LGTM|:fried_shrimp:|🍤" 3 | -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | local standards = require "luacheck.standards" 2 | 3 | -- stds global is provided by luacheck 4 | -- https://luacheck.readthedocs.io/en/stable/config.html#custom-sets-of-globals 5 | stds.ngx = { 6 | read_globals = { 7 | coroutine = standards.def_fields('_yield', '_create', '_resume') 8 | } 9 | } 10 | 11 | std = 'ngx_lua+lua52+ngx' -- lua52 has table.pack 12 | redefined = false 13 | unused_args = false 14 | max_line_length = false 15 | 16 | busted = {std = "+busted", globals = { 'fixture' } } 17 | files["**/spec/**/*_spec.lua"] = busted 18 | 19 | globals = { 'rawlen' } 20 | 21 | files['gateway/config/*.lua'] = { globals = { 'context' } } 22 | -------------------------------------------------------------------------------- /.luacov: -------------------------------------------------------------------------------- 1 | exclude = { 2 | '/.luarocks/', 3 | '/luarocks/', 4 | } 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Michal Cichra Michal Cichra 2 | Joaquim Moreno builder 3 | -------------------------------------------------------------------------------- /3scale-gateway-openshift-template.yml: -------------------------------------------------------------------------------- 1 | openshift/apicast-template.yml -------------------------------------------------------------------------------- /3scale-portal-endpoint-secret.yml: -------------------------------------------------------------------------------- 1 | openshift/portal-secret-template.yml -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | tap "3scale/openresty" 2 | 3 | brew "3scale/openresty/luarocks", link: true 4 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | samugi 2 | kevprice83 3 | sergioifg94 4 | eguzki 5 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | 3scale apicast 2 | Copyright (c) 2016 3scale Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /benchmark/template.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require 'ffi' 3 | 4 | local CLOCK = { 5 | REALTIME = 0, 6 | MONOTONIC = 1, 7 | PROCESS_CPUTIME_ID = 2, 8 | THREAD_CPUTIME_ID = 3, 9 | MONOTONIC_RAW = 4, 10 | REALTIME_COARSE = 5, 11 | MONOTONIC_COARSE = 6, 12 | } 13 | 14 | local function time_ns(clock) 15 | local ts = ffi.new("struct timespec[1]") 16 | assert(ffi.C.clock_gettime(clock or CLOCK.MONOTONIC_RAW, ts) == 0, 17 | "clock_gettime() failed: "..ffi.errno()) 18 | return tonumber(ts[0].tv_sec * 1e9 + ts[0].tv_nsec) 19 | end 20 | 21 | local monotime = require('busted.core')().monotime 22 | 23 | require('benchmark.ips')(function(b) 24 | b.time = 5 25 | b.warmup = 2 26 | 27 | b:report('ffi', function() return time_ns() end) 28 | b:report('syscall', function() return monotime() end) 29 | 30 | b:compare() 31 | end) 32 | -------------------------------------------------------------------------------- /bin/apicast: -------------------------------------------------------------------------------- 1 | ../gateway/bin/apicast -------------------------------------------------------------------------------- /bin/busted: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings FATAL => 'all'; 5 | 6 | use File::Basename; 7 | use File::Path qw(make_path); 8 | use Cwd; 9 | 10 | my $dirname = dirname(__FILE__); 11 | my $cwd = getcwd(); 12 | 13 | chdir "$dirname/.."; 14 | 15 | my $apicast = getcwd(); 16 | 17 | $ENV{APICAST_DIR} ||= "$apicast/gateway"; 18 | 19 | if(defined $ENV{JUNIT_OUTPUT_FILE}) { 20 | make_path(dirname($ENV{JUNIT_OUTPUT_FILE})); 21 | } 22 | 23 | exec '/usr/bin/env', 'resty', 24 | '--errlog-level', $ENV{APICAST_LOG_LEVEL} || 'alert', 25 | '--http-include', "$apicast/spec/fixtures/echo.conf", 26 | '-l', 'resty.core', 27 | "$apicast/bin/busted.lua", 28 | '--config-file', "$apicast/.busted", 29 | '--directory', "$cwd", 30 | @ARGV; 31 | -------------------------------------------------------------------------------- /bin/busted.lua: -------------------------------------------------------------------------------- 1 | -- Clean warning on openresty 1.15.8.1, where some global variables are set 2 | -- using ngx.timer that triggers an invalid warning message. 3 | -- Code related: https://github.com/openresty/lua-nginx-module/blob/61e4d0aac8974b8fad1b5b93d0d3d694d257d328/src/ngx_http_lua_util.c#L795-L839 4 | getmetatable(_G).__newindex = nil 5 | 6 | if ngx ~= nil then 7 | ngx.exit = function()end 8 | end 9 | 10 | if os.getenv('CI') == 'true' then 11 | local luacov = require('luacov.runner') 12 | local pwd = os.getenv('PWD') 13 | 14 | for _, option in ipairs({"statsfile", "reportfile"}) do 15 | -- properly expand current working dir, workaround for https://github.com/openresty/resty-cli/issues/35 16 | luacov.defaults[option] = pwd .. package.config:sub(1, 1) .. luacov.defaults[option] 17 | end 18 | 19 | table.insert(arg, '--coverage') 20 | end 21 | 22 | -- Busted command-line runner 23 | require 'busted.runner'({ standalone = false }) 24 | -------------------------------------------------------------------------------- /config-5.1.lua: -------------------------------------------------------------------------------- 1 | lua_interpreter = [[resty]] 2 | lib_modules_path = [[/lib/lua/]]..lua_version 3 | 4 | variables = { 5 | LUAROCKS_PREFIX = [[/usr]] 6 | } 7 | -------------------------------------------------------------------------------- /dependencies/container-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | exec "$@" 3 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs-native/.gitignore: -------------------------------------------------------------------------------- 1 | /*.rock 2 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs-native/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | 3 | RUN yum upgrade -y \ 4 | && dnf install -y 'dnf-command(config-manager)' 5 | RUN yum install -y epel-release git make gcc cmake gcc-c++ which 6 | RUN yum config-manager --add-repo http://packages.dev.3sca.net/dev_packages_3sca_net.repo 7 | RUN dnf --enablerepo=PowerTools install -y libyaml-devel luarocks 8 | RUN yum install -y rpm-build redhat-rpm-config rpmdevtools 9 | 10 | RUN mkdir -p /root/rpmbuild/SOURCES/ 11 | 12 | 13 | COPY . /opt/data/ 14 | RUN cp /opt/data/licenses.xml /root/rpmbuild/SOURCES/ 15 | RUN spectool -g -R /opt/data/*.spec 16 | RUN rpmbuild -ba /opt/data/*.spec 17 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs-native/licenses.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lyaml 7 | 6.2.3-1 8 | 9 | 10 | MIT 11 | https://opensource.org/licenses/mit-license 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs-native/source_rocks/luafilesystem-1.8.0-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs-native/source_rocks/luafilesystem-1.8.0-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs-native/source_rocks/lyaml-6.2.3-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs-native/source_rocks/lyaml-6.2.3-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/.gitignore: -------------------------------------------------------------------------------- 1 | /*.rock 2 | !/*.src.rock 3 | .*.sw? 4 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi8:8.5 2 | 3 | RUN sed -i s/enabled=./enabled=0/g /etc/yum/pluginconf.d/subscription-manager.conf 4 | 5 | RUN yum upgrade -y \ 6 | && dnf install -y 'dnf-command(config-manager)' 7 | RUN yum config-manager --add-repo http://packages.dev.3sca.net/dev_packages_3sca_net.repo 8 | RUN dnf --disablerepo=epel install -y luarocks 9 | RUN yum install -y rpm-build redhat-rpm-config 10 | 11 | RUN yum localinstall -y https://rpmfind.net/linux/centos/8-stream/AppStream/x86_64/os/Packages/rpmdevtools-8.10-8.el8.noarch.rpm 12 | 13 | RUN mkdir -p /root/rpmbuild/SOURCES/ 14 | 15 | 16 | COPY . /opt/data/ 17 | RUN cp /opt/data/licenses.xml /root/rpmbuild/SOURCES/ 18 | RUN cp /opt/data/*.rock /root/rpmbuild/SOURCES/ 19 | # RUN rm /root/rpmbuild/SOURCES/lua-rover-scm-1.src.rock 20 | RUN spectool -g -R /opt/data/*.spec 21 | RUN rpmbuild -ba /opt/data/*.spec 22 | RUN rpm -i /root/rpmbuild/RPMS/noarch/*.rpm 23 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/argparse-0.6.0-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/argparse-0.6.0-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/date-2.2-2.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/date-2.2-2.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/inspect-3.1.1-0.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/inspect-3.1.1-0.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/jsonschema-0.8-0.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/jsonschema-0.8-0.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/liquid-0.2.0-2.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/liquid-0.2.0-2.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-env-0.4.0-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-env-0.4.0-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-execvp-0.1.1-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-execvp-0.1.1-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-http-0.17.1-0.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-http-0.17.1-0.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-ipmatcher-0.6.1-0.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-ipmatcher-0.6.1-0.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-iputils-0.3.0-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-iputils-0.3.0-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-jit-uuid-0.0.7-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-jit-uuid-0.0.7-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-jwt-0.2.3-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-jwt-0.2.3-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-openssl-1.5.1-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-openssl-1.5.1-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-url-0.3.5-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-resty-url-0.3.5-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-rover-scm-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/lua-rover-scm-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/net-url-0.9-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/net-url-0.9-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/nginx-lua-prometheus-0.20181120-2.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/nginx-lua-prometheus-0.20181120-2.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/penlight-1.13.1-1.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/penlight-1.13.1-1.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/gateway-rockspecs/source_rocks/router-2.1-0.src.rock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/gateway-rockspecs/source_rocks/router-2.1-0.src.rock -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/COPYING: -------------------------------------------------------------------------------- 1 | PCRE LICENCE 2 | 3 | Please see the file LICENCE in the PCRE distribution for licensing details. 4 | 5 | End 6 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/ChangeLog -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/Detrail: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # This is a script for removing trailing whitespace from lines in files that 4 | # are listed on the command line. 5 | 6 | # This subroutine does the work for one file. 7 | 8 | sub detrail { 9 | my($file) = $_[0]; 10 | my($changed) = 0; 11 | open(IN, "$file") || die "Can't open $file for input"; 12 | @lines = ; 13 | close(IN); 14 | foreach (@lines) 15 | { 16 | if (/\s+\n$/) 17 | { 18 | s/\s+\n$/\n/; 19 | $changed = 1; 20 | } 21 | } 22 | if ($changed) 23 | { 24 | open(OUT, ">$file") || die "Can't open $file for output"; 25 | print OUT @lines; 26 | close(OUT); 27 | } 28 | } 29 | 30 | # This is the main program 31 | 32 | $, = ""; # Output field separator 33 | for ($i = 0; $i < @ARGV; $i++) { &detrail($ARGV[$i]); } 34 | 35 | # End 36 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/NON-UNIX-USE: -------------------------------------------------------------------------------- 1 | Compiling PCRE on non-Unix systems 2 | ---------------------------------- 3 | 4 | This has been renamed to better reflect its contents. Please see the file 5 | NON-AUTOTOOLS-BUILD for details of how to build PCRE without using autotools. 6 | 7 | #### 8 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/cmake/FindEditline.cmake: -------------------------------------------------------------------------------- 1 | # Modified from FindReadline.cmake (PH Feb 2012) 2 | 3 | if(EDITLINE_INCLUDE_DIR AND EDITLINE_LIBRARY AND NCURSES_LIBRARY) 4 | set(EDITLINE_FOUND TRUE) 5 | else(EDITLINE_INCLUDE_DIR AND EDITLINE_LIBRARY AND NCURSES_LIBRARY) 6 | FIND_PATH(EDITLINE_INCLUDE_DIR readline.h 7 | /usr/include/editline 8 | /usr/include/edit/readline 9 | /usr/include/readline 10 | ) 11 | 12 | FIND_LIBRARY(EDITLINE_LIBRARY NAMES edit) 13 | include(FindPackageHandleStandardArgs) 14 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Editline DEFAULT_MSG EDITLINE_INCLUDE_DIR EDITLINE_LIBRARY ) 15 | 16 | MARK_AS_ADVANCED(EDITLINE_INCLUDE_DIR EDITLINE_LIBRARY) 17 | endif(EDITLINE_INCLUDE_DIR AND EDITLINE_LIBRARY AND NCURSES_LIBRARY) 18 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/doc/pcre_free_study.3: -------------------------------------------------------------------------------- 1 | .TH PCRE_FREE_STUDY 3 "24 June 2012" "PCRE 8.30" 2 | .SH NAME 3 | PCRE - Perl-compatible regular expressions 4 | .SH SYNOPSIS 5 | .rs 6 | .sp 7 | .B #include 8 | .PP 9 | .SM 10 | .B void pcre_free_study(pcre_extra *\fIextra\fP); 11 | .PP 12 | .B void pcre16_free_study(pcre16_extra *\fIextra\fP); 13 | .PP 14 | .B void pcre32_free_study(pcre32_extra *\fIextra\fP); 15 | . 16 | .SH DESCRIPTION 17 | .rs 18 | .sp 19 | This function is used to free the memory used for the data generated by a call 20 | to \fBpcre[16|32]_study()\fP when it is no longer needed. The argument must be the 21 | result of such a call. 22 | .P 23 | There is a complete description of the PCRE native API in the 24 | .\" HREF 25 | \fBpcreapi\fP 26 | .\" 27 | page and a description of the POSIX API in the 28 | .\" HREF 29 | \fBpcreposix\fP 30 | .\" 31 | page. 32 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/doc/pcre_free_substring.3: -------------------------------------------------------------------------------- 1 | .TH PCRE_FREE_SUBSTRING 3 "24 June 2012" "PCRE 8.30" 2 | .SH NAME 3 | PCRE - Perl-compatible regular expressions 4 | .SH SYNOPSIS 5 | .rs 6 | .sp 7 | .B #include 8 | .PP 9 | .SM 10 | .B void pcre_free_substring(const char *\fIstringptr\fP); 11 | .PP 12 | .B void pcre16_free_substring(PCRE_SPTR16 \fIstringptr\fP); 13 | .PP 14 | .B void pcre32_free_substring(PCRE_SPTR32 \fIstringptr\fP); 15 | . 16 | .SH DESCRIPTION 17 | .rs 18 | .sp 19 | This is a convenience function for freeing the store obtained by a previous 20 | call to \fBpcre[16|32]_get_substring()\fP or \fBpcre[16|32]_get_named_substring()\fP. 21 | Its only argument is a pointer to the string. 22 | .P 23 | There is a complete description of the PCRE native API in the 24 | .\" HREF 25 | \fBpcreapi\fP 26 | .\" 27 | page and a description of the POSIX API in the 28 | .\" HREF 29 | \fBpcreposix\fP 30 | .\" 31 | page. 32 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/doc/pcre_free_substring_list.3: -------------------------------------------------------------------------------- 1 | .TH PCRE_FREE_SUBSTRING_LIST 3 "24 June 2012" "PCRE 8.30" 2 | .SH NAME 3 | PCRE - Perl-compatible regular expressions 4 | .SH SYNOPSIS 5 | .rs 6 | .sp 7 | .B #include 8 | .PP 9 | .SM 10 | .B void pcre_free_substring_list(const char **\fIstringptr\fP); 11 | .PP 12 | .B void pcre16_free_substring_list(PCRE_SPTR16 *\fIstringptr\fP); 13 | .PP 14 | .B void pcre32_free_substring_list(PCRE_SPTR32 *\fIstringptr\fP); 15 | . 16 | .SH DESCRIPTION 17 | .rs 18 | .sp 19 | This is a convenience function for freeing the store obtained by a previous 20 | call to \fBpcre[16|32]_get_substring_list()\fP. Its only argument is a pointer to 21 | the list of string pointers. 22 | .P 23 | There is a complete description of the PCRE native API in the 24 | .\" HREF 25 | \fBpcreapi\fP 26 | .\" 27 | page and a description of the POSIX API in the 28 | .\" HREF 29 | \fBpcreposix\fP 30 | .\" 31 | page. 32 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/doc/pcre_jit_stack_free.3: -------------------------------------------------------------------------------- 1 | .TH PCRE_JIT_STACK_FREE 3 "24 June 2012" "PCRE 8.30" 2 | .SH NAME 3 | PCRE - Perl-compatible regular expressions 4 | .SH SYNOPSIS 5 | .rs 6 | .sp 7 | .B #include 8 | .PP 9 | .SM 10 | .B void pcre_jit_stack_free(pcre_jit_stack *\fIstack\fP); 11 | .PP 12 | .B void pcre16_jit_stack_free(pcre16_jit_stack *\fIstack\fP); 13 | .PP 14 | .B void pcre32_jit_stack_free(pcre32_jit_stack *\fIstack\fP); 15 | . 16 | .SH DESCRIPTION 17 | .rs 18 | .sp 19 | This function is used to free a JIT stack that was created by 20 | \fBpcre[16|32]_jit_stack_alloc()\fP when it is no longer needed. For more details, 21 | see the 22 | .\" HREF 23 | \fBpcrejit\fP 24 | .\" 25 | page. 26 | .P 27 | There is a complete description of the PCRE native API in the 28 | .\" HREF 29 | \fBpcreapi\fP 30 | .\" 31 | page and a description of the POSIX API in the 32 | .\" HREF 33 | \fBpcreposix\fP 34 | .\" 35 | page. 36 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/doc/pcre_version.3: -------------------------------------------------------------------------------- 1 | .TH PCRE_VERSION 3 "24 June 2012" "PCRE 8.30" 2 | .SH NAME 3 | PCRE - Perl-compatible regular expressions 4 | .SH SYNOPSIS 5 | .rs 6 | .sp 7 | .B #include 8 | .PP 9 | .SM 10 | .B const char *pcre_version(void); 11 | .PP 12 | .B const char *pcre16_version(void); 13 | .PP 14 | .B const char *pcre32_version(void); 15 | . 16 | .SH DESCRIPTION 17 | .rs 18 | .sp 19 | This function (even in the 16-bit and 32-bit libraries) returns a 20 | zero-terminated, 8-bit character string that gives the version number of the 21 | PCRE library and the date of its release. 22 | .P 23 | There is a complete description of the PCRE native API in the 24 | .\" HREF 25 | \fBpcreapi\fP 26 | .\" 27 | page and a description of the POSIX API in the 28 | .\" HREF 29 | \fBpcreposix\fP 30 | .\" 31 | page. 32 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/libpcre.pc.in: -------------------------------------------------------------------------------- 1 | # Package Information for pkg-config 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: libpcre 9 | Description: PCRE - Perl compatible regular expressions C library with 8 bit character support 10 | Version: @PACKAGE_VERSION@ 11 | Libs: -L${libdir} -lpcre 12 | Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ 13 | Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ 14 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/libpcre16.pc.in: -------------------------------------------------------------------------------- 1 | # Package Information for pkg-config 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: libpcre16 9 | Description: PCRE - Perl compatible regular expressions C library with 16 bit character support 10 | Version: @PACKAGE_VERSION@ 11 | Libs: -L${libdir} -lpcre16 12 | Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ 13 | Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ 14 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/libpcre32.pc.in: -------------------------------------------------------------------------------- 1 | # Package Information for pkg-config 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: libpcre32 9 | Description: PCRE - Perl compatible regular expressions C library with 32 bit character support 10 | Version: @PACKAGE_VERSION@ 11 | Libs: -L${libdir} -lpcre32 12 | Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ 13 | Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ 14 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/libpcrecpp.pc.in: -------------------------------------------------------------------------------- 1 | # Package Information for pkg-config 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: libpcrecpp 9 | Description: PCRECPP - C++ wrapper for PCRE 10 | Version: @PACKAGE_VERSION@ 11 | Libs: -L${libdir} -lpcre -lpcrecpp 12 | Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ 13 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/libpcreposix.pc.in: -------------------------------------------------------------------------------- 1 | # Package Information for pkg-config 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: libpcreposix 9 | Description: PCREPosix - Posix compatible interface to libpcre 10 | Version: @PACKAGE_VERSION@ 11 | Libs: -L${libdir} -lpcreposix 12 | Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ 13 | Requires.private: libpcre 14 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2011-2018 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 4221 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.6.42-b88ce]) 16 | m4_define([LT_PACKAGE_REVISION], [2.4.6.42]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.6.42-b88ce' 20 | macro_revision='2.4.6.42' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/makevp_c.txt: -------------------------------------------------------------------------------- 1 | pcre_byte_order.c 2 | pcre_chartables.c 3 | pcre_compile.c 4 | pcre_config.c 5 | pcre_dfa_exec.c 6 | pcre_exec.c 7 | pcre_fullinfo.c 8 | pcre_get.c 9 | pcre_globals.c 10 | pcre_jit_compile.c 11 | pcre_maketables.c 12 | pcre_newline.c 13 | pcre_ord2utf8.c 14 | pcre_refcount.c 15 | pcre_string_utils.c 16 | pcre_study.c 17 | pcre_tables.c 18 | pcre_ucd.c 19 | pcre_valid_utf8.c 20 | pcre_version.c 21 | pcre_xclass.c 22 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/makevp_l.txt: -------------------------------------------------------------------------------- 1 | +pcre_byte_order.obj & 2 | +pcre_chartables.obj & 3 | +pcre_compile.obj & 4 | +pcre_config.obj & 5 | +pcre_dfa_exec.obj & 6 | +pcre_exec.obj & 7 | +pcre_fullinfo.obj & 8 | +pcre_get.obj & 9 | +pcre_globals.obj & 10 | +pcre_jit_compile.obj & 11 | +pcre_maketables.obj & 12 | +pcre_newline.obj & 13 | +pcre_ord2utf8.obj & 14 | +pcre_refcount.obj & 15 | +pcre_string_utils.obj & 16 | +pcre_study.obj & 17 | +pcre_tables.obj & 18 | +pcre_ucd.obj & 19 | +pcre_valid_utf8.obj & 20 | +pcre_version.obj & 21 | +pcre_xclass.obj 22 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepbinary: -------------------------------------------------------------------------------- 1 | The quick brown fx jumps over the lazy dog. 2 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepfilelist: -------------------------------------------------------------------------------- 1 | testdata/grepinputv 2 | 3 | testdata/grepinputx 4 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepinput3: -------------------------------------------------------------------------------- 1 | triple: t1_txt s1_tag s_txt p_tag p_txt o_tag o_txt 2 | 3 | triple: t2_txt s1_tag s_txt p_tag p_txt o_tag 4 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 5 | 6 | triple: t3_txt s2_tag s_txt p_tag p_txt o_tag o_txt 7 | 8 | triple: t4_txt s1_tag s_txt p_tag p_txt o_tag o_txt 9 | 10 | triple: t5_txt s1_tag s_txt p_tag p_txt o_tag 11 | o_txt 12 | 13 | triple: t6_txt s2_tag s_txt p_tag p_txt o_tag o_txt 14 | 15 | triple: t7_txt s1_tag s_txt p_tag p_txt o_tag o_txt 16 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepinput8: -------------------------------------------------------------------------------- 1 | X one 2 | X two X three X four X five 3 | X six 4 | X seven…X eight
X nine
X ten 5 | 6 | Before 111 7 | Before 222
Before 333…Match 8 | After 111 9 | After 222
After 333 10 | And so on and so on 11 | And so on and so on 12 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepinputv: -------------------------------------------------------------------------------- 1 | The quick brown 2 | fox jumps 3 | over the lazy dog. 4 | This time it jumps and jumps and jumps. 5 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepinputx: -------------------------------------------------------------------------------- 1 | This is a second file of input for the pcregrep tests. 2 | 3 | Here is the pattern again. 4 | 5 | Pattern 6 | That time it was on a line by itself. 7 | 8 | To pat or not to pat, that is the question. 9 | 10 | complete pair 11 | of lines 12 | 13 | That was a complete pair 14 | of lines all by themselves. 15 | 16 | complete pair 17 | of lines 18 | 19 | And there they were again, to check line numbers. 20 | 21 | one 22 | two 23 | three 24 | four 25 | five 26 | six 27 | seven 28 | eight 29 | nine 30 | ten 31 | eleven 32 | twelve 33 | thirteen 34 | fourteen 35 | fifteen 36 | sixteen 37 | seventeen 38 | eighteen 39 | nineteen 40 | twenty 41 | 42 | This line contains pattern not on a line by itself. 43 | This is the last line of this file. 44 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/greplist: -------------------------------------------------------------------------------- 1 | This is a file of patterns for testing the -f option. Don't include any blank 2 | lines because they will match everything! This is no longer true, so have one. 3 | 4 | pattern 5 | line by itself 6 | 7 | End of the list of patterns. 8 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepoutput8: -------------------------------------------------------------------------------- 1 | ---------------------------- Test U1 ------------------------------ 2 | 1:X one 3 | 2:X two 3:X three 4:X four 5:X five 4 | 6:X six 5 | 7:X seven…8:X eight
9:X nine
10:X ten 6 | RC=0 7 | ---------------------------- Test U2 ------------------------------ 8 | 12-Before 111 9 | 13-Before 222
14-Before 333…15:Match 10 | 16-After 111 11 | 17-After 222
18-After 333 12 | RC=0 13 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/grepoutputN: -------------------------------------------------------------------------------- 1 | ---------------------------- Test N1 ------------------------------ 2 | 1:abc 2:def ---------------------------- Test N2 ------------------------------ 3 | 1:abc def 4 | 2:ghi 5 | jkl---------------------------- Test N3 ------------------------------ 6 | 2:def 3: 7 | ghi 8 | jkl---------------------------- Test N4 ------------------------------ 9 | 2:ghi 10 | jkl---------------------------- Test N5 ------------------------------ 11 | 1:abc 2:def 12 | 3:ghi 13 | 4:jkl---------------------------- Test N6 ------------------------------ 14 | 1:abc 2:def 15 | 3:ghi 16 | 4:jkl -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/greppatN4: -------------------------------------------------------------------------------- 1 | xxx 2 | jkl -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16BE-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16BE-1 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16BE-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16BE-2 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16LE-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16LE-1 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16LE-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved16LE-2 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32BE-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32BE-1 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32BE-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32BE-2 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32LE-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32LE-1 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32LE-2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved32LE-2 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/saved8 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput1 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput13: -------------------------------------------------------------------------------- 1 | /-- This test is run only when JIT support is not available. It checks that an 2 | attempt to use it has the expected behaviour. It also tests things that 3 | are different without JIT. --/ 4 | 5 | /abc/S+I 6 | 7 | /a*/SI 8 | 9 | /-- End of testinput13 --/ 10 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput15: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput15 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput18: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput18 -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput20: -------------------------------------------------------------------------------- 1 | /-- These DFA tests are for the handling of characters greater than 255 in 2 | 16- or 32-bit, non-UTF mode. --/ 3 | 4 | /^\x{ffff}+/i 5 | \x{ffff} 6 | 7 | /^\x{ffff}?/i 8 | \x{ffff} 9 | 10 | /^\x{ffff}*/i 11 | \x{ffff} 12 | 13 | /^\x{ffff}{3}/i 14 | \x{ffff}\x{ffff}\x{ffff} 15 | 16 | /^\x{ffff}{0,3}/i 17 | \x{ffff} 18 | 19 | /-- End of testinput20 --/ 20 | -------------------------------------------------------------------------------- /dependencies/rpm-specs/openresty-pcre/sources/pcre-8.44/testdata/testinput21: -------------------------------------------------------------------------------- 1 | /-- Tests for reloading pre-compiled patterns. The first one gives an error 2 | right away, and can be any old pattern compiled in 8-bit mode ("abc" is 3 | typical). The others require the link size to be 2. */x 4 | 5 | (?:[AaLl]+)[^xX-]*?)(?P[\x{150}-\x{250}\x{300}]| 9 | [^\x{800}aAs-uS-U\x{d800}-\x{dfff}])++[^#\b\x{500}\x{1000}]{3,5}$ 10 | /x 11 | 12 | In 16-bit mode with options: S>testdata/saved16LE-1 13 | FS>testdata/saved16BE-1 14 | In 32-bit mode with options: S>testdata/saved32LE-1 15 | FS>testdata/saved32BE-1 16 | --%x 17 | 18 | [aZ\x{400}-\x{10ffff}]{4,} 5 | [\x{f123}\x{10039}\x{20000}-\x{21234}]?| 6 | [A-Cx-z\x{100000}-\x{1000a7}\x{101234}]) 7 | (?[^az])/x 8 | 9 | In 16-bit mode with options: S8>testdata/saved16LE-2 10 | FS8>testdata/saved16BE-2 11 | In 32-bit mode with options: S8>testdata/saved32LE-2 12 | FS8>testdata/saved32BE-2 13 | --%8x 14 | 15 | /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access upstream powered with TLS 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | -------------------------------------------------------------------------------- /dev-environments/http-proxy-plain-http-upstream/tinyproxy.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mirror.gcr.io/library/alpine:3 2 | 3 | LABEL summary="Forward proxy based on tinyproxy for development purposes" \ 4 | description="Forward proxy based on tinyproxy for development purposes" \ 5 | io.k8s.description="Forward proxy based on tinyproxy for development purposes" \ 6 | io.k8s.display-name="Forward Proxy (Tinyproxy)" \ 7 | io.openshift.tags="tinyproxy, proxy" \ 8 | maintainer="3scale-engineering@redhat.com" 9 | 10 | RUN apk --no-cache add tinyproxy 11 | ENTRYPOINT ["/usr/bin/tinyproxy"] 12 | CMD ["-d"] 13 | -------------------------------------------------------------------------------- /dev-environments/https-proxy-upstream-tlsv1.3/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /usr/bin/env bash -o pipefail 2 | .SHELLFLAGS = -ec 3 | .DEFAULT_GOAL := gateway 4 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 6 | DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access upstream powered with TLS 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | 15 | certs: 16 | $(MAKE) clean -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 17 | $(MAKE) ca -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 18 | $(MAKE) clientcerts -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile DOMAIN=example.com 19 | -------------------------------------------------------------------------------- /dev-environments/https-proxy-upstream-tlsv1.3/cert/Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | - rm *.crt *.key *.pem *.csr *.srl 3 | 4 | ca: 5 | openssl genrsa -out rootCA.key 2048 6 | openssl req -batch -new -x509 -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem 7 | 8 | clientcerts: 9 | openssl req -subj '/CN=$(DOMAIN)' -newkey rsa:4096 -nodes \ 10 | -sha256 \ 11 | -days 3650 \ 12 | -keyout $(DOMAIN).key \ 13 | -out $(DOMAIN).csr 14 | chmod +r $(DOMAIN).key 15 | openssl x509 -req -in $(DOMAIN).csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out $(DOMAIN).crt -days 500 -sha256 16 | cat $(DOMAIN).key $(DOMAIN).crt >$(DOMAIN).pem 17 | -------------------------------------------------------------------------------- /dev-environments/https-proxy-upstream-tlsv1.3/tinyproxy.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mirror.gcr.io/library/alpine:3 2 | 3 | LABEL summary="Forward proxy based on tinyproxy for development purposes" \ 4 | description="Forward proxy based on tinyproxy for development purposes" \ 5 | io.k8s.description="Forward proxy based on tinyproxy for development purposes" \ 6 | io.k8s.display-name="Forward Proxy (Tinyproxy)" \ 7 | io.openshift.tags="tinyproxy, proxy" \ 8 | maintainer="3scale-engineering@redhat.com" 9 | 10 | RUN apk --no-cache add tinyproxy 11 | ENTRYPOINT ["/usr/bin/tinyproxy"] 12 | CMD ["-d"] 13 | -------------------------------------------------------------------------------- /dev-environments/listen-tls/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /usr/bin/env bash -o pipefail 2 | .SHELLFLAGS = -ec 3 | .DEFAULT_GOAL := gateway 4 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 6 | DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access upstream powered with TLS 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | 15 | certs: 16 | $(MAKE) clean -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 17 | $(MAKE) ca -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 18 | $(MAKE) clientcerts -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile DOMAIN=example.com 19 | -------------------------------------------------------------------------------- /dev-environments/listen-tls/README.md: -------------------------------------------------------------------------------- 1 | # Making APIcast listen on HTTPS 2 | 3 | ## Create the SSL Certificates 4 | 5 | ```sh 6 | make certs 7 | ``` 8 | 9 | ## Run the gateway 10 | 11 | Running local `apicast-test` docker image 12 | 13 | ```sh 14 | make gateway 15 | ``` 16 | 17 | Running custom apicast image 18 | 19 | ```sh 20 | make gateway IMAGE_NAME=quay.io/3scale/apicast:latest 21 | ``` 22 | 23 | ## Testing 24 | 25 | ```sh 26 | curl --resolve example.com:8443:127.0.0.1 -v --cacert cert/rootCA.pem "https://example.com:8443/?user_key=123" 27 | ``` 28 | 29 | ## Clean env 30 | 31 | ```sh 32 | make clean 33 | ``` 34 | -------------------------------------------------------------------------------- /dev-environments/listen-tls/apicast-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "id": "1", 5 | "backend_version": "1", 6 | "proxy": { 7 | "hosts": ["example.com"], 8 | "api_backend": "http://one.upstream/get", 9 | "backend": { 10 | "endpoint": "http://127.0.0.1:8081", 11 | "host": "backend" 12 | }, 13 | "policy_chain": [ 14 | { 15 | "name": "apicast.policy.apicast" 16 | } 17 | ], 18 | "proxy_rules": [ 19 | { 20 | "http_method": "GET", 21 | "pattern": "/", 22 | "metric_system_name": "hits", 23 | "delta": 1, 24 | "parameters": [], 25 | "querystring_parameters": {} 26 | } 27 | ] 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /dev-environments/listen-tls/cert/Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | - rm *.crt *.key *.pem *.csr 3 | 4 | ca: 5 | openssl genrsa -out rootCA.key 2048 6 | openssl req -batch -new -x509 -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem 7 | 8 | clientcerts: 9 | openssl req -subj '/CN=$(DOMAIN)' -newkey rsa:4096 -nodes \ 10 | -sha256 \ 11 | -days 3650 \ 12 | -keyout $(DOMAIN).key \ 13 | -out $(DOMAIN).csr 14 | chmod +r $(DOMAIN).key 15 | openssl x509 -req -in $(DOMAIN).csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out $(DOMAIN).crt -days 500 -sha256 16 | -------------------------------------------------------------------------------- /dev-environments/mtls/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #This entrypoint is responsible for leaving the OSCP running to accept requests 4 | openssl ocsp -url http://0.0.0.0:2560 -text -index /cert/index.txt -CA /cert/ca-chain.cert.pem -rkey /cert/ocsp.example.com.key.pem -rsigner /cert/ocsp.example.com.cert.pem 5 | -------------------------------------------------------------------------------- /dev-environments/mtls/ocsp.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mirror.gcr.io/library/alpine:3 2 | 3 | RUN apk --no-cache add openssl 4 | 5 | COPY cert /cert 6 | 7 | COPY docker-entrypoint.sh docker-entrypoint.sh 8 | EXPOSE 2560 9 | ENTRYPOINT [ "/bin/sh", "docker-entrypoint.sh" ] 10 | -------------------------------------------------------------------------------- /dev-environments/opentelemetry-instrumented-gateway/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /usr/bin/env bash -o pipefail 2 | .SHELLFLAGS = -ec 3 | .DEFAULT_GOAL := gateway 4 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 6 | DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access plain HTTP 1.1 upstream 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | -------------------------------------------------------------------------------- /dev-environments/opentelemetry-instrumented-gateway/otel.toml: -------------------------------------------------------------------------------- 1 | exporter = "otlp" 2 | processor = "simple" 3 | 4 | [exporters.otlp] 5 | # Alternatively the OTEL_EXPORTER_OTLP_ENDPOINT environment variable can also be used. 6 | host = "jaeger" 7 | port = 4317 8 | # Optional: enable SSL, for endpoints that support it 9 | # use_ssl = true 10 | # Optional: set a filesystem path to a pem file to be used for SSL encryption 11 | # (when use_ssl = true) 12 | # ssl_cert_path = "/path/to/cert.pem" 13 | 14 | [processors.batch] 15 | max_queue_size = 2048 16 | schedule_delay_millis = 5000 17 | max_export_batch_size = 512 18 | 19 | [service] 20 | name = "apicast" # Opentelemetry resource name 21 | -------------------------------------------------------------------------------- /dev-environments/plain-http-upstream/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /usr/bin/env bash -o pipefail 2 | .SHELLFLAGS = -ec 3 | .DEFAULT_GOAL := gateway 4 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 6 | DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access plain HTTP 1.1 upstream 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | -------------------------------------------------------------------------------- /dev-environments/upstream-tlsv1.3/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /usr/bin/env bash -o pipefail 2 | .SHELLFLAGS = -ec 3 | .DEFAULT_GOAL := gateway 4 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 5 | WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 6 | DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") 7 | 8 | gateway: ## run gateway configured to access upstream powered with TLS 9 | $(DOCKER) compose -f docker-compose.yml up --attach gateway 10 | 11 | clean: 12 | $(DOCKER) compose down --volumes --remove-orphans 13 | $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans 14 | 15 | certs: 16 | $(MAKE) clean -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 17 | $(MAKE) ca -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile 18 | $(MAKE) clientcerts -C $(WORKDIR)/cert -f $(WORKDIR)/cert/Makefile DOMAIN=example.com 19 | -------------------------------------------------------------------------------- /dev-environments/upstream-tlsv1.3/cert/Makefile: -------------------------------------------------------------------------------- 1 | clean: 2 | - rm *.crt *.key *.pem *.csr 3 | 4 | ca: 5 | openssl genrsa -out rootCA.key 2048 6 | openssl req -batch -new -x509 -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem 7 | 8 | clientcerts: 9 | openssl req -subj '/CN=$(DOMAIN)' -newkey rsa:4096 -nodes \ 10 | -sha256 \ 11 | -days 3650 \ 12 | -keyout $(DOMAIN).key \ 13 | -out $(DOMAIN).csr 14 | chmod +r $(DOMAIN).key 15 | openssl x509 -req -in $(DOMAIN).csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out $(DOMAIN).crt -days 500 -sha256 16 | cat $(DOMAIN).key $(DOMAIN).crt >$(DOMAIN).pem 17 | -------------------------------------------------------------------------------- /doc/config.ld: -------------------------------------------------------------------------------- 1 | file = { 2 | '../gateway/src/apicast', 3 | '../gateway/src/resty', 4 | } 5 | dir = '../doc/lua' 6 | project = 'APIcast' 7 | title = 'NGINX based API gateway used to integrate your internal and external API services with 3scale’s API Management Platform' 8 | merge = true 9 | format = 'markdown' 10 | not_luadoc = true 11 | 12 | new_type("http","HTTP") 13 | new_type("http_ng.backend","http_ng.backend") 14 | -------------------------------------------------------------------------------- /doc/policy_tutorial/apicast/examples/configuration/hello_world_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "proxy": { 5 | "policy_chain": [ 6 | { 7 | "name": "hello_world", 8 | "version": "builtin", 9 | "configuration": { 10 | "overwrite": true, 11 | "secret": "mysecret" 12 | } 13 | }, 14 | { 15 | "name": "apicast.policy.upstream", 16 | "configuration": { 17 | "rules": [ 18 | { 19 | "regex": "/", 20 | "url": "http://echo:8081" 21 | } 22 | ] 23 | } 24 | } 25 | ] 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /doc/policy_tutorial/apicast/gateway/src/apicast/policy/hello_world/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "hello_world", 4 | "summary": "Parameter converter and secret checker", 5 | "description": [ 6 | "Modifies HTTP query parameters in a request to HTTP headers. And checks the existence of the secret header." 7 | ], 8 | "version": "builtin", 9 | "configuration": { 10 | "type": "object", 11 | "properties": { 12 | "overwrite": { 13 | "description": "Overwrite flag used to indicate whether or not an existing header must be overwritten by this policy. The default is true.", 14 | "type": "boolean" 15 | }, 16 | "secret": { 17 | "description": "The additional static secret used for verifying the request.", 18 | "type": "string" 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /doc/policy_tutorial/apicast/gateway/src/apicast/policy/hello_world/init.lua: -------------------------------------------------------------------------------- 1 | return require('hello_world') 2 | -------------------------------------------------------------------------------- /doc/policy_tutorial/img/apicast-dev-container-mount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/doc/policy_tutorial/img/apicast-dev-container-mount.png -------------------------------------------------------------------------------- /doc/policy_tutorial/img/nginx-phases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/doc/policy_tutorial/img/nginx-phases.png -------------------------------------------------------------------------------- /doc/policy_tutorial/img/policy_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/doc/policy_tutorial/img/policy_layout.png -------------------------------------------------------------------------------- /docker-compose-devel-volmount-default.yml: -------------------------------------------------------------------------------- 1 | version: '2.2' 2 | services: 3 | development: 4 | privileged: true 5 | pid: "host" 6 | volumes: 7 | - .:/opt/app-root/src/ 8 | - /sys/kernel/debug:/sys/kernel/debug 9 | - /lib/modules:/lib/module 10 | -------------------------------------------------------------------------------- /docker-compose-devel-volmount-mac.yml: -------------------------------------------------------------------------------- 1 | version: '2.2' 2 | services: 3 | development: 4 | volumes: 5 | - .:/opt/app-root/src/:cached 6 | -------------------------------------------------------------------------------- /docker-compose-devel.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '2.2' 3 | services: 4 | development: 5 | image: ${IMAGE:-quay.io/3scale/apicast-ci:openresty-1.21.4-2} 6 | platform: "linux/amd64" 7 | depends_on: 8 | - redis 9 | working_dir: /opt/app-root/src/ 10 | command: cat 11 | tty: true 12 | init: true 13 | environment: 14 | EDITOR: vi 15 | TEST_NGINX_REDIS_HOST: redis 16 | TEST_NGINX_BINARY: openresty 17 | PROJECT_PATH: /opt/app-root/src 18 | TEST_NGINX_APICAST_PATH: /opt/app-root/src/gateway 19 | ROVER: /usr/local/openresty/luajit/bin/rover 20 | HOME: /opt/app-root/src/ 21 | # https://github.com/jenkinsci/docker/issues/519#issuecomment-313052325 22 | GIT_COMMITTER_NAME: ${GIT_COMMITTER_NAME:-${USER}} 23 | GIT_COMMITTER_EMAIL: ${GIT_COMMITTER_EMAIL:-""} 24 | redis: 25 | image: mirror.gcr.io/library/redis 26 | -------------------------------------------------------------------------------- /docker-compose.prove.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | services: 3 | prove: 4 | image: ${IMAGE_NAME:-apicast-test} 5 | environment: 6 | HOME: /opt/app-root/src/ 7 | TEST_NGINX_BINARY: openresty 8 | TEST_NGINX_REDIS_HOST: redis 9 | command: "sh -ec '$$TEST_NGINX_BINARY -V; cd ; make dependencies; make prove; exit $$?'" 10 | depends_on: 11 | - redis 12 | redis: 13 | image: mirror.gcr.io/library/redis 14 | -------------------------------------------------------------------------------- /examples/configuration/local.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1234567890987, 3 | "provider_key": "provider-key", 4 | "services": [ 5 | { 6 | "id": 654321, 7 | "backend_version": "1", 8 | "proxy": { 9 | "api_backend": "http://127.0.0.1:8081", 10 | "hostname_rewrite": "echo", 11 | "hosts": [ 12 | "localhost", 13 | "127.0.0.1" 14 | ], 15 | "backend": { 16 | "endpoint": "http://127.0.0.1:8081", 17 | "host": "backend" 18 | }, 19 | "proxy_rules": [ 20 | { 21 | "http_method": "GET", 22 | "pattern": "/", 23 | "metric_system_name": "hits", 24 | "delta": 1, 25 | "parameters": [], 26 | "querystring_parameters": {} 27 | } 28 | ] 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /examples/custom-config/README.md: -------------------------------------------------------------------------------- 1 | # Custom Config 2 | 3 | Sometimes you might require injecting custom nginx configuration into the gateway for customization. For example to add another server block to handle some routing. This **does not override existing configuration**. So the gateway will work as usual + your extra configuration. 4 | 5 | That can be done very easily just with mounting a volume inside `sites.d` folder in the container: 6 | 7 | ```shell 8 | docker run --publish 8080:8080 --volume $(pwd)/echo.conf:/opt/app/sites.d/echo.conf --env THREESCALE_PORTAL_ENDPOINT=http://portal.example.com quay.io/3scale/apicast:master 9 | ``` 10 | 11 | And then try a request: 12 | 13 | ```shell 14 | curl localhost:8080 -H 'Host: echo' -X 'POST' 15 | ``` 16 | 17 | And you should see: 18 | 19 | ``` 20 | POST / HTTP/1.1 21 | Host: echo 22 | User-Agent: curl/7.49.1 23 | Accept: */* 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /examples/custom-config/echo.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8080; 3 | server_name echo; 4 | 5 | location / { 6 | echo $echo_client_request_headers; 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /examples/custom-module/verbose.lua: -------------------------------------------------------------------------------- 1 | local apicast = require('apicast').new() 2 | 3 | local _M = { _VERSION = '0.0' } 4 | local mt = { __index = setmetatable(_M, { __index = apicast }) } 5 | 6 | function _M.new() 7 | return setmetatable({}, mt) 8 | end 9 | 10 | function _M.log() 11 | ngx.log(ngx.WARN, 12 | 'upstream response time: ', ngx.var.upstream_response_time, ' ', 13 | 'upstream connect time: ', ngx.var.upstream_connect_time) 14 | return apicast:log() 15 | end 16 | 17 | return _M 18 | -------------------------------------------------------------------------------- /examples/opentracing/apicast-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "backend_version": "1", 5 | "proxy": { 6 | "hosts": ["one"], 7 | "api_backend": "http://httpbin.org", 8 | "backend": { 9 | "endpoint": "http://127.0.0.1:8081", 10 | "host": "backend" 11 | }, 12 | "proxy_rules": [ 13 | { 14 | "http_method": "GET", 15 | "pattern": "/", 16 | "metric_system_name": "hits", 17 | "delta": 1, 18 | "parameters": [], 19 | "querystring_parameters": {} 20 | } 21 | ] 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /examples/opentracing/jaeger-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "service_name": "apicast", 3 | "disabled": false, 4 | "sampler": { 5 | "type": "const", 6 | "param": 1 7 | }, 8 | "reporter": { 9 | "queueSize": 100, 10 | "bufferFlushInterval": 10, 11 | "logSpans": false, 12 | "localAgentHostPort": "jaeger:6831" 13 | }, 14 | "headers": { 15 | "jaegerDebugHeader": "debug-id", 16 | "jaegerBaggageHeader": "baggage", 17 | "TraceContextHeaderName": "uber-trace-id", 18 | "traceBaggageHeaderPrefix": "testctx-" 19 | }, 20 | "baggage_restrictions": { 21 | "denyBaggageOnInitializationFailure": false, 22 | "hostPort": "127.0.0.1:5778", 23 | "refreshInterval": 60 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /examples/policies/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "proxy": { 5 | "policy_chain": [ 6 | { "name": "ngx-example", "version": "1.0.0", 7 | "configuration": { "set_header": [{"name": "Example", "value": "Value" }] } }, 8 | { "name": "apicast.policy.upstream", 9 | "configuration": { 10 | "rules": [{ 11 | "regex": "/", 12 | "url": "http://echo:8081" 13 | }] 14 | } 15 | } 16 | ] 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /examples/policies/ngx-example/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Ngx example policy", 4 | "summary": "Sets request headers", 5 | "description": 6 | ["This policy is meant to be just an example.", 7 | "It sets request headers based on the configuration.", 8 | "And prints a log entry for each header set. " ], 9 | "version": "1.0.0", 10 | "configuration": { 11 | "type": "object", 12 | "properties": { 13 | "set_header": { 14 | "type": "array", 15 | "items": { 16 | "type": "object", 17 | "properties": { 18 | "name": { 19 | "type": "string", 20 | "description": "HTTP header name" 21 | }, 22 | "value": { 23 | "type": "string", 24 | "description": "HTTP header value" 25 | } 26 | }, 27 | "required": ["name", "value"] 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/policies/ngx-example/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('ngx_example') 2 | -------------------------------------------------------------------------------- /examples/policies/ngx-example/1.0.0/ngx_example.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('Nginx Example', '1.0.0') 2 | 3 | local new = _M.new 4 | 5 | local ipairs = ipairs 6 | local insert = table.insert 7 | 8 | function _M.new(configuration) 9 | local self = new() 10 | 11 | local ops = {} 12 | 13 | local config = configuration or {} 14 | local set_header = config.set_header or {} 15 | 16 | for _, header in ipairs(set_header) do 17 | insert(ops, function() 18 | ngx.log(ngx.NOTICE, 'setting header: ', header.name, ' to: ', header.value) 19 | ngx.req.set_header(header.name, header.value) 20 | end) 21 | end 22 | 23 | self.ops = ops 24 | 25 | return self 26 | end 27 | 28 | function _M:rewrite() 29 | for _,op in ipairs(self.ops) do 30 | op() 31 | end 32 | end 33 | 34 | return _M 35 | -------------------------------------------------------------------------------- /examples/policies/rate_limit_configuration.lua: -------------------------------------------------------------------------------- 1 | local policy_chain = require('apicast.policy_chain').default() 2 | 3 | local rate_limit_policy = require('apicast.policy.rate_limit').new({ 4 | connection_limiters = { 5 | { 6 | key = {name = "limit1"}, 7 | conn = 20, 8 | burst = 10, 9 | delay = 0.5 10 | } 11 | }, 12 | leaky_bucket_limiters = { 13 | { 14 | key = {name = "limit2"}, 15 | rate = 18, 16 | burst = 9 17 | } 18 | }, 19 | fixed_window_limiters = { 20 | { 21 | key = {name = "limit3"}, 22 | count = 10, 23 | window = 10 24 | } 25 | }, 26 | redis_url = "redis://localhost:6379/1" 27 | }) 28 | 29 | policy_chain:insert(rate_limit_policy, 1) 30 | 31 | return { 32 | policy_chain = policy_chain 33 | } 34 | -------------------------------------------------------------------------------- /examples/policies/token_introspection_configuration.lua: -------------------------------------------------------------------------------- 1 | local policy_chain = require('apicast.policy_chain').default() 2 | 3 | local token_policy = require('apicast.policy.token_introspection').new({ 4 | auth_type = "client_id+client_secret", 5 | introspection_url = "http://localhost:8080/auth/realms/3scale/protocol/openid-connect/token/introspect", 6 | client_id = "YOUR_CLIENT_ID", 7 | client_secret = "YOUR_CLIENT_SECRET" 8 | }) 9 | 10 | policy_chain:insert(token_policy) 11 | 12 | return { 13 | policy_chain = policy_chain 14 | } 15 | 16 | -------------------------------------------------------------------------------- /examples/policy_chain/README.md: -------------------------------------------------------------------------------- 1 | # Configure Policy Chain 2 | 3 | Environment configuration can define the global policy chain. You can provide custom chain or insert policies to the default one. 4 | 5 | ## Using Echo Policy 6 | 7 | [Echo policy](../../gateway/src/apicast/policy/echo) accepts configuration option to terminate the request phase. See the example in [`configuration.lua`](./configuration.lua). 8 | 9 | You can start it as: 10 | 11 | ```shell 12 | ECHO_STATUS=202 bin/apicast --environment examples/policy_chain/configuration.lua 13 | ``` 14 | -------------------------------------------------------------------------------- /examples/policy_chain/configuration.lua: -------------------------------------------------------------------------------- 1 | local resty_env = require('resty.env') 2 | local policy_chain = require('apicast.policy_chain').default() 3 | local echo_policy = require('apicast.policy.echo').new({ 4 | status = tonumber(resty_env.value('ECHO_STATUS') or 201), 5 | exit = 'request' 6 | }) 7 | 8 | -- add Echo policy to the chain on the 1st place 9 | policy_chain:insert(echo_policy, 1) 10 | 11 | return { 12 | policy_chain = policy_chain 13 | } 14 | -------------------------------------------------------------------------------- /examples/scaffold/policy/gateway/src/apicast/policy/{{policy.file}}/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "{{ policy.name }}", 4 | "summary": "{{ policy.summary }}", 5 | "description": [ 6 | "TODO: Write policy description" 7 | ], 8 | "version": "{{policy.version}}", 9 | "configuration": { 10 | "type": "object", 11 | "properties": { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/scaffold/policy/gateway/src/apicast/policy/{{policy.file}}/init.lua: -------------------------------------------------------------------------------- 1 | return require('{{ policy.file }}') 2 | -------------------------------------------------------------------------------- /examples/scaffold/policy/gateway/src/apicast/policy/{{policy.file}}/{{policy.file}}.lua: -------------------------------------------------------------------------------- 1 | -- This is a {{ policy.name }} description. 2 | 3 | local policy = require('apicast.policy') 4 | local _M = policy.new('{{ policy.name }}') 5 | 6 | local new = _M.new 7 | --- Initialize a {{ policy.name }} 8 | -- @tparam[opt] table config Policy configuration. 9 | function _M.new(config) 10 | local self = new(config) 11 | return self 12 | end 13 | 14 | return _M 15 | -------------------------------------------------------------------------------- /examples/scaffold/policy/spec/policy/{{policy.name}}/{{policy.name}}_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy.{{ policy.file }}') 2 | 3 | describe('{{ policy.name }} policy', function() 4 | describe('.new', function() 5 | it('works without configuration', function() 6 | assert(_M.new()) 7 | end) 8 | 9 | it('accepts configuration', function() 10 | assert(_M.new({ })) 11 | end) 12 | end) 13 | end) 14 | -------------------------------------------------------------------------------- /examples/scaffold/policy/t/apicast-policy-{{policy.file}}.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | run_tests(); 5 | 6 | __DATA__ 7 | 8 | === TEST 1: {{ policy.name}} accepts configuration 9 | --- configuration 10 | { 11 | "services": [ 12 | { 13 | "proxy": { 14 | "policy_chain": [ 15 | { "name": "apicast.policy.{{ policy.file }}", 16 | "configuration": { } }, 17 | { "name": "apicast.policy.echo" } 18 | ] 19 | } 20 | } 21 | ] 22 | } 23 | --- request 24 | GET /t 25 | --- response_body 26 | GET /t HTTP/1.1 27 | --- error_code: 200 28 | --- no_error_log 29 | [error] 30 | -------------------------------------------------------------------------------- /examples/ssl-verification/README.md: -------------------------------------------------------------------------------- 1 | # SSL/TLS Verification 2 | 3 | APIcast supports certificate verification against trusted CAs. This feature is off by default because some environments use custom CAs and would make those connections fail by default. 4 | 5 | ## Upstream verification 6 | 7 | This validation is controller by `proxy_ssl_*` nginx directives. Everything is set up to use default OS trusted certificates. Only step needed is to add custom configuration to enable the verification: 8 | 9 | ```nginx 10 | # apicast.d/proxy_ssl.conf 11 | proxy_ssl_verify on; 12 | ``` 13 | 14 | ## 3scale AMP verification 15 | 16 | To enable verification for connections between APIcast and 3scale AMP you'll need to set `OPENSSL_VERIFY` environment variable. Everything is set up to use the default OS trusted certificate chain. 17 | 18 | ```shell 19 | docker run --env OPENSSL_VERIFY=true apicast 20 | ``` -------------------------------------------------------------------------------- /examples/ssl-verification/proxy_ssl.conf: -------------------------------------------------------------------------------- 1 | proxy_ssl_verify on; 2 | -------------------------------------------------------------------------------- /gateway/Makefile: -------------------------------------------------------------------------------- 1 | $(INST_LUADIR)/apicast: 2 | mkdir -p $@ 3 | 4 | install: $(INST_LUADIR)/apicast 5 | @echo --- install 6 | cp -R gateway/src/* $(INST_LUADIR)/ 7 | cp gateway/bin/apicast* $(INST_BINDIR)/ 8 | cp -r gateway/*.d gateway/conf{,ig} gateway/libexec $(INST_CONFDIR) 9 | -------------------------------------------------------------------------------- /gateway/Roverfile: -------------------------------------------------------------------------------- 1 | luarocks { 2 | 3 | rockspec 'apicast-scm-1.rockspec', 4 | 5 | group 'production' { 6 | module {'lua-resty-iputils', '0.3.0'}, 7 | }, 8 | 9 | group 'testing' { 10 | module { 'busted' }, 11 | module { 'luacov' }, 12 | module { 'jsonschema', '0.8' }, 13 | }, 14 | 15 | group 'development' { 16 | module {'ldoc'}, 17 | module {'lua-resty-repl'}, 18 | module {'fifo'}, 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /gateway/apicast.d/buffers.conf: -------------------------------------------------------------------------------- 1 | {%- assign proxy_buffer_size = env.APICAST_PROXY_BUFFER_SIZE %} 2 | {% if proxy_buffer_size -%} 3 | proxy_buffers 8 {{ proxy_buffer_size }}; 4 | proxy_buffer_size {{ proxy_buffer_size }}; 5 | {%- endif %} 6 | -------------------------------------------------------------------------------- /gateway/apicast.d/location.d/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/gateway/apicast.d/location.d/.keep -------------------------------------------------------------------------------- /gateway/apicast.d/proxy_ssl.conf: -------------------------------------------------------------------------------- 1 | {% if proxy_ssl_verify %} 2 | proxy_ssl_verify on; 3 | {% else %} 4 | proxy_ssl_verify off; 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /gateway/bin/container-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | exec "$@" 3 | -------------------------------------------------------------------------------- /gateway/bin/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 3scale (operations@3scale.net) 4 | set -eu 5 | 6 | luarocks=/opt/app/bin/luarocks 7 | 8 | # Load Luarocks paths 9 | if [ -f "${luarocks}" ]; then 10 | eval `/opt/app/bin/luarocks path` 11 | fi 12 | 13 | if [ -f bin/apicast ]; then 14 | apicast=bin/apicast 15 | elif [ -f "${BASH_SOURCE%/*}/apicast" ]; then 16 | apicast="${BASH_SOURCE%/*}/apicast" 17 | else 18 | apicast=apicast 19 | fi 20 | 21 | exec "${apicast}" "$@" 22 | -------------------------------------------------------------------------------- /gateway/conf.d/backend.conf: -------------------------------------------------------------------------------- 1 | location /transactions/authrep.xml { 2 | access_by_lua_block { 3 | local delay = tonumber(ngx.var.arg_delay) or 0 4 | 5 | if delay > 0 then 6 | ngx.sleep(delay) 7 | end 8 | } 9 | 10 | echo "transactions authrep!"; 11 | } 12 | 13 | location /transactions/oauth_authrep.xml { 14 | access_by_lua_block { 15 | local delay = tonumber(ngx.var.arg_delay) or 0 16 | 17 | if delay > 0 then 18 | ngx.sleep(delay) 19 | end 20 | } 21 | 22 | echo "transactions oauth_authrep!"; 23 | } 24 | 25 | location /transactions/authorize.xml { 26 | access_by_lua_block { 27 | local delay = tonumber(ngx.var.arg_delay) or 0 28 | 29 | if delay > 0 then 30 | ngx.sleep(delay) 31 | end 32 | } 33 | 34 | echo "transactions authorize!"; 35 | } 36 | -------------------------------------------------------------------------------- /gateway/conf.d/echo.conf: -------------------------------------------------------------------------------- 1 | location / { 2 | log_by_lua_block { 3 | if ngx.config.debug then 4 | ngx.log(ngx.DEBUG, "[echo]:\n", ngx.req.raw_header()) 5 | end 6 | } 7 | 8 | echo_foreach_split '\r\n' $echo_client_request_headers; 9 | echo $echo_it; 10 | echo_end; 11 | 12 | echo_read_request_body; 13 | 14 | if ($http_content_length) { 15 | echo_after_body "\n$echo_request_body"; 16 | } 17 | 18 | access_by_lua_block { 19 | local delay = tonumber(ngx.var.arg_delay) or 0 20 | 21 | if delay > 0 then 22 | ngx.sleep(delay) 23 | end 24 | } 25 | } 26 | 27 | location /config/ { 28 | echo "{}"; 29 | } 30 | -------------------------------------------------------------------------------- /gateway/conf.d/management.conf: -------------------------------------------------------------------------------- 1 | location / { 2 | content_by_lua_block { require('apicast.management').call() } 3 | } 4 | -------------------------------------------------------------------------------- /gateway/conf.d/opentelemetry/otel.conf.liquid: -------------------------------------------------------------------------------- 1 | opentelemetry on; 2 | 3 | {% if opentelemetry_config_file == nil or opentelemetry_config_file == empty %} 4 | {% assign opentelemetry_config_file = "conf.d/opentelemetry/jaeger.example.toml" | filesystem | first%} 5 | {% endif %} 6 | 7 | opentelemetry_config {{ opentelemetry_config_file }}; 8 | -------------------------------------------------------------------------------- /gateway/conf.d/opentelemetry/otel.example.toml: -------------------------------------------------------------------------------- 1 | exporter = "otlp" 2 | processor = "batch" 3 | 4 | [exporters.otlp] 5 | # Alternatively the OTEL_EXPORTER_OTLP_ENDPOINT environment variable can also be used. 6 | host = "localhost" 7 | port = 4317 8 | # Optional: enable SSL, for endpoints that support it 9 | # use_ssl = true 10 | # Optional: set a filesystem path to a pem file to be used for SSL encryption 11 | # (when use_ssl = true) 12 | # ssl_cert_path = "/path/to/cert.pem" 13 | 14 | [processors.batch] 15 | max_queue_size = 2048 16 | schedule_delay_millis = 5000 17 | max_export_batch_size = 512 18 | 19 | [service] 20 | name = "apicast" # Opentelemetry resource name 21 | 22 | [sampler] 23 | name = "AlwaysOn" # Also: AlwaysOff, TraceIdRatioBased 24 | ratio = 0.1 25 | parent_based = false 26 | -------------------------------------------------------------------------------- /gateway/conf/proxy.conf: -------------------------------------------------------------------------------- 1 | daemon off; 2 | 3 | events { 4 | worker_connections 1024; 5 | } 6 | 7 | error_log stderr debug; 8 | 9 | stream { 10 | lua_code_cache on; 11 | 12 | resolver local=on; 13 | lua_socket_log_errors off; 14 | 15 | init_by_lua_block { proxy = require('t.fixtures.proxy') } 16 | 17 | # define a TCP server listening on the port 1234: 18 | server { 19 | listen 8099; 20 | content_by_lua_block { proxy() } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /gateway/conf/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBTzCB9gIJAJ/Hbl7Rg8UpMAoGCCqGSM49BAMCMDAxEDAOBgNVBAoMB0FQSWNh 3 | c3QxHDAaBgNVBAsME0RlZmF1bHQgY2VydGlmaWNhdGUwHhcNMTgwNjA1MTAxNjAx 4 | WhcNMjgwNjAyMTAxNjAxWjAwMRAwDgYDVQQKDAdBUEljYXN0MRwwGgYDVQQLDBNE 5 | ZWZhdWx0IGNlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVUiV 6 | WRQcAve1ssYN0qaFWP33pYRLSV4SM6G0BB3SLiYnQKan8K0I7DtvOAoT8HOm0UyM 7 | +6vNyedReg5PXHOuPjAKBggqhkjOPQQDAgNIADBFAiEAoSKLhFHcwFGSu1N4NxSq 8 | p0bGI5J8WYfrdvWVZgWsV9MCIBeJzCEsegLdVBf/mn+4m7GNitMNzLj4CxTCnpqq 9 | S1m1 10 | -----END CERTIFICATE----- 11 | -------------------------------------------------------------------------------- /gateway/conf/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PARAMETERS----- 2 | BggqhkjOPQMBBw== 3 | -----END EC PARAMETERS----- 4 | -----BEGIN EC PRIVATE KEY----- 5 | MHcCAQEEIK9vyuYjAXWiI6QwoBwMs2BPKyY/46Qdd8ZFgTCA2YNRoAoGCCqGSM49 6 | AwEHoUQDQgAEVUiVWRQcAve1ssYN0qaFWP33pYRLSV4SM6G0BB3SLiYnQKan8K0I 7 | 7DtvOAoT8HOm0UyM+6vNyedReg5PXHOuPg== 8 | -----END EC PRIVATE KEY----- 9 | -------------------------------------------------------------------------------- /gateway/config-5.1.lua: -------------------------------------------------------------------------------- 1 | -- vim: set ft=lua: 2 | -- workaround for https://github.com/luarocks/luarocks/issues/740 3 | rocks_trees = { 4 | { name = 'rover', root = [[lua_modules]] }, 5 | } 6 | -------------------------------------------------------------------------------- /gateway/config/production.lua: -------------------------------------------------------------------------------- 1 | return { 2 | master_process = 'on', 3 | lua_code_cache = 'on', 4 | configuration_loader = 'boot', 5 | configuration_cache = os.getenv('APICAST_CONFIGURATION_CACHE') or 5*60, 6 | timer_resolution = '100ms', 7 | port = { metrics = 9421 }, 8 | log_buffer_size = os.getenv("APICAST_ACCESS_LOG_BUFFER") or nil 9 | } 10 | -------------------------------------------------------------------------------- /gateway/config/sandbox.lua: -------------------------------------------------------------------------------- 1 | staging.lua -------------------------------------------------------------------------------- /gateway/config/staging.lua: -------------------------------------------------------------------------------- 1 | return { 2 | master_process = 'on', 3 | lua_code_cache = 'on', 4 | configuration_loader = 'lazy', 5 | configuration_cache = os.getenv('APICAST_CONFIGURATION_CACHE'), 6 | port = { metrics = 9421 }, -- see https://github.com/prometheus/prometheus/wiki/Default-port-allocations, 7 | } 8 | -------------------------------------------------------------------------------- /gateway/cpanfile: -------------------------------------------------------------------------------- 1 | requires 'Test::APIcast', '0.24'; 2 | requires 'Crypt::JWT'; 3 | requires 'Test::Deep'; 4 | requires 'File::Slurp'; 5 | requires 'JSON'; 6 | requires 'URI::data'; 7 | requires 'TAP::Harness::JUnit'; 8 | requires 'Data::Inspect'; 9 | requires 'YAML'; 10 | -------------------------------------------------------------------------------- /gateway/http.d/core.conf: -------------------------------------------------------------------------------- 1 | client_max_body_size 0; 2 | 3 | large_client_header_buffers {{env.APICAST_LARGE_CLIENT_HEADER_BUFFERS | default: "4 8k"}}; -------------------------------------------------------------------------------- /gateway/http.d/lua_capture_error_log.conf: -------------------------------------------------------------------------------- 1 | # To be able to use the ngx.errlog methods that we call from the Metrics policy 2 | # Ref: https://github.com/openresty/lua-nginx-module#lua_capture_error_log 3 | lua_capture_error_log 4k; 4 | -------------------------------------------------------------------------------- /gateway/http.d/shdict.conf: -------------------------------------------------------------------------------- 1 | lua_shared_dict api_keys 30m; 2 | lua_shared_dict rate_limit_headers 20m; 3 | lua_shared_dict limiter 1m; 4 | 5 | # This shared dictionaries are only used in the 3scale batcher policy. 6 | # These requirements will remain in place until we allow policy to 7 | # modify this template. 8 | lua_shared_dict cached_auths 20m; 9 | lua_shared_dict batched_reports {{env.APICAST_POLICY_BATCHER_SHARED_MEMORY_SIZE | default: "20m"}}; 10 | lua_shared_dict batched_reports_locks 1m; 11 | lua_shared_dict ocsp_cache 10m; 12 | -------------------------------------------------------------------------------- /gateway/http.d/ssl.conf: -------------------------------------------------------------------------------- 1 | ## Customize this file to set up proper ssl validation. 2 | ## Openresty/Nginx can't use system certificates: 3 | ## https://groups.google.com/forum/#!topic/openresty-en/SuqORBK9ys0 4 | ## So you have to point it to some ca-bundle which makes 5 | ## it really hard to have working cross platform configuration. 6 | # 7 | 8 | # https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_verify.html 9 | # The default depth limit is 100, allowing for the peer certificate, 10 | # at most 100 intermediate CA certificates and a final trust anchor certificate. 11 | lua_ssl_verify_depth 100; 12 | lua_ssl_trusted_certificate "{{ ca_bundle | default: 'ca-bundle.crt' }}"; 13 | lua_ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; 14 | 15 | proxy_ssl_server_name on; 16 | proxy_ssl_name $http_host; 17 | proxy_ssl_verify_depth 100; 18 | 19 | proxy_ssl_trusted_certificate "{{ ca_bundle | default: 'ca-bundle.crt' }}"; 20 | 21 | proxy_ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; 22 | -------------------------------------------------------------------------------- /gateway/http.d/upstream.conf: -------------------------------------------------------------------------------- 1 | upstream upstream { 2 | server 0.0.0.1:1; 3 | 4 | balancer_by_lua_block { require('apicast.executor'):balancer() } 5 | 6 | keepalive 1024; 7 | keepalive_pool $upstream_keepalive_key; 8 | } 9 | -------------------------------------------------------------------------------- /gateway/libexec/boot: -------------------------------------------------------------------------------- 1 | run -------------------------------------------------------------------------------- /gateway/libexec/boot.lua: -------------------------------------------------------------------------------- 1 | -- Clean warning on openresty 1.15.8.1, where some global variables are set, 2 | -- and a warning message is show during startup outside apicast packages. 3 | -- Code related: https://github.com/openresty/lua-nginx-module/blob/61e4d0aac8974b8fad1b5b93d0d3d694d257d328/src/ngx_http_lua_util.c#L795-L839 4 | (getmetatable(_G) or {}).__newindex = nil 5 | 6 | package.path = package.path .. ";./src/?.lua;" 7 | require('apicast.loader') 8 | 9 | local configuration = require 'apicast.configuration_loader' 10 | local config = configuration.boot() 11 | 12 | ngx.say(config) 13 | -------------------------------------------------------------------------------- /gateway/libexec/keycloak: -------------------------------------------------------------------------------- 1 | run -------------------------------------------------------------------------------- /gateway/main.d/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/gateway/main.d/.keep -------------------------------------------------------------------------------- /gateway/sites.d/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/gateway/sites.d/.gitkeep -------------------------------------------------------------------------------- /gateway/src/apicast/cli/command/console.lua: -------------------------------------------------------------------------------- 1 | local setmetatable = setmetatable 2 | 3 | local _M = { } 4 | local mt = { __index = _M } 5 | 6 | local function configure(cmd) 7 | cmd:argument('file', 'file to execute'):args("?") 8 | return cmd 9 | end 10 | 11 | function _M.new(parser) 12 | local cmd = configure(parser:command('console', 'Start console')) 13 | 14 | return setmetatable({ parser = parser, cmd = cmd }, mt) 15 | end 16 | 17 | function mt.__call(_, options) 18 | local repl = require('resty.repl') 19 | 20 | _G.repl = repl.start 21 | 22 | function _G.reload() package.loaded = {} end 23 | 24 | if options.file then 25 | dofile(options.file) 26 | end 27 | 28 | repl.start() 29 | end 30 | 31 | return setmetatable(_M, mt) 32 | -------------------------------------------------------------------------------- /gateway/src/apicast/configuration_loader/mock.lua: -------------------------------------------------------------------------------- 1 | local _M = { 2 | _VERSION = '0.1', 3 | config = false 4 | } 5 | 6 | function _M.call() 7 | return _M.config 8 | end 9 | 10 | function _M.save(config) 11 | _M.config = config 12 | end 13 | 14 | return _M 15 | -------------------------------------------------------------------------------- /gateway/src/apicast/metrics/3scale_backend_calls.lua: -------------------------------------------------------------------------------- 1 | local prometheus = require('apicast.prometheus') 2 | 3 | local format = string.format 4 | 5 | local _M = {} 6 | 7 | local threescale_backend_call = prometheus( 8 | 'counter', 9 | 'threescale_backend_calls', 10 | "Calls to the 3scale backend", 11 | { 'endpoint', 'status' } 12 | ) 13 | 14 | local function label_for_status(status) 15 | if not status or status == '' or status == 0 then 16 | return 'invalid_status' 17 | else 18 | return format("%dxx", status/100) 19 | end 20 | end 21 | 22 | function _M.report(endpoint, status) 23 | if threescale_backend_call then 24 | threescale_backend_call:inc(1, { endpoint, label_for_status(status) }) 25 | end 26 | end 27 | 28 | return _M 29 | -------------------------------------------------------------------------------- /gateway/src/apicast/metrics/updater.lua: -------------------------------------------------------------------------------- 1 | local tonumber = tonumber 2 | 3 | local _M = {} 4 | 5 | local function metric_op(op, metric, value, label) 6 | local metric_labels = {} 7 | if not metric then return end 8 | metric_labels[1] = label 9 | metric[op](metric, tonumber(value) or 0, metric_labels) 10 | end 11 | 12 | function _M.set(metric, value, label) 13 | return metric_op('set', metric, value, label) 14 | end 15 | 16 | function _M.inc(metric, label) 17 | return metric_op('inc', metric, 1, label) 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/oauth.lua: -------------------------------------------------------------------------------- 1 | local oidc = require 'apicast.oauth.oidc' 2 | 3 | local _M = { 4 | _VERSION = '0.0.2', 5 | oidc = oidc, 6 | } 7 | 8 | return _M 9 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_batcher/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "3scale Batcher", 4 | "summary": "Caches auths from 3scale backend and batches reports.", 5 | "description": 6 | ["This policy caches authorizations from the 3scale backend ", 7 | "and reports them in batches. This is more efficient than authorizing ", 8 | "and reporting on each request at the expense of losing accuracy in the ", 9 | "rate limits."], 10 | "version": "builtin", 11 | "configuration": { 12 | "type": "object", 13 | "properties": { 14 | "auths_ttl": { 15 | "description": "TTL for cached auths in seconds", 16 | "type": "integer" 17 | }, 18 | "batch_report_seconds": { 19 | "description": "Duration (in seconds) for batching reports", 20 | "type": "integer" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_batcher/init.lua: -------------------------------------------------------------------------------- 1 | return require('3scale_batcher') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_batcher/metrics.lua: -------------------------------------------------------------------------------- 1 | local prometheus = require('apicast.prometheus') 2 | 3 | local _M = {} 4 | 5 | local auth_cache_hits = prometheus( 6 | 'counter', 7 | 'batching_policy_auths_cache_hits', 8 | 'Hits in the auths cache of the 3scale batching policy' 9 | ) 10 | 11 | local auth_cache_misses = prometheus( 12 | 'counter', 13 | 'batching_policy_auths_cache_misses', 14 | "Misses in the auths cache of the 3scale batching policy" 15 | ) 16 | 17 | local function inc_auth_cache_hits() 18 | return auth_cache_hits and auth_cache_hits:inc() 19 | end 20 | 21 | local function inc_auth_cache_misses() 22 | return auth_cache_misses and auth_cache_misses:inc() 23 | end 24 | 25 | local func_update_counters = { 26 | [true] = inc_auth_cache_hits, 27 | [false] = inc_auth_cache_misses 28 | } 29 | 30 | function _M.update_cache_counters(cache_hit) 31 | func_update_counters[cache_hit]() 32 | end 33 | 34 | return _M 35 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_batcher/transaction.lua: -------------------------------------------------------------------------------- 1 | --- Transaction 2 | -- A transaction contains the information that APIcast needs to send to the 3 | -- 3scale backend in order to know whether a call should be authorized. 4 | 5 | local setmetatable = setmetatable 6 | 7 | local _M = {} 8 | 9 | local mt = { __index = _M } 10 | 11 | function _M.new(service_id, credentials, usage) 12 | local self = setmetatable({}, mt) 13 | 14 | self.service_id = service_id 15 | self.credentials = credentials 16 | self.usage = usage 17 | 18 | return self 19 | end 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_referrer/3scale_referrer.lua: -------------------------------------------------------------------------------- 1 | local policy = require('apicast.policy') 2 | local _M = policy.new('3scale Referrer policy', 'builtin') 3 | 4 | function _M.rewrite(_, context) 5 | local referrer = ngx.var.http_referer 6 | 7 | if referrer then 8 | if context.proxy then 9 | context.proxy.extra_params_backend_authrep.referrer = referrer 10 | else 11 | ngx.log(ngx.ERR, 'Did not find a proxy in the policies context.') 12 | end 13 | end 14 | end 15 | 16 | return _M 17 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_referrer/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "3scale Referrer", 4 | "summary": "Sends the 'Referer' to 3scale backend so it can be validated.", 5 | "description": "Sends the 'Referer' to 3scale backend for validation.", 6 | "version": "builtin", 7 | "configuration": { 8 | "type": "object", 9 | "properties": {} 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/3scale_referrer/init.lua: -------------------------------------------------------------------------------- 1 | return require('3scale_referrer') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/apicast/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "3scale APIcast", 4 | "summary": "Main functionality of APIcast to work with the 3scale API manager.", 5 | "description": 6 | ["Main functionality of APIcast to work with the 3scale API ", 7 | "manager. This includes matching of mapping rules, authorization, ", 8 | "reporting, etc."], 9 | "version": "builtin", 10 | "configuration": { 11 | "type": "object", 12 | "properties": { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/apicast/init.lua: -------------------------------------------------------------------------------- 1 | return require('apicast') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/caching/init.lua: -------------------------------------------------------------------------------- 1 | return require('caching') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/camel/init.lua: -------------------------------------------------------------------------------- 1 | return require("camel") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/clear_context/clear_context.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('Clear Context') 2 | local new = _M.new 3 | 4 | function _M.new(...) 5 | return new(...) 6 | end 7 | 8 | local function clear_table(t) 9 | for k, _ in pairs(t) do 10 | t[k] = nil 11 | end 12 | end 13 | 14 | function _M:ssl_certificate(_) 15 | --resetting the context after every other policy in the chain 16 | --has executed their ssl_certificate phase. 17 | clear_table(ngx.ctx) 18 | end 19 | 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/clear_context/init.lua: -------------------------------------------------------------------------------- 1 | return require('clear_context') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/conditional/init.lua: -------------------------------------------------------------------------------- 1 | return require('conditional') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/content_caching/init.lua: -------------------------------------------------------------------------------- 1 | return require("content_caching") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/cors/Readme.md: -------------------------------------------------------------------------------- 1 | # APICast CORS Policy 2 | 3 | This policy allows to enable CORS Headers for the service. 4 | 5 | ## Example configuration 6 | 7 | ``` 8 | { 9 | "name": "cors", 10 | "version": "builtin", 11 | "configuration": { 12 | "allow_headers": [ 13 | "App-Id", "App-Key", 14 | "Content-Type", "Accept" 15 | ], 16 | "allow_credentials": true, 17 | "allow_methods": [ 18 | "GET", "POST" 19 | ], 20 | "allow_origin": "https://example.com", 21 | "max_age" : 200 22 | } 23 | ``` 24 | 25 | ## Recommended configuration 26 | 27 | - Setting `allow_origin` to blank will enable any origin for `Cross request` on the service. 28 | - If used alongside with `APICAST_PATH_ROUTING` the policy must be enabled for every service that share the same host name. 29 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/cors/init.lua: -------------------------------------------------------------------------------- 1 | return require('cors') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/custom_metrics/init.lua: -------------------------------------------------------------------------------- 1 | return require("custom_metrics") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/default_credentials/init.lua: -------------------------------------------------------------------------------- 1 | return require('default_credentials') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/echo/init.lua: -------------------------------------------------------------------------------- 1 | return require('echo') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/fapi/init.lua: -------------------------------------------------------------------------------- 1 | return require('fapi') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/find_service/host_based_finder.lua: -------------------------------------------------------------------------------- 1 | local _M = {} 2 | 3 | function _M.find_service(config_store, host) 4 | local found 5 | local services = config_store:find_by_host(host) 6 | 7 | for s=1, #services do 8 | local service = services[s] 9 | local hosts = service.hosts or {} 10 | 11 | for h=1, #hosts do 12 | if hosts[h] == host and service == config_store:find_by_id(service.id) then 13 | found = service 14 | break 15 | end 16 | end 17 | if found then break end 18 | end 19 | 20 | return found or ngx.log(ngx.WARN, 'service not found for host ', host) 21 | end 22 | 23 | return _M 24 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/find_service/init.lua: -------------------------------------------------------------------------------- 1 | return require('find_service') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/grpc/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "HTTP2 Endpoint", 4 | "summary": "Main functionality to enable HTTP2 endpoint reply.", 5 | "description": 6 | ["To enable full HTTP2 traffic from the user to the final endpoint "], 7 | "version": "builtin", 8 | "configuration": { 9 | "type": "object", 10 | "properties": { } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/grpc/grpc.lua: -------------------------------------------------------------------------------- 1 | -- This policy enables HTTP2 handle on the API endpoint. 2 | 3 | local policy = require('apicast.policy') 4 | local _M = policy.new('grpc', "builtin") 5 | 6 | local apicast_balancer = require('apicast.balancer') 7 | local new = _M.new 8 | 9 | function _M.new(config) 10 | local self = new(config) 11 | return self 12 | end 13 | 14 | function _M:rewrite(context) 15 | -- upstream defined in gateway/conf.d/http2.conf 16 | context.upstream_location_name = "@grpc_upstream" 17 | ngx.var.proxy_host = "upstream" 18 | end 19 | 20 | _M.balancer = apicast_balancer.call 21 | 22 | return _M 23 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/grpc/init.lua: -------------------------------------------------------------------------------- 1 | return require('grpc') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/headers/init.lua: -------------------------------------------------------------------------------- 1 | return require('headers') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/http_proxy/init.lua: -------------------------------------------------------------------------------- 1 | return require("proxy") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/ip_check/init.lua: -------------------------------------------------------------------------------- 1 | return require('ip_check') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/jwt_claim_check/init.lua: -------------------------------------------------------------------------------- 1 | return require('jwt_claim_check') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/jwt_parser/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "JWT Parser", 4 | "summary": "Parse JWT", 5 | "description": ["This policy parse JWT token from Authorization header"], 6 | "version": "builtin", 7 | "configuration": { 8 | "type": "object", 9 | "properties": { 10 | "issuer_endpoint": { 11 | "description": "URL of OpenID Provider. The format of this endpoint is determined on your OpenID Provider setup.", 12 | "type": "string" 13 | }, 14 | "required": { 15 | "description": "when enabled, rejected request if no JWT token present in Authorization header", 16 | "type": "boolean" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/jwt_parser/init.lua: -------------------------------------------------------------------------------- 1 | return require('jwt_parser') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/keycloak_role_check/init.lua: -------------------------------------------------------------------------------- 1 | return require('keycloak_role_check') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/liquid_context_debug/init.lua: -------------------------------------------------------------------------------- 1 | return require('liquid_context_debug') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/liquid_context_debug/liquid_context_debug.lua: -------------------------------------------------------------------------------- 1 | local context_content = require('context_content') 2 | local cjson = require('cjson') 3 | local policy = require('apicast.policy') 4 | local ngx_variable = require('apicast.policy.ngx_variable') 5 | local _M = policy.new('Liquid context debug', 'builtin') 6 | 7 | local new = _M.new 8 | 9 | function _M.new(config) 10 | local self = new(config) 11 | return self 12 | end 13 | 14 | function _M.content(_, context) 15 | local liquid_context = ngx_variable.available_context(context) 16 | local content = context_content.from(liquid_context) 17 | 18 | ngx.say(cjson.encode(content)) 19 | end 20 | 21 | return _M 22 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/load_configuration/init.lua: -------------------------------------------------------------------------------- 1 | return require('load_configuration') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/local_chain/init.lua: -------------------------------------------------------------------------------- 1 | return require('local_chain') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/logging/init.lua: -------------------------------------------------------------------------------- 1 | return require('logging') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/maintenance_mode/init.lua: -------------------------------------------------------------------------------- 1 | return require('maintenance_mode') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/management/init.lua: -------------------------------------------------------------------------------- 1 | return require('management') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/management/management.lua: -------------------------------------------------------------------------------- 1 | -- This is a management description. 2 | 3 | local policy = require('apicast.policy') 4 | local _M = policy.new('management') 5 | 6 | local management = require('apicast.management') 7 | 8 | local new = _M.new 9 | --- Initialize a management 10 | -- @tparam[opt] table config Policy configuration. 11 | function _M.new(config) 12 | local self = new(config) 13 | 14 | local router = management.router(config and config.mode) 15 | 16 | if not router then 17 | return nil, 'invalid management api' 18 | end 19 | 20 | self.router = router 21 | 22 | return self 23 | end 24 | 25 | function _M:content() 26 | local method = ngx.req.get_method() 27 | local uri = ngx.var.uri 28 | 29 | local ok, err = self.router:execute(method, uri) 30 | 31 | if not ok then 32 | ngx.status = 404 33 | end 34 | 35 | if err then 36 | ngx.say(err) 37 | end 38 | end 39 | 40 | return _M 41 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/nginx_filters/init.lua: -------------------------------------------------------------------------------- 1 | return require("nginx_filters") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/nginx_metrics/init.lua: -------------------------------------------------------------------------------- 1 | return require('nginx_metrics') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/ngx_variable.lua: -------------------------------------------------------------------------------- 1 | local LinkedList = require('apicast.linked_list') 2 | 3 | local _M = {} 4 | 5 | local function context_values() 6 | return { 7 | uri = ngx.var.uri, 8 | path = ngx.var.path, 9 | host = ngx.var.host, 10 | remote_addr = ngx.var.remote_addr, 11 | remote_port = ngx.var.remote_port, 12 | scheme = ngx.var.scheme, 13 | server_addr = ngx.var.server_addr, 14 | server_port = ngx.var.server_port, 15 | headers = ngx.req.get_headers(), 16 | http_method = ngx.req.get_method(), 17 | request_id = ngx.var.request_id, 18 | } 19 | end 20 | 21 | function _M.available_context(policies_context) 22 | return LinkedList.readonly(context_values(), policies_context) 23 | end 24 | 25 | return _M 26 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/oauth_mtls/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "OAuth 2.0 Mutual TLS Client Authentication", 4 | "summary": "Configure OAuth 2.0 Mutual TLS Client Authentication.", 5 | "description": ["This policy executes OAuth 2.0 Mutual TLS Client Authentication ", 6 | "(https://tools.ietf.org/html/rfc8705) for every API call." 7 | ], 8 | "version": "builtin", 9 | "configuration": { 10 | "type": "object", 11 | "properties": { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/oauth_mtls/init.lua: -------------------------------------------------------------------------------- 1 | return require('oauth_mtls') -------------------------------------------------------------------------------- /gateway/src/apicast/policy/on_failed/Readme.md: -------------------------------------------------------------------------------- 1 | # Policy on_failed 2 | 3 | When any policy fails, this policy block the request and send back a given 4 | status code to the user. 5 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/on_failed/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "On fail", 4 | "summary": "Block request if any policy fails", 5 | "description": "When a policy fails, this policy allows to set an error message back to the user and stop processing the request to the upstream API.", 6 | "version": "builtin", 7 | "order": { 8 | "before": [ 9 | { 10 | "name": "apicast", 11 | "version": "builtin" 12 | } 13 | ] 14 | }, 15 | "configuration": { 16 | "type": "object", 17 | "properties": { 18 | "error_status_code": { 19 | "description": "Status code that will send to the user if any policy fails", 20 | "type": "integer", 21 | "minimum": 100, 22 | "exclusiveMaximum": 700 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/on_failed/init.lua: -------------------------------------------------------------------------------- 1 | return require("on_failed") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/on_failed/on_failed.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('On failed', 'builtin') 2 | local new = _M.new 3 | 4 | 5 | function _M.new(config) 6 | local self = new(config) 7 | self.error_status_code = config.error_status_code or ngx.HTTP_SERVICE_UNAVAILABLE 8 | return self 9 | end 10 | 11 | function _M:export() 12 | return { 13 | policy_error_callback = function(policy_name, error_message) 14 | ngx.log(ngx.DEBUG, "Stop request because policy: '", policy_name, "' failed, error='", error_message, "'") 15 | ngx.exit(self.error_status_code) 16 | end 17 | } 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/payload_limits/Readme.md: -------------------------------------------------------------------------------- 1 | # Request/response payload size limits policy 2 | 3 | This policy allows users to limit the size of the request and the response. 4 | 5 | To get this policy working, the content-length header is mandatory on request 6 | and response. 7 | 8 | ## Configuration 9 | 10 | - Limit request to 100 bytes, response unlimited 11 | 12 | ``` 13 | { 14 | "name": "apicast.policy.limits", 15 | "configuration": { 16 | "request": 100, 17 | "response": 0 18 | } 19 | } 20 | ``` 21 | 22 | - Limit response to 100 bytes, request unlimited 23 | 24 | ``` 25 | { 26 | "name": "apicast.policy.limits", 27 | "configuration": { 28 | "request": 0, 29 | "response": 100 30 | } 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/payload_limits/init.lua: -------------------------------------------------------------------------------- 1 | return require("payload_limit") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/phase_logger/init.lua: -------------------------------------------------------------------------------- 1 | return require('phase_logger') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rate_limit/init.lua: -------------------------------------------------------------------------------- 1 | return require('rate_limit') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rate_limit_headers/Readme.md: -------------------------------------------------------------------------------- 1 | # Rate limits headers 2 | 3 | This policy send the headers back to the user with the rate limit information. 4 | This policy implements the [RateLimit Header Fields for HTTP draft] 5 | (https://ioggstream.github.io/draft-polli-ratelimit-headers/draft-polli-ratelimit-headers.html) 6 | 7 | 8 | ## Headers accuracy: 9 | 10 | This header information is retrieved from 11 | [APISonator](https://github.com/3scale/apisonator), but is not always sync, on 12 | second request we cached the information, so it's possible that the information 13 | is not 100% accurate with APISonator, but APIcast always try to sync with 14 | backend. 15 | 16 | The main reason for this is performance, in this case, call to APISonator in 17 | request time is time-consuming, and it's not needed at all. 18 | 19 | If data accurate is needed, caching can be disabled, so data will always be 100% 20 | accurate. 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rate_limit_headers/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "Rate Limits Headers", 4 | "summary": "Set rate limit headers on response", 5 | "description": 6 | ["This policy implements the `RateLimit Header Fields for HTTP` draft in ", 7 | "responses."], 8 | "version": "builtin", 9 | "configuration": {} 10 | } 11 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rate_limit_headers/countdown_counter.lua: -------------------------------------------------------------------------------- 1 | local now = ngx.now 2 | local _M = {} 3 | 4 | local mt = { __index = _M } 5 | 6 | function _M.new(limit_time_delta, initial_time) 7 | if not initial_time then 8 | initial_time = now() 9 | end 10 | 11 | local self = setmetatable({}, mt) 12 | self.limit_time = tonumber(initial_time) + tonumber(limit_time_delta) 13 | return self 14 | end 15 | 16 | function _M:remaining_secs(time) 17 | return self.limit_time - time 18 | end 19 | 20 | function _M:remaining_secs_positive(time) 21 | local result = self:remaining_secs(time) 22 | if result >= 0 then 23 | return tonumber(string.format("%i", result)) 24 | end 25 | return 0 26 | end 27 | 28 | function _M:__tostring() 29 | return tostring(self.limit_time) 30 | end 31 | 32 | return _M 33 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rate_limit_headers/init.lua: -------------------------------------------------------------------------------- 1 | return require('rate_limit_headers') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/request_unbuffered/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Request Unbuffered", 4 | "summary": "Disable request buffering", 5 | "description": [ 6 | "Disable request buffering. This is useful when proxying big payloads with HTTP/1.1 chunked encoding" 7 | ], 8 | "version": "builtin", 9 | "configuration": { 10 | "type": "object", 11 | "properties": {} 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/request_unbuffered/init.lua: -------------------------------------------------------------------------------- 1 | return require('request_unbuffered') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/request_unbuffered/request_unbuffered.lua: -------------------------------------------------------------------------------- 1 | -- Request Unbuffered policy 2 | -- This policy will disable request buffering 3 | 4 | local policy = require('apicast.policy') 5 | local _M = policy.new('request_unbuffered') 6 | 7 | local new = _M.new 8 | 9 | --- Initialize a buffering 10 | -- @tparam[opt] table config Policy configuration. 11 | function _M.new(config) 12 | local self = new(config) 13 | return self 14 | end 15 | 16 | function _M:rewrite(context) 17 | context.request_unbuffered = true 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/retry/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "Retry", 4 | "summary": "Allows to retry requests to the upstream", 5 | "description": "Allows to retry requests to the upstream", 6 | "version": "builtin", 7 | "configuration": { 8 | "type": "object", 9 | "properties": { 10 | "retries": { 11 | "description": "Number of retries", 12 | "type": "integer", 13 | "minimum": 1, 14 | "maximum": 10 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/retry/init.lua: -------------------------------------------------------------------------------- 1 | return require('retry') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/retry/retry.lua: -------------------------------------------------------------------------------- 1 | --- Retry policy 2 | 3 | local tonumber = tonumber 4 | 5 | local _M = require('apicast.policy').new('Retry Policy', 'builtin') 6 | 7 | local new = _M.new 8 | 9 | 10 | function _M.new(config) 11 | local self = new(config) 12 | self.retries = tonumber(config.retries) 13 | return self 14 | end 15 | 16 | function _M:rewrite(context) 17 | context.upstream_retries = self.retries 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/rewrite_url_captures/init.lua: -------------------------------------------------------------------------------- 1 | return require 'rewrite_url_captures' 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/routing/init.lua: -------------------------------------------------------------------------------- 1 | return require('routing') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/routing/request.lua: -------------------------------------------------------------------------------- 1 | local setmetatable = setmetatable 2 | 3 | local _M = {} 4 | 5 | local mt = { __index = _M } 6 | 7 | function _M.new() 8 | local self = setmetatable({}, mt) 9 | return self 10 | end 11 | 12 | function _M:get_uri() 13 | self.uri = self.uri or ngx.var.uri 14 | return self.uri 15 | end 16 | 17 | function _M:get_header(name) 18 | self.headers = self.headers or ngx.req.get_headers() 19 | return self.headers[name] 20 | end 21 | 22 | function _M:get_uri_arg(name) 23 | self.query_args = self.query_args or ngx.req.get_uri_args() 24 | return self.query_args[name] 25 | end 26 | 27 | function _M:set_validated_jwt(jwt) 28 | self.jwt = jwt 29 | end 30 | 31 | function _M:get_validated_jwt() 32 | return self.jwt 33 | end 34 | 35 | return _M 36 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/soap/init.lua: -------------------------------------------------------------------------------- 1 | return require('soap') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/standalone/init.lua: -------------------------------------------------------------------------------- 1 | return require('standalone') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/statuscode_overwrite/Readme.md: -------------------------------------------------------------------------------- 1 | # StatusCode overwrite 2 | 3 | This policy changes the upstream status code with the desired ones. 4 | 5 | ## Examples 6 | 7 | Change status 200 to 201 8 | 9 | ``` 10 | { 11 | "name": "statuscode_overwrite", 12 | "version": "builtin", 13 | "configuration": { 14 | "http_statuses": [ 15 | { 16 | "upstream": 200, 17 | "apicast": 201 18 | } 19 | ] 20 | } 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/statuscode_overwrite/code_overwrite.lua: -------------------------------------------------------------------------------- 1 | local policy = require('apicast.policy') 2 | local _M = policy.new('HTTP Code Overwrite', 'builtin') 3 | local ipairs = ipairs 4 | local new = _M.new 5 | 6 | function _M.new(config) 7 | local self = new(config) 8 | self.http_statuses = {} 9 | for _, code in ipairs(config.http_statuses or {}) do 10 | self.http_statuses[code.upstream] = code.apicast 11 | end 12 | return self 13 | end 14 | 15 | function _M:header_filter() 16 | ngx.status = self.http_statuses[ngx.status] or ngx.status 17 | end 18 | 19 | return _M 20 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/statuscode_overwrite/init.lua: -------------------------------------------------------------------------------- 1 | return require('code_overwrite') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/tls/init.lua: -------------------------------------------------------------------------------- 1 | return require('tls') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/tls_validation/init.lua: -------------------------------------------------------------------------------- 1 | return require('tls_validation') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/token_introspection/init.lua: -------------------------------------------------------------------------------- 1 | return require('token_introspection') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/upstream/init.lua: -------------------------------------------------------------------------------- 1 | return require('upstream') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/upstream_connection/init.lua: -------------------------------------------------------------------------------- 1 | return require('upstream_connection') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/upstream_connection/upstream_connection.lua: -------------------------------------------------------------------------------- 1 | -- Upstream Connection Policy 2 | --- This policy exposes some parameters related with the connection to the 3 | --- upstream. 4 | 5 | local tonumber = tonumber 6 | 7 | local _M = require('apicast.policy').new('Upstream connection policy', 'builtin') 8 | 9 | local new = _M.new 10 | 11 | function _M.new(config) 12 | local self = new(config) 13 | 14 | self.connect_timeout = tonumber(config.connect_timeout) 15 | self.send_timeout = tonumber(config.send_timeout) 16 | self.read_timeout = tonumber(config.read_timeout) 17 | 18 | return self 19 | end 20 | 21 | function _M:rewrite(context) 22 | context.upstream_connection_opts = { 23 | connect_timeout = self.connect_timeout, 24 | send_timeout = self.send_timeout, 25 | read_timeout = self.read_timeout 26 | } 27 | end 28 | 29 | return _M 30 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/upstream_mtls/init.lua: -------------------------------------------------------------------------------- 1 | return require("upstream_mtls") 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/url_rewriting/init.lua: -------------------------------------------------------------------------------- 1 | return require('url_rewriting') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/websocket/README.md: -------------------------------------------------------------------------------- 1 | # Websocket policy 2 | 3 | A policy which enables Websocket connection from the endpoint to the Upstream 4 | API. 5 | 6 | ## Properties 7 | 8 | This policy does not have properties. 9 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/websocket/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1.1/schema#manifest#", 3 | "name": "Websocket", 4 | "summary": "Allows websocket connection pass through.", 5 | "description": [ 6 | "A policy which allows Websocket traffic for the service" 7 | ], 8 | "version": "builtin", 9 | "configuration": { 10 | "type": "object", 11 | "properties": { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/websocket/init.lua: -------------------------------------------------------------------------------- 1 | return require('websocket') 2 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy/websocket/websocket.lua: -------------------------------------------------------------------------------- 1 | -- This policy enables Web socket pass through on APIcast 2 | 3 | local _M = require('apicast.policy').new('Websocket', 'builtin') 4 | 5 | local new = _M.new 6 | 7 | function _M.new(configuration) 8 | local policy = new(configuration) 9 | return policy 10 | end 11 | 12 | local function is_websocket_connection() 13 | local headers = ngx.req.get_headers() 14 | return headers["Upgrade"] ~= nil and headers["Sec-WebSocket-Key"] ~= nil 15 | end 16 | 17 | function _M:rewrite() 18 | if is_websocket_connection() then 19 | ngx.var.upstream_connection_header = "Upgrade" 20 | end 21 | end 22 | 23 | return _M 24 | -------------------------------------------------------------------------------- /gateway/src/apicast/policy_config_validator.lua: -------------------------------------------------------------------------------- 1 | --- Policy Config Validator 2 | -- @module policy_config_validator 3 | -- Validates a policy configuration against a policy config JSON schema. 4 | 5 | local jsonschema = require('jsonschema') 6 | 7 | local _M = { } 8 | 9 | --- Validate a policy configuration 10 | -- Checks if a policy configuration is valid according to the given schema. 11 | -- @tparam table config Policy configuration 12 | -- @tparam table config_schema Policy configuration schema 13 | -- @treturn boolean True if the policy configuration is valid. False otherwise. 14 | -- @treturn string Error message only when the policy config is invalid. 15 | function _M.validate_config(config, config_schema) 16 | local validator = jsonschema.generate_validator(config_schema or {}) 17 | return validator(config or {}) 18 | end 19 | 20 | return _M 21 | -------------------------------------------------------------------------------- /gateway/src/apicast/prometheus.lua: -------------------------------------------------------------------------------- 1 | local prometheus = require('nginx.prometheus') 2 | local assert = assert 3 | local dict = 'prometheus_metrics' 4 | 5 | if ngx.shared[dict] then 6 | local init = prometheus.init(dict) 7 | 8 | local metrics = { } 9 | local __call = function(_, type, name, ...) 10 | local metric_name = assert(name, 'missing metric name') 11 | 12 | if not metrics[metric_name] then 13 | metrics[metric_name] = init[assert(type, 'missing metric type')](init, metric_name, ...) 14 | end 15 | 16 | return metrics[metric_name] 17 | end 18 | 19 | return setmetatable({ }, { __call = __call, __index = init }) 20 | else 21 | local noop = function() end 22 | return setmetatable({ collect = noop }, { __call = noop }) 23 | end 24 | -------------------------------------------------------------------------------- /gateway/src/apicast/version.lua: -------------------------------------------------------------------------------- 1 | return "3.16.0" 2 | -------------------------------------------------------------------------------- /gateway/src/resty/balancer/random.lua: -------------------------------------------------------------------------------- 1 | local balancer = require 'resty.balancer' 2 | 3 | local _M = { 4 | _VERSION = '0.1' 5 | } 6 | 7 | local random = math.random 8 | 9 | function _M.new() 10 | return balancer.new(_M.call) 11 | end 12 | 13 | local function random_peer(peers) 14 | local n = #peers 15 | local i = random(1, n) 16 | 17 | return peers[i], i 18 | end 19 | 20 | function _M.call(peers) 21 | return random_peer(peers) 22 | end 23 | 24 | return _M 25 | -------------------------------------------------------------------------------- /gateway/src/resty/concurrent/executor.lua: -------------------------------------------------------------------------------- 1 | --- @module resty.concurrent 2 | 3 | local ImmediateExecutor = require('resty.concurrent.immediate_executor') 4 | local TimerPoolExecutor = require('resty.concurrent.timer_pool_executor') 5 | 6 | --- @type Executor 7 | local _M = { 8 | default = ImmediateExecutor, 9 | immediate = ImmediateExecutor, 10 | timer_pool = TimerPoolExecutor, 11 | } 12 | 13 | --- @function from_options 14 | --- @static 15 | --- @tparam ?table options 16 | --- @tparam nil|table|string|Executor options.executor 17 | function _M.from_options(options) 18 | local executor = options and options.executor or nil 19 | 20 | if type(executor) == 'string' then 21 | return _M[executor] or error('unknown executor: ' .. executor) 22 | elseif executor then 23 | return executor 24 | else 25 | return _M.default 26 | end 27 | end 28 | 29 | 30 | return _M 31 | -------------------------------------------------------------------------------- /gateway/src/resty/concurrent/immediate_executor.lua: -------------------------------------------------------------------------------- 1 | --- @module resty.concurrent 2 | 3 | --- @type ImmediateExecutor 4 | 5 | local _M = { } 6 | 7 | --- Immediately execute task in current thread. 8 | --- @function ImmediateExecutor:post 9 | function _M.post(_, task, ...) 10 | return task(...) 11 | end 12 | 13 | return _M 14 | -------------------------------------------------------------------------------- /gateway/src/resty/coroutines.lua: -------------------------------------------------------------------------------- 1 | local co_create = coroutine._create 2 | local co_resume = coroutine._resume 3 | 4 | local _M = {} 5 | 6 | --- Create coroutine iterator 7 | -- Like coroutine.wrap but safe to be used as iterator, 8 | -- because it will return nil as first return value on error. 9 | function _M.co_wrap_iter(f) 10 | local co = co_create(f) 11 | 12 | return function(...) 13 | local ok, ret = co_resume(co, ...) 14 | 15 | if ok then 16 | return ret 17 | else 18 | return nil, ret 19 | end 20 | end 21 | end 22 | 23 | return _M 24 | 25 | -------------------------------------------------------------------------------- /gateway/src/resty/counter.lua: -------------------------------------------------------------------------------- 1 | local _M = {} 2 | 3 | local mt = { __index = _M } 4 | 5 | function _M.new(initial_value) 6 | local self = setmetatable({}, mt) 7 | self.value = tonumber(initial_value) or 0 8 | return self 9 | end 10 | 11 | function _M:increment(delta) 12 | self.value = self.value + (tonumber(delta) or 1) 13 | return self.value 14 | end 15 | 16 | function _M:decrement(delta) 17 | self.value = self.value - (tonumber(delta) or 1) 18 | return self.value 19 | end 20 | 21 | function _M:__tostring() 22 | return tostring(self.value) 23 | end 24 | 25 | return _M 26 | -------------------------------------------------------------------------------- /gateway/src/resty/http_ng/backend/cache.lua: -------------------------------------------------------------------------------- 1 | local setmetatable = setmetatable 2 | 3 | ------------ 4 | --- HTTP 5 | -- HTTP client 6 | -- @module http_ng.backend 7 | 8 | local _M = {} 9 | 10 | local mt = { __index = _M } 11 | 12 | function _M.new(backend, options) 13 | local opts = options or {} 14 | return setmetatable({ 15 | backend = backend, cache_store = opts.cache_store 16 | }, mt) 17 | end 18 | 19 | --- Send request and return the response 20 | -- @tparam http_ng.request request 21 | -- @treturn http_ng.response 22 | function _M:send(request) 23 | local cache_store = self.cache_store 24 | local backend = self.backend 25 | 26 | local response, err 27 | 28 | if cache_store then 29 | response, err = cache_store:send(backend, request) 30 | else 31 | response, err = backend:send(request) 32 | end 33 | 34 | return response, err 35 | end 36 | 37 | return _M 38 | -------------------------------------------------------------------------------- /gateway/src/resty/oidc/jwk.lua: -------------------------------------------------------------------------------- 1 | local ipairs = ipairs 2 | 3 | local tab_new = require('resty.core.base').new_tab 4 | local pkey = require ('resty.openssl.pkey') 5 | local cjson = require ('cjson') 6 | 7 | local _M = { } 8 | 9 | function _M.convert_keys(res, ...) 10 | if not res then return nil, ... end 11 | local keys = tab_new(0, #res.keys) 12 | 13 | for _,jwk in ipairs(res.keys) do 14 | keys[jwk.kid] = _M.convert_jwk_to_pem(jwk) 15 | end 16 | 17 | return keys 18 | end 19 | 20 | function _M.convert_jwk_to_pem(jwk) 21 | local val, err = pkey.new(cjson.encode(jwk), { format = "JWK" }) 22 | if not val then 23 | return nil, err 24 | end 25 | jwk.pem = val:tostring("public", "PEM") 26 | 27 | return jwk 28 | end 29 | 30 | return _M 31 | -------------------------------------------------------------------------------- /gateway/src/resty/yaml.lua: -------------------------------------------------------------------------------- 1 | local init = false 2 | local _M = {} 3 | 4 | local function init_yaml() 5 | if not init then 6 | init = true 7 | yaml = require('lyaml.functional') 8 | yaml.NULL = ngx.null 9 | yaml.isnull = function(value) return value == ngx.null end 10 | YAML = require('lyaml') 11 | _M["load"] = YAML.load 12 | _M["null"] = YAML.null 13 | end 14 | end 15 | 16 | 17 | local mt = { 18 | __index = function (self, key) 19 | init_yaml() 20 | return _M[key] 21 | end 22 | } 23 | 24 | return setmetatable({}, mt) 25 | -------------------------------------------------------------------------------- /luarocks.config: -------------------------------------------------------------------------------- 1 | -- vim: set ft=lua: 2 | lua_interpreter = [[resty]] 3 | 4 | rocks_trees = { 5 | { root = [[lua_modules]] }, 6 | } 7 | 8 | variables = { 9 | LUA_BINDIR = "" 10 | } 11 | -------------------------------------------------------------------------------- /markdown-lint-check-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [ 3 | { 4 | "pattern": "^.*.foo" 5 | }, 6 | { 7 | "pattern": "^.*.bar" 8 | } 9 | ], 10 | "replacementPatterns": [ 11 | { 12 | "pattern": "^/", 13 | "replacement": "{{BASEURL}}/" 14 | } 15 | ], 16 | "retryOn429": true, 17 | "retryCount": 5, 18 | "fallbackRetryDelay": "30s" 19 | } 20 | -------------------------------------------------------------------------------- /openresty.repo: -------------------------------------------------------------------------------- 1 | [openresty] 2 | name=Official OpenResty Repository 3 | baseurl=https://copr-be.cloud.fedoraproject.org/results/openresty/openresty/epel-$releasever-$basearch/ 4 | skip_if_unavailable=True 5 | gpgcheck=1 6 | gpgkey=https://copr-be.cloud.fedoraproject.org/results/openresty/openresty/pubkey.gpg 7 | enabled=1 8 | enabled_metadata=1 -------------------------------------------------------------------------------- /openshift/portal-secret-template.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | objects: 4 | - apiVersion: v1 5 | kind: Secret 6 | metadata: 7 | name: ${SECRET_NAME} 8 | data: 9 | password: ${APICAST_CONFIGURATION_URL_BASE64} 10 | type: Opaque 11 | parameters: 12 | - description: "Name of the secret, if you change this name, be sure to point the 3scale gateway to the correct secret name." 13 | value: apicast-configuration-url-secret 14 | name: SECRET_NAME 15 | required: true 16 | - description: base64 encoded value of the 3scale portal endpoint using this format "https://access-token@test-admin.3scale.net" 17 | value: 18 | name: APICAST_CONFIGURATION_URL_BASE64 19 | required: true 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "markdown-link-check": "3.10.2" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /rockspec: -------------------------------------------------------------------------------- 1 | package = "apicast-test" 2 | source = { url = '.' } 3 | version = '0.0-0' 4 | dependencies = { 5 | 'busted >= 0', 6 | 'ldoc >= 0', 7 | 'lua-resty-repl >= 0', 8 | 'lua-resty-iputils == 0.3.0-1', -- just as dev dependency before gets bumped to runtime 9 | } 10 | build = { 11 | type = "builtin", 12 | modules = { } 13 | } 14 | -------------------------------------------------------------------------------- /script/install/apicast.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x -e 4 | pip install --user hererocks 5 | 6 | if [ -n "$1" ]; then 7 | cd "$1" 8 | fi 9 | 10 | "$HOME/.local/bin/hererocks" lua_modules -r^ -l 5.1 --no-readline 11 | curl -L https://raw.githubusercontent.com/3scale/s2i-openresty/ffb1c55533be866a97466915d7ef31c12bae688c/site_config.lua -o lua_modules/share/lua/5.1/luarocks/site_config.lua 12 | make lua_modules cpan 13 | 14 | mkdir -p ~/.systemtap 15 | # needed for complete backtraces 16 | # increase this if you start seeing stacks collapsed in impossible ways 17 | # also try https://github.com/openresty/stapxx/commit/59ba231efba8725a510cd8d1d585aedf94670404 18 | # to avoid MAXACTTION problems 19 | cat <<- EOF > ~/.systemtap/rc 20 | -D MAXSTRINGLEN=1024 21 | EOF 22 | -------------------------------------------------------------------------------- /script/install/centos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x -e 4 | 5 | # Old Centos packages are moved to vault.centos.org 6 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-Stream-* 7 | sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* 8 | 9 | yum install -y yum-utils 10 | yum-config-manager --enable "powertools" 11 | 12 | # Remove lua 5.3 13 | yum remove -y lua 14 | 15 | # install build and runtime dependencies 16 | yum -y install gcc gcc-c++ make m4 git which iputils bind-utils expat-devel m4\ 17 | wget tar unzip libyaml libyaml-devel \ 18 | perl-local-lib perl-App-cpanminus \ 19 | openssl-devel libev-devel \ 20 | kernel-headers kernel-devel kernel-debug \ 21 | redis systemtap \ 22 | python2-pip elfutils-devel 23 | 24 | dnf --enablerepo="debuginfo" debuginfo-install -y "kernel-core-$(uname -r)" 25 | -------------------------------------------------------------------------------- /script/luacov: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -euo pipefail 3 | 4 | stats=$1 5 | pid=$(echo "$stats" | awk -F"." '{print $4}') 6 | 7 | mv -v "$stats" luacov.stats.out 8 | luacov 9 | mv -v luacov.report.out "luacov.report.${pid}.out" 10 | rm luacov.stats.out 11 | -------------------------------------------------------------------------------- /script/profiling/configs/echo_config.lua: -------------------------------------------------------------------------------- 1 | local cjson = require('cjson') 2 | 3 | local configuration = cjson.encode(cjson.decode([[{ 4 | "services": [ 5 | { 6 | "proxy": { 7 | "hosts": [ 8 | "localhost", 9 | "127.0.0.1" 10 | ], 11 | "policy_chain": [ 12 | { "name": "apicast.policy.echo" } 13 | ] 14 | } 15 | } 16 | ] 17 | } 18 | ]])) 19 | 20 | local function data_url(mime_type, content) 21 | return string.format([[data:%s,%s]],mime_type, ngx.escape_uri(content)) 22 | end 23 | 24 | return { 25 | worker_processes = '1', 26 | lua_code_cache = 'on', 27 | configuration = data_url('application/json', configuration), 28 | port = { apicast = 9000, echo = 9001, management = 9002, backend = 9003 }, 29 | timer_resolution = false, 30 | } 31 | 32 | -------------------------------------------------------------------------------- /script/profiling/configs/profile_apicast_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "proxy": { 5 | "policy_chain": [ 6 | { "name": "apicast.policy.upstream", 7 | "configuration": { 8 | "rules": [{ 9 | "regex": "/", 10 | "url": "http://127.0.0.1:9001" 11 | }] 12 | } 13 | } 14 | ] 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /script/prove: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | coverage='luacov.stats.*.out' 5 | 6 | generate_coverage() { 7 | find . -maxdepth 1 -name "$coverage" -exec script/luacov '{}' \; 8 | } 9 | trap generate_coverage EXIT 10 | 11 | # shellcheck disable=SC2086 12 | rm -f $coverage luacov.report.*.out 13 | 14 | if [ -n "${JUNIT_OUTPUT_FILE:-}" ]; then 15 | mkdir -p "$(dirname "$JUNIT_OUTPUT_FILE")" 16 | fi 17 | 18 | TMPFILE=$(mktemp) || exit 1 19 | prove "$@" 2>&1 | tee $TMPFILE 20 | # No need to capture exit code. set -e option instructs bash to immediately exit if any command has a non-zero exit status 21 | if [ -n "${CI:-}" ]; then 22 | cat "${TMPFILE}" | awk '/found ONLY/ { print "FAIL: because found ONLY in test"; print; exit 1 }; { print }' 23 | status="$?" 24 | if [ $status -gt 0 ]; then 25 | echo "Failure. Exit code: ${status}" 26 | exit $status 27 | fi 28 | fi 29 | 30 | echo "Success" 31 | -------------------------------------------------------------------------------- /script/redis: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | exec resty -I apicast/src script/redis.lua "$@" 4 | -------------------------------------------------------------------------------- /script/redis.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env resty -I apicast/src 2 | 3 | local cmd = arg[1] 4 | local args = {} 5 | 6 | for i=2, #arg do 7 | table.insert(args, arg[i]) 8 | end 9 | 10 | if not cmd then 11 | print('missing command') 12 | print('usage: ' .. arg[0] .. ' cmd [arg [arg ...]]') 13 | os.exit(1) 14 | end 15 | 16 | local inspect = require 'inspect' 17 | local ts = require 'threescale_utils' 18 | 19 | local red, connerr = ts.connect_redis() 20 | 21 | if not red and connerr then 22 | print('could not connect to redis: ', connerr) 23 | os.exit(1) 24 | end 25 | 26 | local fn = red[cmd] 27 | local res, err = fn(red, unpack(args)) 28 | 29 | if res then 30 | print(inspect(res)) 31 | end 32 | 33 | if err then 34 | print('error: ', err) 35 | os.exit(1) 36 | end 37 | -------------------------------------------------------------------------------- /script/reorder-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | if ARGF.filename == '-' 4 | ARGV.replace(Dir['t/*.t']) 5 | end 6 | 7 | ARGF.inplace_mode = '' 8 | 9 | tests = Hash.new(0) 10 | 11 | ARGF.each_line do |line| 12 | print line.sub(/^=== TEST (\d+):/) { "=== TEST #{tests[ARGF.filename] += 1}:" } 13 | end 14 | -------------------------------------------------------------------------------- /script/resolver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | exec resty -I gateway/src script/resolver.lua "$@" 4 | -------------------------------------------------------------------------------- /script/resolver.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env resty -I apicast/src 2 | 3 | local inspect = require 'inspect' 4 | 5 | local resty_resolver = require 'resty.resolver' 6 | 7 | local r = resty_resolver:instance() 8 | 9 | local host = arg[1] 10 | 11 | if not host then 12 | print('missing host') 13 | print('usage: ' .. arg[0] .. ' example.com') 14 | os.exit(1) 15 | end 16 | 17 | local servers, err = r:get_servers(host) 18 | 19 | if err then 20 | print('error: ', err) 21 | print(inspect(r)) 22 | os.exit(1) 23 | end 24 | 25 | print(inspect(servers)) 26 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | COMMAND=$1 4 | PROJECT_PATH=${PROJECT_PATH-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )} 5 | ROVER=${ROVER-/usr/local/openresty/luajit/bin/rover} 6 | 7 | function run_busted_tests { 8 | cd "${PROJECT_PATH}" || exit 9 | ${ROVER} exec ./bin/busted 10 | } 11 | 12 | function run_nginx_unit_tests { 13 | cd "${PROJECT_PATH}" || exit 14 | 15 | "${ROVER}" exec prove 16 | 17 | # Text::Nginx runs nginx in the t/servroot dir. Clean it. 18 | rm -rf "${PROJECT_PATH}/t/servroot" 19 | } 20 | 21 | function run_all_tests { 22 | run_busted_tests 23 | run_nginx_unit_tests 24 | } 25 | 26 | case "${COMMAND}" in 27 | busted) 28 | run_busted_tests 29 | ;; 30 | nginx) 31 | run_nginx_unit_tests 32 | ;; 33 | *) 34 | run_all_tests 35 | ;; 36 | esac 37 | -------------------------------------------------------------------------------- /script/traces/Readme.md: -------------------------------------------------------------------------------- 1 | # Trace scripts 2 | 3 | A few trace scripts to run bpftrace tool in the container and be able to debug 4 | how Nginx behave 5 | 6 | ## Install 7 | 8 | ```shell 9 | docker exec -ti --user root --privileged apicast_build_0_development_1 dnf install -y bpftrace 10 | ``` 11 | 12 | Recommended to install debuginfo packages to get better ustack 13 | 14 | ``` 15 | docker exec -ti --user root --privileged apicast_build_0_development_1 dnf install -y openresty-debuginfo 16 | ``` 17 | 18 | 19 | ## Run 20 | 21 | ```shell 22 | docker exec -ti --user root --privileged apicast_build_0_development_1 bpftrace leaked.bt -p ${OPENRESTY_WORKER_PID} 23 | ``` 24 | -------------------------------------------------------------------------------- /script/traces/leaked.st: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | printf("Probe started\n"); 3 | } 4 | 5 | uretprobe:/usr/local/openresty/nginx/sbin/nginx:ngx_create_pool { 6 | @pools[retval] = ustack ; 7 | } 8 | 9 | uprobe:/usr/local/openresty/nginx/sbin/nginx:ngx_destroy_pool { 10 | delete(@pools[arg0]); 11 | } 12 | 13 | interval:s:60 { 14 | printf("--------------\n"); 15 | print(@pools); 16 | } 17 | -------------------------------------------------------------------------------- /spec/ci_reporter.lua: -------------------------------------------------------------------------------- 1 | local TAP = require('busted.outputHandlers.TAP') 2 | local JUnit = require('busted.outputHandlers.junit') 3 | 4 | 5 | return function(options) 6 | local handler = require 'busted.outputHandlers.base'() 7 | 8 | local tap = TAP(setmetatable({ }, { __index = options })) 9 | local junit = JUnit(setmetatable({ 10 | arguments = { os.getenv('JUNIT_OUTPUT_FILE') }, 11 | }, { __index = options })) 12 | 13 | function handler.subscribe(_, ...) 14 | tap:subscribe(...) 15 | junit:subscribe(...) 16 | end 17 | 18 | return handler 19 | end 20 | -------------------------------------------------------------------------------- /spec/cli/environment_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.cli.environment') 2 | 3 | describe('Environment Configuration', function () 4 | 5 | describe('.new', function() 6 | it('accepts default', function() 7 | local default = { foo = 'bar' } 8 | local env = _M.new(default) 9 | 10 | assert.contains(default, env:context()) 11 | end) 12 | end) 13 | 14 | end) 15 | -------------------------------------------------------------------------------- /spec/cli/template_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.cli.template') 2 | 3 | describe('Liquid Template', function () 4 | 5 | describe('default filter', function() 6 | it('overrides nil values', function() 7 | local str = _M:new():interpret([[{{ nothing | default: "foo" }}]]) 8 | 9 | assert.equal(str, 'foo') 10 | end) 11 | 12 | it('overrides false values', function() 13 | local str = _M:new():interpret([[{{ false | default: "foo" }}]]) 14 | 15 | assert.equal(str, 'false') 16 | end) 17 | end) 18 | 19 | end) 20 | -------------------------------------------------------------------------------- /spec/configuration_loader/file_spec.lua: -------------------------------------------------------------------------------- 1 | local loader = require 'apicast.configuration_loader.file' 2 | 3 | describe('Configuration File loader', function() 4 | describe('.call', function() 5 | it('ignores empty path', function() 6 | assert.same({nil, 'invalid or missing path'}, { loader.call() }) 7 | assert.same({nil, 'invalid or missing path'}, { loader.call('') }) 8 | end) 9 | 10 | it('reads a file', function() 11 | assert.truthy(loader.call('fixtures/config.json')) 12 | end) 13 | 14 | it('reads absolute path', function() 15 | local pl_path = require('pl.path') 16 | local _, path = loader.call('fixtures/config.json') 17 | 18 | assert.match(pl_path.currentdir(), path, nil, true) 19 | end) 20 | end) 21 | end) 22 | -------------------------------------------------------------------------------- /spec/configuration_loader/mock_spec.lua: -------------------------------------------------------------------------------- 1 | local loader = require 'apicast.configuration_loader.mock' 2 | 3 | describe('Configuration Mock loader', function() 4 | describe('.call', function() 5 | after_each(function() loader.config = nil end) 6 | 7 | it('returns saved config', function() 8 | local config = { 'config ' } 9 | 10 | loader.config = config 11 | 12 | assert.equal(config, loader.call()) 13 | end) 14 | 15 | it('saves config', function() 16 | local config = { 'config' } 17 | 18 | loader.save(config) 19 | 20 | assert.equal(config, loader.config) 21 | end) 22 | end) 23 | end) 24 | -------------------------------------------------------------------------------- /spec/errors_spec.lua: -------------------------------------------------------------------------------- 1 | local errors = require 'apicast.errors' 2 | local Service = require 'apicast.configuration.service' 3 | 4 | describe('Errors', function() 5 | describe('.limits_exceeded', function() 6 | before_each(function() 7 | ngx.var = {} 8 | ngx.header = {} 9 | end) 10 | 11 | local test_service = Service.new({ id = 1 }) 12 | 13 | it('sets the Retry-After header when a value for it is received', function() 14 | local retry_after = 60 15 | 16 | errors.limits_exceeded(test_service, retry_after) 17 | 18 | assert.equals(retry_after, ngx.header['Retry-After']) 19 | end) 20 | 21 | it('does not set the Retry-After header when a value for it is not received', function() 22 | errors.limits_exceeded(test_service) 23 | 24 | assert.is_nil(ngx.header['Retry-After']) 25 | end) 26 | end) 27 | end) 28 | -------------------------------------------------------------------------------- /spec/examples/custom-module/blacklist_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require 'examples.custom-module.blacklist' 2 | local apicast = require 'apicast.policy.apicast' 3 | 4 | describe('blacklist', function() 5 | it('returns new module instance', function() 6 | local blacklist = _M.new() 7 | 8 | assert.table(blacklist) 9 | assert.equal(_M.balancer, blacklist.balancer) 10 | assert.equal(_M.init, blacklist.init) 11 | end) 12 | 13 | it('has all apicast methods', function() 14 | local blacklist = _M.new() 15 | 16 | assert['function'](blacklist.init) 17 | 18 | for _,fun in ipairs{'init_worker', 'rewrite', 'post_action', 'access', 'log'} do 19 | assert.equal(apicast[fun], blacklist[fun], fun .. " is not inherited from apicast") 20 | end 21 | 22 | assert['function'](blacklist.balancer) 23 | end) 24 | end) 25 | -------------------------------------------------------------------------------- /spec/fake_backend_helper.lua: -------------------------------------------------------------------------------- 1 | local fake_backend = {} 2 | 3 | function fake_backend.new(response) 4 | local backend = { requests = {} } 5 | 6 | backend.send = function(_, request) 7 | backend.requests[#backend.requests + 1] = request 8 | backend.last_request = request 9 | 10 | if response then 11 | return response(request) 12 | else 13 | return { request = request, status = 200 } 14 | end 15 | end 16 | 17 | return backend 18 | end 19 | 20 | 21 | return fake_backend 22 | -------------------------------------------------------------------------------- /spec/fixtures/echo.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 1984 default_server; 3 | server_name _; 4 | 5 | location / { 6 | echo_duplicate 1 $echo_client_request_headers; 7 | echo "\r"; 8 | echo_read_request_body; 9 | echo $request_body; 10 | } 11 | 12 | location /json { 13 | echo "{}"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/1.0.0-0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy", 4 | "summary": "An example policy to be used in unit tests.", 5 | "version": "1.0.0-0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/1.0.0-0/dependency.lua: -------------------------------------------------------------------------------- 1 | return { 2 | '1.0 dependency' 3 | } 4 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/1.0.0-0/init.lua: -------------------------------------------------------------------------------- 1 | return require('test') 2 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/1.0.0-0/test.lua: -------------------------------------------------------------------------------- 1 | local Policy = require('apicast.policy').new('Test', '1.0.0-0') 2 | 3 | Policy.dependency = require('dependency') 4 | 5 | return Policy 6 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/2.0.0-0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy", 4 | "summary": "An example policy to be used in unit tests.", 5 | "version": "2.0.0-0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/2.0.0-0/dependency.lua: -------------------------------------------------------------------------------- 1 | return { 2 | '2.0 dependency' 3 | } 4 | -------------------------------------------------------------------------------- /spec/fixtures/policies/test/2.0.0-0/init.lua: -------------------------------------------------------------------------------- 1 | local Policy = require('apicast.policy').new('Test', '1.0.0-0') 2 | 3 | Policy.dependency = require('dependency') 4 | 5 | return Policy 6 | -------------------------------------------------------------------------------- /spec/fixtures/standalone/invalid.json: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- /spec/fixtures/standalone/invalid.txt: -------------------------------------------------------------------------------- 1 | txt is not valid at all 2 | -------------------------------------------------------------------------------- /spec/fixtures/standalone/invalid.yml: -------------------------------------------------------------------------------- 1 | global: 2 | - array 3 | another: object 4 | -------------------------------------------------------------------------------- /spec/fixtures/standalone/valid.json: -------------------------------------------------------------------------------- 1 | { "global": [] } 2 | -------------------------------------------------------------------------------- /spec/fixtures/standalone/valid.yml: -------------------------------------------------------------------------------- 1 | global: 2 | -------------------------------------------------------------------------------- /spec/jwt_helper.lua: -------------------------------------------------------------------------------- 1 | local busted = require('busted') 2 | 3 | local jwt_validators = require 'resty.jwt-validators' 4 | local ngx_now = ngx.now 5 | 6 | busted.before_each(function() 7 | jwt_validators.set_system_clock(ngx_now) 8 | end) 9 | 10 | local oidc = require('apicast.oauth.oidc') 11 | 12 | busted.before_each(oidc.reset) 13 | -------------------------------------------------------------------------------- /spec/policy/clear_context/clear_context_spec.lua: -------------------------------------------------------------------------------- 1 | local ClearContextPolicy = require('apicast.policy.clear_context') 2 | local ngx_variable = require('apicast.policy.ngx_variable') 3 | 4 | 5 | describe('Clear Context policy', function() 6 | local current_ctx = {some_key = 'some_value'} 7 | 8 | describe('log phase context reset', function() 9 | before_each(function() 10 | ctx = ngx.ctx 11 | stub(ngx_variable, 'available_context', function(context) return context end) 12 | end) 13 | 14 | context('.ssl_certificate', function() 15 | local clear_context_policy = ClearContextPolicy.new() 16 | 17 | it('clears the context', function() 18 | ctx.current = current_ctx 19 | clear_context_policy:ssl_certificate(ctx) 20 | assert.is_nil(ctx.current) 21 | end) 22 | end) 23 | end) 24 | end) 25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/policy/echo/echo_spec.lua: -------------------------------------------------------------------------------- 1 | local EchoPolicy = require('apicast.policy.echo') 2 | 3 | describe('Echo policy', function() 4 | describe('.rewrite', function() 5 | describe('when configured with exit=request', function() 6 | it('stops processing the request and returns with the configured status', function() 7 | local ngx_exit_spy = spy.on(ngx, 'exit') 8 | local status = 200 9 | local echo = EchoPolicy.new({ status = status, exit = 'request' }) 10 | 11 | echo:rewrite() 12 | 13 | assert.spy(ngx_exit_spy).was_called_with(status) 14 | end) 15 | end) 16 | 17 | describe('when configured with exit=phase', function() 18 | it('skips the current phase', function() 19 | local ngx_exit_spy = spy.on(ngx, 'exit') 20 | local echo = EchoPolicy.new({ status = 200, exit = 'phase' }) 21 | 22 | echo:rewrite() 23 | 24 | assert.spy(ngx_exit_spy).was_called_with(0) 25 | end) 26 | end) 27 | end) 28 | end) 29 | -------------------------------------------------------------------------------- /spec/policy/load_configuration/load_configuration_spec.lua: -------------------------------------------------------------------------------- 1 | describe('load_configuration', function() 2 | describe('.new', function() 3 | it('initializes the policy with a configuration') 4 | local load_config_policy = require('apicast.policy.load_configuration').new() 5 | assert.not_nil(load_config_policy) 6 | end) 7 | 8 | describe('.export', function() 9 | it('returns a table with the configuration of the policy', function() 10 | local load_config_policy = require('apicast.policy.load_configuration').new() 11 | assert.same(load_config_policy.configuration , load_config_policy:export().configuration) 12 | end) 13 | end) 14 | 15 | -- TODO: test .init(), .init_worker(), and .rewrite(). Right now it is 16 | -- difficult because of the coupling with configuration_store. 17 | end) 18 | -------------------------------------------------------------------------------- /spec/policy/management/management_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy.management') 2 | 3 | describe('management policy', function() 4 | describe('.new', function() 5 | it('works without configuration', function() 6 | assert(_M.new()) 7 | end) 8 | 9 | it('accepts configuration', function() 10 | assert(_M.new({ })) 11 | end) 12 | end) 13 | end) 14 | -------------------------------------------------------------------------------- /spec/policy/retry/retry_spec.lua: -------------------------------------------------------------------------------- 1 | local RetryPolicy = require('apicast.policy.retry') 2 | 3 | describe('Retry policy', function() 4 | describe('.export', function() 5 | it('returns the the number of retries', function() 6 | local policy_config = { retries = 5, } 7 | local policy = RetryPolicy.new(policy_config) 8 | local context = {} 9 | 10 | policy:rewrite(context) 11 | 12 | assert.same(policy_config.retries, context.upstream_retries) 13 | end) 14 | end) 15 | end) 16 | -------------------------------------------------------------------------------- /spec/policy/standalone/standalone_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy.standalone') 2 | 3 | describe('standalone policy', function() 4 | describe('.new', function() 5 | it('works without configuration', function() 6 | assert(_M.new()) 7 | end) 8 | 9 | it('accepts configuration', function() 10 | assert(_M.new({ })) 11 | end) 12 | end) 13 | end) 14 | -------------------------------------------------------------------------------- /spec/resty/concurrent/immediate_executor_spec.lua: -------------------------------------------------------------------------------- 1 | local ImmediateExecutor = require('resty.concurrent.immediate_executor') 2 | 3 | describe('ImmediateExecutor', function() 4 | describe(':post', function() 5 | it('executes in the same coroutine', function() 6 | local fun = coroutine.running 7 | 8 | assert.equal(fun(), ImmediateExecutor:post(fun)) 9 | end) 10 | end) 11 | end) 12 | -------------------------------------------------------------------------------- /spec/resty/http/uri_escape_spec.lua: -------------------------------------------------------------------------------- 1 | local escape = require("resty.http.uri_escape") 2 | 3 | describe('resty.http.uri_escape', function() 4 | 5 | it("escapes uri correctly", function() 6 | local test_cases = { 7 | {"/foo /test", "/foo%20/test"}, 8 | {"/foo/test", "/foo/test"}, 9 | {"/foo/", "/foo/"}, 10 | {"/foo / test", "/foo%20/%20test"}, 11 | {"/foo / test", "/foo%20%20%20%20/%20%20test"}, 12 | {"/foo#/test", "/foo%23/test"}, 13 | {"/foo$/test", "/foo$/test"}, 14 | {"/foo=/test", "/foo=/test"}, 15 | {"/foo!/test", "/foo!/test"} , 16 | {"/foo,/test", "/foo,/test"}, 17 | } 18 | 19 | for _,val in ipairs(test_cases) do 20 | assert.are.same(escape.escape_uri(val[1]), val[2]) 21 | end 22 | end) 23 | end) 24 | -------------------------------------------------------------------------------- /spec/resty/http_ng/response_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require 'resty.http_ng.response' 2 | local request = require 'resty.http_ng.request' 3 | 4 | describe('http_ng response', function() 5 | 6 | describe('error', function() 7 | 8 | local req = request.new{ method = 'GET', url = 'http://example.com' } 9 | 10 | it('has the request', function() 11 | local error = _M.error(req, 'failed') 12 | 13 | assert.equal(req, error.request) 14 | end) 15 | 16 | 17 | it('has the message', function() 18 | local error = _M.error(req, 'error message') 19 | 20 | assert.equal('error message', error.error) 21 | end) 22 | end) 23 | 24 | describe('response without date', function() 25 | it('creates default date', function() 26 | local res = _M.new(nil, 200, {}, '') 27 | 28 | assert.truthy(ngx.parse_http_time(res.headers.date)) 29 | end) 30 | end) 31 | end) 32 | -------------------------------------------------------------------------------- /spec/resty/resolver/dns_client_spec.lua: -------------------------------------------------------------------------------- 1 | local dns_client = require 'resty.resolver.dns_client' 2 | 3 | describe('resty.resolver.dns_client', function() 4 | 5 | describe(':init_resolvers #network', function() 6 | it('is called only once', function() 7 | local dns = dns_client:new{ nameservers = { '127.0.0.1' } } 8 | local s = spy.on(dns, 'init_resolvers') 9 | 10 | dns:query('www.3scale.net', { qtype = dns.TYPE_A }) 11 | dns:query('www.3scale.net', { qtype = dns.TYPE_A }) 12 | 13 | assert.spy(s).was.called(1) 14 | end) 15 | 16 | it('handles invalid resolvers', function() 17 | local nameservers = { 18 | 'invalid', 19 | '256.0.0.0', 20 | '127.0.0.1', 21 | } 22 | local dns = dns_client:new{nameservers = nameservers } 23 | local resolvers = assert(dns:init_resolvers()) 24 | 25 | assert.equal(1, #resolvers) 26 | end) 27 | end) 28 | 29 | end) 30 | -------------------------------------------------------------------------------- /spec/resty/resolver/http_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require 'resty.resolver.http' 2 | 3 | describe('resty.resolver.http', function() 4 | 5 | describe('.new', function() 6 | it('initializes client', function() 7 | local client = _M.new() 8 | 9 | assert.truthy(client) 10 | end) 11 | end) 12 | 13 | describe(':connect', function() 14 | it('resolves localhost', function() 15 | local client = _M.new() 16 | client:set_timeout(1000) 17 | client.resolver.cache:save('unknown', 1, { { address = '127.0.0.1', name = 'unknown.', ttl = 1800 , type=1} }) 18 | assert(client:connect({scheme="http", host='unknown', port=1984})) 19 | assert.equal('unknown', client.host) 20 | assert.equal(1984, client.port) 21 | end) 22 | end) 23 | 24 | end) 25 | -------------------------------------------------------------------------------- /spec/resty/resolver/socket_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require 'resty.resolver.socket' 2 | 3 | describe('resty.resolver.socket', function() 4 | 5 | describe('.new', function() 6 | it('initializes client', function() 7 | local wrapper = _M.new(ngx.socket.tcp()) 8 | 9 | assert.truthy(wrapper) 10 | end) 11 | end) 12 | 13 | describe(':connect', function() 14 | it('resolves localhost', function() 15 | local sock = ngx.socket.tcp() 16 | sock:settimeout(1000) 17 | local wrapper = _M.new(sock) 18 | 19 | wrapper.resolver.cache:save('unknown', 1, { { address = '127.0.0.1', name = 'unknown.', ttl = 1800, type = 1} }) 20 | assert(wrapper:connect('unknown', 1984)) 21 | assert.equal('unknown', wrapper.host) 22 | assert.equal(1984, wrapper.port) 23 | end) 24 | end) 25 | 26 | end) 27 | -------------------------------------------------------------------------------- /spec/resty/yaml_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require 'resty.yaml' 2 | 3 | describe('Resty YAML', function() 4 | describe('.load', function() 5 | it('loads yaml', function() 6 | assert.same({ global = _M.null }, _M.load('global: ')) 7 | end) 8 | end) 9 | 10 | describe('.null', function() 11 | it('is ngx.null', function () 12 | assert.equal(ngx.null, _M.null) 13 | end) 14 | end) 15 | end) 16 | -------------------------------------------------------------------------------- /spec/ssl_helper.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | ffi.cdef([[ 5 | typedef long time_t; 6 | typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; 7 | typedef struct x509_store_st X509_STORE; 8 | X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); 9 | void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); 10 | ]]) 11 | 12 | local SSL = {} 13 | 14 | function SSL.set_time(store, seconds) 15 | local verify_param = C.X509_STORE_get0_param(store) 16 | C.X509_VERIFY_PARAM_set_time(verify_param, seconds) 17 | end 18 | 19 | return SSL 20 | -------------------------------------------------------------------------------- /spec/threescale_utils_spec.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.threescale_utils') 2 | 3 | describe('3scale utils', function() 4 | describe('.error', function() 5 | it('returns concatenated error in timer phase', function() 6 | local get_phase = spy.on(ngx, 'get_phase', function() return 'timer' end) 7 | local error = _M.error('one', ' two', ' three') 8 | 9 | assert.spy(get_phase).was_called(1) 10 | 11 | assert.equal('one two three', error) 12 | end) 13 | end) 14 | end) 15 | -------------------------------------------------------------------------------- /t/apicast-bin.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | run_tests(); 5 | 6 | __DATA__ 7 | 8 | === TEST 1: Empty APICAST_LOG_LEVEL does not crash APIcast. 9 | --- env eval 10 | ( 11 | 'APICAST_LOG_LEVEL' => '', 12 | ) 13 | 14 | --- configuration fixture=echo.json 15 | --- request 16 | GET / 17 | --- error_code: 200 18 | -------------------------------------------------------------------------------- /t/apicast-policy-chains-crash.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | $ENV{APICAST_ACCESS_LOG_FILE} = "$Test::Nginx::Util::ErrLogFile"; 5 | $ENV{APICAST_POLICY_LOAD_PATH} = 't/fixtures/policies'; 6 | 7 | repeat_each(1); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: policy chain with a policy that crashes on new() 13 | Policies that crash when initialized should be removed from the chain 14 | --- configuration 15 | { 16 | "services": [ 17 | { 18 | "id": 42, 19 | "proxy": { 20 | "policy_chain" : [ 21 | { "name" : "error_policy", "version" : "1.0.0" }, 22 | { "name" : "apicast.policy.echo" } 23 | ] 24 | } 25 | } 26 | ] 27 | } 28 | --- request 29 | GET /test 30 | --- response_body 31 | GET /test HTTP/1.1 32 | --- error_code: 200 33 | --- error_log 34 | Policy error_policy crashed in .new() 35 | -------------------------------------------------------------------------------- /t/apicast-policy-management.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | run_tests(); 5 | 6 | __DATA__ 7 | 8 | === TEST 1: management accepts configuration 9 | --- configuration 10 | { 11 | "services": [ 12 | { 13 | "proxy": { 14 | "policy_chain": [ 15 | { "name": "apicast.policy.management", 16 | "configuration": { } } 17 | ] 18 | } 19 | } 20 | ] 21 | } 22 | --- request 23 | GET /status/info 24 | --- error_code: 200 25 | --- no_error_log 26 | [error] 27 | -------------------------------------------------------------------------------- /t/backend.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast 'no_plan'; 3 | 4 | run_tests(); 5 | 6 | __DATA__ 7 | 8 | === TEST 1: backend 9 | This is just a simple demonstration of the 10 | echo directive provided by ngx_http_echo_module. 11 | --- config 12 | include $TEST_NGINX_BACKEND_CONFIG; 13 | --- request 14 | GET /transactions/authrep.xml 15 | --- response_body 16 | transactions authrep! 17 | --- error_code: 200 18 | -------------------------------------------------------------------------------- /t/balancer.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast 'no_plan'; 3 | 4 | $ENV{TEST_NGINX_HTTP_CONFIG} = "$Test::APIcast::path/http.d/*.conf"; 5 | $ENV{RESOLVER} = '127.0.1.1:5353'; 6 | 7 | env_to_nginx( 8 | 'RESOLVER' 9 | ); 10 | master_on(); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: round robin does not leak memory 16 | Balancing different hosts does not leak memory. 17 | --- http_config 18 | lua_package_path "$TEST_NGINX_LUA_PATH"; 19 | init_by_lua_block { 20 | require('resty.balancer.round_robin').cache_size = 1 21 | } 22 | --- config 23 | location = /t { 24 | content_by_lua_block { 25 | local round_robin = require('resty.balancer.round_robin') 26 | local balancer = round_robin.new() 27 | 28 | local peers = { hash = ngx.var.request_id, cur = 1, 1, 2 } 29 | local peer = round_robin.call(peers) 30 | 31 | ngx.print(peer) 32 | } 33 | } 34 | --- pipelined_requests eval 35 | [ "GET /t", "GET /t" ] 36 | --- response_body eval 37 | [ "1", "1" ] 38 | -------------------------------------------------------------------------------- /t/configuration-loading-boot-staging.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | $ENV{THREESCALE_DEPLOYMENT_ENV} = 'staging'; 5 | $ENV{APICAST_CONFIGURATION_LOADER} = 'boot'; 6 | $ENV{APICAST_CONFIGURATION_CACHE} = ''; 7 | 8 | filters { configuration => 'fixture=echo.json' }; 9 | 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: 'boot' config loader in staging deployment env without config cache 15 | Test that APIcast does not crash when using the 'boot' config loader and the 16 | 'staging' deployment env without a config cache value. 17 | This is a regression test. APIcast was setting a 0 as the default value for the 18 | config cache which is incompatible with the 'boot' loader method, and it 19 | crashed as a result. 20 | --- configuration 21 | --- request 22 | GET /test 23 | --- response_body 24 | GET /test HTTP/1.1 25 | X-Real-IP: 127.0.0.1 26 | Host: echo 27 | --- error_code: 200 28 | --- no_error_log 29 | [error] 30 | -------------------------------------------------------------------------------- /t/configuration-loading-boot-without-config.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast 'no_plan'; 3 | 4 | $ENV{TEST_NGINX_HTTP_CONFIG} = "$Test::APIcast::path/http.d/init.conf"; 5 | $ENV{APICAST_CONFIGURATION_LOADER} = 'boot'; 6 | 7 | env_to_nginx( 8 | 'APICAST_CONFIGURATION_LOADER', 9 | 'TEST_NGINX_APICAST_PATH', 10 | 'THREESCALE_CONFIG_FILE' 11 | ); 12 | 13 | log_level('emerg'); 14 | run_tests(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: require configuration on boot 19 | should exit with error if there is no configuration 20 | --- http_config 21 | include $TEST_NGINX_HTTP_CONFIG; 22 | lua_package_path "$TEST_NGINX_LUA_PATH"; 23 | --- config 24 | --- must_die 25 | --- request 26 | GET 27 | --- error_log 28 | failed to load configuration, exiting 29 | -------------------------------------------------------------------------------- /t/custom-config.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | $ENV{APICAST_CUSTOM_CONFIG} = "$Test::Nginx::Util::HtmlDir/custom.lua"; 5 | 6 | env_to_nginx('APICAST_CUSTOM_CONFIG'); 7 | 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: loading custom config file works 13 | --- configuration 14 | {} 15 | --- upstream 16 | location /t { 17 | content_by_lua_block { 18 | path = package.path 19 | require('apicast.proxy') 20 | assert(path == package.path) 21 | package.loaded['apicast.proxy'] = nil 22 | ngx.exit(ngx.HTTP_OK) 23 | } 24 | } 25 | --- upstream_name 26 | ctx 27 | --- more_headers 28 | Host: ctx 29 | --- request 30 | GET /t 31 | --- user_files 32 | >>> custom.lua 33 | return { setup = function() print('loaded custom.lua') end } 34 | --- error_log 35 | loaded custom.lua 36 | -------------------------------------------------------------------------------- /t/fixtures/CA/client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBmjCCAUCgAwIBAgIQUcZ+JcZiYBkY1+U2Wa3XLDAKBggqhkjOPQQDAjAaMRgw 3 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwHhcNMTkwNDA0MTEzMjU5WhcNMjkwNDAx 4 | MTEzMjU5WjARMQ8wDQYDVQQDEwZjbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMB 5 | BwNCAASsKgVvKiD+TeyRWhs3CBoGmIAFiCNplJ4JVmX7nE53HfBrqEOdnftHllCO 6 | Dm3VT2/vfFw4bDPsbGFtMZjIpCM8o3EwbzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l 7 | BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRxJJmM0Zj+HIBXBkIR 8 | 9YTJkbhFRDAfBgNVHSMEGDAWgBTaEjeKcCSJEuUcnwUlddtXhKhMcTAKBggqhkjO 9 | PQQDAgNIADBFAiABKzFUTP4MqJAGwPkdid+TCBmSXS+C2FnrSJ6aAjYbWgIhAPV3 10 | PCV/T+AylMWeL3iPq8FuaXjWNAsTC9aii6g/NAQV 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /t/fixtures/CA/client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIMOOktLiaoQeRNeEQmDalcIftZdB/GG6G0HmDI7aQ+HEoAoGCCqGSM49 3 | AwEHoUQDQgAErCoFbyog/k3skVobNwgaBpiABYgjaZSeCVZl+5xOdx3wa6hDnZ37 4 | R5ZQjg5t1U9v73xcOGwz7GxhbTGYyKQjPA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIBRzCB7wIBATAKBggqhkjOPQQDAjAaMRgwFgYDVQQDEw9pbnRlcm1lZGlhdGUt 3 | Y2EXDTI0MTAzMDA1NDQyNVoXDTM0MTAyODA1NDQyNVowRzAhAhAMx1ybLzQvkRKJ 4 | 0xUQrJteFw0yNDEwMzAwNTQ0MjVaMCICEQDD68D5lvxp5CXYFTVYWT0FFw0yNDEw 5 | MzAwNTI0MjJaoFswWTBKBgNVHSMEQzBBgBTaEjeKcCSJEuUcnwUlddtXhKhMcaEW 6 | pBQwEjEQMA4GA1UEAxMHcm9vdC1jYYIRAPvf2lJeYv9BaUhvVQzCD8wwCwYDVR0U 7 | BAQCAhACMAoGCCqGSM49BAMCA0cAMEQCIHmFVLW2NnerBataPZSmGfyfQaXsjT1W 8 | a4j7Hp+5IA2zAiBOXNqOIqElfShj6UVVc6j2geuUtkD6NLjOPRRqoEUw4A== 9 | -----END X509 CRL----- 10 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl/crlnumber: -------------------------------------------------------------------------------- 1 | 1003 2 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl/index.txt: -------------------------------------------------------------------------------- 1 | R 341028052243Z 241030052422Z C3EBC0F996FC69E425D8153558593D05 unknown /CN=client 2 | R 341028054420Z 241030054425Z 0CC75C9B2F342F911289D31510AC9B5E unknown /CN=client 3 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl/index.txt.attr: -------------------------------------------------------------------------------- 1 | unique_subject = yes 2 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl/index.txt.old: -------------------------------------------------------------------------------- 1 | R 341028052243Z 241030052422Z C3EBC0F996FC69E425D8153558593D05 unknown /CN=client 2 | -------------------------------------------------------------------------------- /t/fixtures/CA/crl/serial: -------------------------------------------------------------------------------- 1 | 1000 2 | -------------------------------------------------------------------------------- /t/fixtures/CA/intermediate-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBkTCCATegAwIBAgIRAPvf2lJeYv9BaUhvVQzCD8wwCgYIKoZIzj0EAwIwEjEQ 3 | MA4GA1UEAxMHcm9vdC1jYTAeFw0xOTA0MDQxMTMyNTlaFw0yOTA0MDExMTMyNTla 4 | MBoxGDAWBgNVBAMTD2ludGVybWVkaWF0ZS1jYTBZMBMGByqGSM49AgEGCCqGSM49 5 | AwEHA0IABAWpNxVoU+FB6ESOOqt1knztvYdjDFlzvtrOPHJz3Meo2JnMUzINPiIV 6 | FHJkXtSStRKHuB/Lw2vj/gH0AJPg5CKjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNV 7 | HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTaEjeKcCSJEuUcnwUlddtXhKhMcTAf 8 | BgNVHSMEGDAWgBRfJt1t0sAlUMBwfeTWVv2v4XNcNjAKBggqhkjOPQQDAgNIADBF 9 | AiBXmwMUs2/CG8UdL4ThgNrZ5k+Jnd6tJagDagjS/1pIEAIhAPOI6vWuaqUU68K6 10 | 2Uvp9lVMDCS6vd3cljqeipcsOYzl 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /t/fixtures/CA/intermediate-ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIHo2cUPeDiROHNEYFm6ljYQOvHdKbleUKzOm8oYWz0aJoAoGCCqGSM49 3 | AwEHoUQDQgAEBak3FWhT4UHoRI46q3WSfO29h2MMWXO+2s48cnPcx6jYmcxTMg0+ 4 | IhUUcmRe1JK1Eoe4H8vDa+P+AfQAk+DkIg== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/CA/revoked_client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBrzCCAVWgAwIBAgIQDMdcmy80L5ESidMVEKybXjAKBggqhkjOPQQDAjAaMRgw 3 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwHhcNMjQxMDMwMDU0NDIwWhcNMzQxMDI4 4 | MDU0NDIwWjARMQ8wDQYDVQQDEwZjbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMB 5 | BwNCAAQcDPD//JMA0j46aYVdsTh5Eb5KIfNhoJcHkhVRjMbhhsZGcMD+pysHvUlQ 6 | 7lwprlYOMSXgnPJUM7IUPq9eCMvso4GFMIGCMA4GA1UdDwEB/wQEAwIHgDAdBgNV 7 | HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFNPTMaJOoyQXFMEz 8 | 6Cf7WfWFLlXxMB8GA1UdIwQYMBaAFNoSN4pwJIkS5RyfBSV121eEqExxMBEGA1Ud 9 | EQQKMAiCBmNsaWVudDAKBggqhkjOPQQDAgNIADBFAiAmcpvUCOettopMTnaCoIaX 10 | k3/Xw2GpM5OB90YWvbs69wIhAJhhK6+73p3yMu6MvTn4bSLL8eLAWrDcAuSX17vM 11 | OAOb 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /t/fixtures/CA/revoked_client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEINyI8SLVOG+ufV0+tAzwhRT9/Xe19z//O0xci/SqZJCAoAoGCCqGSM49 3 | AwEHoUQDQgAEHAzw//yTANI+OmmFXbE4eRG+SiHzYaCXB5IVUYzG4YbGRnDA/qcr 4 | B71JUO5cKa5WDjEl4JzyVDOyFD6vXgjL7A== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/CA/root-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBZjCCAQ2gAwIBAgIQBHMSmrmlj2QTqgFRa+HP3DAKBggqhkjOPQQDAjASMRAw 3 | DgYDVQQDEwdyb290LWNhMB4XDTE5MDQwNDExMzI1OVoXDTI5MDQwMTExMzI1OVow 4 | EjEQMA4GA1UEAxMHcm9vdC1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGG2 5 | NDgiBuXNVWVVxrDNVjPsKm14wg76w4830Zn3K24u03LJthzsB3RPJN9l+kM7ryjg 6 | dCenDYANVabMMQEy2iGjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG 7 | AQH/AgEBMB0GA1UdDgQWBBRfJt1t0sAlUMBwfeTWVv2v4XNcNjAKBggqhkjOPQQD 8 | AgNHADBEAiB+MlaTocrG33AiOE8TrH4N2gVrDBo2fAyJ1qDmjxhWvAIgPOoAoWQ9 9 | qwUVj52L6/Ptj0Tn4Mt6u+bdVr6jEXkZ8f0= 10 | -----END CERTIFICATE----- 11 | -------------------------------------------------------------------------------- /t/fixtures/CA/root-ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIHVw+IOhIZzhskNuXFHLQdBtoutotAQioIAniZjAWNwIoAoGCCqGSM49 3 | AwEHoUQDQgAEYbY0OCIG5c1VZVXGsM1WM+wqbXjCDvrDjzfRmfcrbi7Tcsm2HOwH 4 | dE8k32X6QzuvKOB0J6cNgA1VpswxATLaIQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/CA/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBuDCCAV6gAwIBAgIQRGgV43VB/OtJVFNcSi7KfDAKBggqhkjOPQQDAjAaMRgw 3 | FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwHhcNMTkwNDA0MTEzMjU5WhcNMjkwNDAx 4 | MTEzMjU5WjARMQ8wDQYDVQQDEwZzZXJ2ZXIwWTATBgcqhkjOPQIBBggqhkjOPQMB 5 | BwNCAAQ+prdLOpkjFm1/qh5vrqBW27HfcD4WzlwIYlzuKKCJFqGY7aEwWpv24vAg 6 | nLJBQafq8UCFgXUb3M/xKc3JADpho4GOMIGLMA4GA1UdDwEB/wQEAwIFoDAdBgNV 7 | HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFH+JSeOn3sjIbkHv 8 | D8+x7avMzZlOMB8GA1UdIwQYMBaAFNoSN4pwJIkS5RyfBSV121eEqExxMBoGA1Ud 9 | EQQTMBGCCWxvY2FsaG9zdIIEdGVzdDAKBggqhkjOPQQDAgNIADBFAiAZO1TH/Kox 10 | 0L8g95Rd44/PZ7dqcQK9s3iH7QQ0j9IrkwIhAP/GrzDCLEVkDgBO9otkqGZdGp1y 11 | CYC6AgGdCFHbLP1n 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /t/fixtures/CA/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEILYVbaRhRxvmVcVL21/DDk9bCI9cv9Z0qCjgrIhpWIpGoAoGCCqGSM49 3 | AwEHoUQDQgAEPqa3SzqZIxZtf6oeb66gVtux33A+Fs5cCGJc7iigiRahmO2hMFqb 4 | 9uLwIJyyQUGn6vFAhYF1G9zP8SnNyQA6YQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/certs/ec256_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIA8Bv35dnS289gK/lBbp0bj3LzFuvFvZowNClcUW4E84oAoGCCqGSM49 3 | AwEHoUQDQgAERm/e/qZmgIyVSksHrHh1lzf9F6WToTKnyWLfLdz8SZiaLVaI1GW3 4 | GekLwVlbKZUkmqUnKfrNs2U9DuJ3jSyX8A== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /t/fixtures/certs/ec256_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERm/e/qZmgIyVSksHrHh1lzf9F6WT 3 | oTKnyWLfLdz8SZiaLVaI1GW3GekLwVlbKZUkmqUnKfrNs2U9DuJ3jSyX8A== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /t/fixtures/certs/ec521_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MIHcAgEBBEIBEsogZYirhy12UPSwJx3ps/6j9fRHdIrqzUfz8uDz1xZ4KGm1uzyQ 3 | oB355ifR/5IriiWzai1LZM+dyR1uS8wV2qKgBwYFK4EEACOhgYkDgYYABAHzlvzU 4 | iiXqNVDBW66xFHhJgdQ3qg8qEtZbKhtjJ0gn9UCaYQeDlaL9Vxik/f+qVq0yG5A8 5 | qML+PiV8tqXvXpvJGgBwS1L5XjDrJPWkizPACi+ny7g8mkSh7d/0mixXda+bNq6T 6 | 6jS5pb9wWJqtvzWFANMP8ajEVYRh+qBLWS/42kQkAA== 7 | -----END EC PRIVATE KEY----- 8 | -------------------------------------------------------------------------------- /t/fixtures/certs/ec521_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB85b81Iol6jVQwVuusRR4SYHUN6oP 3 | KhLWWyobYydIJ/VAmmEHg5Wi/VcYpP3/qlatMhuQPKjC/j4lfLal716byRoAcEtS 4 | +V4w6yT1pIszwAovp8u4PJpEoe3f9JosV3Wvmzauk+o0uaW/cFiarb81hQDTD/Go 5 | xFWEYfqgS1kv+NpEJAA= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /t/fixtures/configs/without_nginx_metrics.lua: -------------------------------------------------------------------------------- 1 | local PolicyChain = require('apicast.policy_chain') 2 | 3 | local policies = { 4 | 'apicast.policy.load_configuration', 5 | 'apicast.policy.find_service', 6 | 'apicast.policy.local_chain' 7 | } 8 | 9 | local policy_chain = PolicyChain.build(policies) 10 | 11 | return { 12 | policy_chain = policy_chain, 13 | port = { metrics = 9421 }, 14 | } 15 | -------------------------------------------------------------------------------- /t/fixtures/echo.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [{ 3 | "proxy": { 4 | "policy_chain": [ 5 | { "name": "apicast.policy.upstream", 6 | "configuration": { "rules": [ { "regex": "/", "url": "http://echo" } ] } } 7 | ] 8 | } 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /t/fixtures/mutual_ssl.pl: -------------------------------------------------------------------------------- 1 | use File::Slurp qw(read_file); 2 | 3 | [ 4 | [ "server.crt" => CORE::join('', read_file('t/fixtures/server.crt')) ], 5 | [ "server.key" => CORE::join('', read_file('t/fixtures/server.key')) ], 6 | [ "client.crt" => CORE::join('', read_file('t/fixtures/client.crt')) ], 7 | [ "client.key" => CORE::join('', read_file('t/fixtures/client.key')) ], 8 | [ "passwords.file" => CORE::join('', read_file('t/fixtures/passwords.file')) ], 9 | ] 10 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/cfssl/ca_csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "APIcast Root CA", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "CA", 10 | "L": "Ottawa", 11 | "O": "Lua Nginx", 12 | "OU": "APIcast Root CA", 13 | "ST": "Ontario" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/cfssl/cfssl_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "ocsp_url": "https://ocsp-responder.test", 5 | "expiry": "2190000h", 6 | "usages": [ 7 | "signing", 8 | "key encipherment", 9 | "client auth" 10 | ] 11 | }, 12 | "profiles": { 13 | "ocsp": { 14 | "usages": ["digital signature", "ocsp signing"], 15 | "expiry": "876000h" 16 | }, 17 | "intermediate": { 18 | "usages": ["cert sign", "crl sign"], 19 | "expiry": "2190000h", 20 | "ca_constraint": {"is_ca": true} 21 | }, 22 | "server": { 23 | "usages": ["signing", "key encipherment", "server auth"], 24 | "expiry": "876000h" 25 | }, 26 | "client": { 27 | "usages": ["signing", "key encipherment", "client auth"], 28 | "expiry": "876000h" 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/cfssl/intermediate_ca_csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "APIcast Intermediate CA", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "CA", 10 | "L": "Ottawa", 11 | "O": "Lua Nginx", 12 | "OU": "APIcast Intermediate CA", 13 | "ST": "Ontario" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/cfssl/leaf_csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "test.com", 3 | "hosts": [ 4 | "localhost", 5 | "test" 6 | ], 7 | "key": { 8 | "algo": "rsa", 9 | "size": 2048 10 | }, 11 | "names": [ 12 | { 13 | "C": "US", 14 | "L": "San Francisco", 15 | "O": "Customer", 16 | "OU": "Website", 17 | "ST": "California" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/cfssl/ocsp_csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "APIcast OCSP Responder", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "CA", 10 | "L": "Ottawa", 11 | "O": "Lua Nginx", 12 | "OU": "APIcast OCSP Responder", 13 | "ST": "Ontario" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/files.pl: -------------------------------------------------------------------------------- 1 | use File::Slurp qw(read_file); 2 | 3 | [ 4 | [ "ca.pem" => CORE::join('', 5 | read_file('t/fixtures/ocsp/intermediate_ca.pem'), 6 | read_file('t/fixtures/ocsp/ca.pem'), 7 | ) ], 8 | [ "intermediate_ca.pem" => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) ], 9 | [ "server.pem" => CORE::join('', read_file('t/fixtures/ocsp/server.pem')) ], 10 | [ "server-key.pem" => CORE::join('', read_file('t/fixtures/ocsp/server-key.pem')) ], 11 | [ "client.pem" => CORE::join('', read_file('t/fixtures/ocsp/client.pem')) ], 12 | [ "client-key.pem" => CORE::join('', read_file('t/fixtures/ocsp/client-key.pem')) ], 13 | [ "chain.pem" => CORE::join('', read_file('t/fixtures/ocsp/chain.pem')) ], 14 | [ "wrong-issuer-order-chain.pem" => CORE::join('', read_file('t/fixtures/ocsp/wrong-issuer-order-chain.pem')) ], 15 | ] 16 | -------------------------------------------------------------------------------- /t/fixtures/ocsp/ocsp-response-good-response.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/t/fixtures/ocsp/ocsp-response-good-response.der -------------------------------------------------------------------------------- /t/fixtures/ocsp/ocsp-response-revoked-response.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3scale/APIcast/e24d3c84b3c1038701d7638923ab8b86e06874e5/t/fixtures/ocsp/ocsp-response-revoked-response.der -------------------------------------------------------------------------------- /t/fixtures/otel.toml: -------------------------------------------------------------------------------- 1 | exporter = "otlp" 2 | processor = "simple" 3 | [exporters.otlp] 4 | host = "127.0.0.1" 5 | port = 4317 6 | [service] 7 | name = "apicast" 8 | -------------------------------------------------------------------------------- /t/fixtures/passwords.file: -------------------------------------------------------------------------------- 1 | password 2 | -------------------------------------------------------------------------------- /t/fixtures/policies/deny/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Deny policy", 4 | "summary": "A policy that denies requests. To be used in integration tests.", 5 | "version": "1.0.0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | "phase": { 10 | "type": "string", 11 | "enum": [ 12 | "rewrite", 13 | "access" 14 | ] 15 | } 16 | }, 17 | "required": ["phase"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /t/fixtures/policies/deny/1.0.0/deny.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('deny', '1.0.0') 2 | 3 | local new = _M.new 4 | 5 | function _M.new(configuration) 6 | local policy = new(configuration) 7 | policy.phase = configuration.phase 8 | return policy 9 | end 10 | 11 | function _M:rewrite() 12 | if self.phase == 'rewrite' then 13 | ngx.exit(403) 14 | end 15 | end 16 | 17 | function _M:access() 18 | if self.phase == 'access' then 19 | ngx.exit(403) 20 | end 21 | end 22 | 23 | return _M 24 | -------------------------------------------------------------------------------- /t/fixtures/policies/deny/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('deny') 2 | -------------------------------------------------------------------------------- /t/fixtures/policies/error_policy/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy", 4 | "summary": "An example policy to be used in integration tests. It just raises an error", 5 | "version": "1.0.0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /t/fixtures/policies/error_policy/1.0.0/error_policy.lua: -------------------------------------------------------------------------------- 1 | local error = error 2 | 3 | local _M = require('apicast.policy').new('error_policy', '1.0.0') 4 | 5 | function _M.new() 6 | error() 7 | end 8 | 9 | function _M.rewrite() 10 | error() 11 | end 12 | 13 | return _M 14 | -------------------------------------------------------------------------------- /t/fixtures/policies/error_policy/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('error_policy') 2 | -------------------------------------------------------------------------------- /t/fixtures/policies/example_policy/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy", 4 | "summary": "An example policy to be used in integration tests.", 5 | "version": "1.0.0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | "message": { 10 | "type": "string", 11 | "description": "A message." 12 | } 13 | }, 14 | "required": ["message"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /t/fixtures/policies/example_policy/1.0.0/example_policy.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('example_policy', '1.0.0') 2 | 3 | local new = _M.new 4 | 5 | function _M.new(configuration) 6 | local policy = new(configuration) 7 | 8 | policy.message = '' 9 | 10 | if configuration then 11 | policy.message = configuration.message 12 | end 13 | 14 | policy.fail_access = configuration.fail_access 15 | 16 | return policy 17 | end 18 | 19 | function _M:access() 20 | if self.fail_access then 21 | self.fail() 22 | end 23 | end 24 | 25 | function _M:content() 26 | ngx.say(self.message) 27 | end 28 | 29 | return _M 30 | -------------------------------------------------------------------------------- /t/fixtures/policies/example_policy/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('example_policy') 2 | -------------------------------------------------------------------------------- /t/fixtures/policies/https/builtin/init.lua: -------------------------------------------------------------------------------- 1 | local _M = require('apicast.policy').new('HTTPS', '1.0.0') 2 | local ssl = require('ngx.ssl') 3 | local new = _M.new 4 | 5 | function _M.new(configuration) 6 | local policy = new(configuration) 7 | 8 | if configuration then 9 | policy.certificate_chain = assert(ssl.parse_pem_cert(configuration.certificate)) 10 | policy.priv_key = assert(ssl.parse_pem_priv_key(configuration.key)) 11 | end 12 | 13 | return policy 14 | end 15 | 16 | function _M:ssl_certificate() 17 | assert(ssl.clear_certs()) 18 | 19 | assert(ssl.set_cert(self.certificate_chain)) 20 | assert(ssl.set_priv_key(self.priv_key)) 21 | end 22 | 23 | return _M 24 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example1/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy 1", 4 | "summary": "Just an example.", 5 | "version": "1.0.0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | "message": { 10 | "type": "string", 11 | "description": "A message." 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example1/1.0.0/example1.lua: -------------------------------------------------------------------------------- 1 | local Policy = require('apicast.policy').new('Example1') 2 | return Policy 3 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example1/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('example1') 2 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example2/1.0.0/apicast-policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://apicast.io/policy-v1/schema#manifest#", 3 | "name": "Example policy 2", 4 | "summary": "Just an example with a version mismatch.", 5 | "version": "2.0.0", 6 | "configuration": { 7 | "type": "object", 8 | "properties": { 9 | "message": { 10 | "type": "string", 11 | "description": "A message." 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example2/1.0.0/example2.lua: -------------------------------------------------------------------------------- 1 | local Policy = require('apicast.policy').new('Example2') 2 | return Policy 3 | -------------------------------------------------------------------------------- /t/fixtures/policies_endpoint_test/policies/example2/1.0.0/init.lua: -------------------------------------------------------------------------------- 1 | return require('example2') 2 | -------------------------------------------------------------------------------- /t/fixtures/rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIBPAIBAAJBALClz96cDQ965ENYMfZzG+Acu25lpx2KNpAALBQ+catCA59us7+u 3 | LY5rjQR6SOgZpCz5PJiKNAdRPDJMXSmXqM0CAwEAAQJBAJnwZa4BIACVf8aQXToA 4 | JhKv90bFn1TG1bW38LHTmQs8EM9XCmghLWCje7d/NbUrUceotIOnjtv/xHTywGt2 5 | NwECIQDhvMZDQ+ZRRbbwONcvO9G7h6hFgy0okiv6JciZccvtxQIhAMhUTAWgV1hQ 6 | O2yWTRYRQZosEIsFB3kZfsLMeTKjk8dpAiEAslsZ92m9n3dKrJDsjFhiRR5ROOMF 7 | Gior7xBNZ9e+vdUCIDsjf4nNqttcXB6TRFB2aapsxbl0k58xYpV5LXJAjfi5AiEA 8 | vRaSauBfRCP3JgXHNgcDSW017/BtbwGiz8aITv6B0Fw= 9 | -----END RSA PRIVATE KEY----- 10 | -------------------------------------------------------------------------------- /t/fixtures/rsa.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALClz96cDQ965ENYMfZzG+Acu25lpx2K 3 | NpAALBQ+catCA59us7+uLY5rjQR6SOgZpCz5PJiKNAdRPDJMXSmXqM0CAwEAAQ== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /t/fixtures/tls.pl: -------------------------------------------------------------------------------- 1 | use File::Slurp qw(read_file); 2 | 3 | [ 4 | [ "server.crt" => CORE::join('', read_file('t/fixtures/server.crt')) ], 5 | [ "server.key" => CORE::join('', read_file('t/fixtures/server.key')) ], 6 | ] 7 | -------------------------------------------------------------------------------- /t/fixtures/upstream.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [{ 3 | "proxy": { 4 | "policy_chain": [ 5 | { "name": "apicast.policy.upstream", 6 | "configuration": { "rules": [ { "regex": "/", "url": "http://test" } ] } } 7 | ] 8 | } 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /t/sanity.t: -------------------------------------------------------------------------------- 1 | use lib 't'; 2 | use Test::APIcast::Blackbox 'no_plan'; 3 | 4 | filters { configuration => 'fixture=echo.json' }; 5 | 6 | run_tests(); 7 | 8 | __DATA__ 9 | 10 | === TEST 1: underscores in headers 11 | HTTP headers with underscores allowed and passed upstream. 12 | --- configuration 13 | --- request 14 | GET /test 15 | --- more_headers 16 | API_KEY: somekey 17 | --- response_body 18 | GET /test HTTP/1.1 19 | X-Real-IP: 127.0.0.1 20 | Host: echo 21 | API_KEY: somekey 22 | --- error_code: 200 23 | --- no_error_log 24 | [error] 25 | 26 | 27 | 28 | === TEST 2 dots in headers 29 | Dots in headers are allowed and passed upstream. 30 | --- configuration 31 | --- request 32 | GET /test 33 | --- more_headers 34 | Client.ID: someid 35 | --- response_body 36 | GET /test HTTP/1.1 37 | X-Real-IP: 127.0.0.1 38 | Host: echo 39 | Client.ID: someid 40 | --- error_code: 200 41 | --- no_error_log 42 | [error] 43 | --------------------------------------------------------------------------------