├── .actrc ├── .gitattributes ├── .github ├── actions │ ├── cleanup │ │ └── action.yml │ ├── load-docker-image │ │ └── action.yml │ └── setup-httpbin-server │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── ci-large.yml │ ├── ci.yml │ ├── codeql.yml │ ├── job-build-tests.yml │ ├── job-clang-analyzer.yml │ ├── job-unit-tests.yml │ ├── job-valgrind-tests.yml │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── SECURITY.md ├── asan.suppress ├── assets ├── ci │ ├── Dockerfile.nginx │ └── nginx.conf ├── release │ ├── Dockerfiles │ │ ├── Dockerfile.amd64.archlinux │ │ ├── Dockerfile.amd64.centos7 │ │ ├── Dockerfile.amd64.centos8 │ │ ├── Dockerfile.amd64.ubuntu-18.04 │ │ ├── Dockerfile.ubuntu-20.04 │ │ ├── Dockerfile.ubuntu-22.04 │ │ └── skip.Dockerfile.amd64.alpinelinux │ ├── INSTALL │ ├── README │ └── nginx.conf └── vectors │ ├── logo.svg │ ├── proxy_wasm_nginx_phases.svg │ └── proxy_wasm_sdk_structure.svg ├── auto ├── cargo └── runtime ├── codecov.yml ├── config ├── docs ├── DEVELOPER.md ├── DIRECTIVES.md ├── INSTALL.md ├── METRICS.md ├── PROXY_WASM.md ├── PROXY_WASM_HOST_DIFFERENCES.md ├── README.md ├── SLRU.md └── adr │ ├── 000-template.md │ ├── 001-proxy-wasm-gateway-embedding.md │ ├── 002-proxy-wasm-abi.md │ ├── 003-proxy-wasm-gateway-plugin.md │ ├── 004-shm.md │ └── 005-metrics.md ├── lib ├── Cargo.lock ├── Cargo.toml ├── ngx-rust │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── log.rs │ │ └── resp.rs ├── ngx-wasm-rs │ ├── Cargo.lock │ ├── Cargo.toml │ ├── include │ │ ├── ngx_wasm_backtrace.h │ │ └── ngx_wasm_wat.h │ ├── lib │ │ ├── backtrace │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── backtrace.rs │ │ │ │ ├── c_api.rs │ │ │ │ └── lib.rs │ │ ├── c-api │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ └── lib.rs │ │ └── wat │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ └── src │ │ │ └── lib.rs │ └── src │ │ └── lib.rs ├── resty │ ├── wasmx.lua │ └── wasmx │ │ ├── proxy_wasm.lua │ │ └── shm.lua ├── rust-toolchain.toml └── v8bridge │ ├── Makefile │ ├── bridge.cc │ └── bridge.h ├── lsan.suppress ├── src ├── common │ ├── ddebug.h │ ├── debug │ │ └── ngx_wasm_debug_module.c │ ├── lua │ │ ├── ngx_wasm_lua.c │ │ ├── ngx_wasm_lua.h │ │ ├── ngx_wasm_lua_ffi.c │ │ ├── ngx_wasm_lua_ffi.h │ │ ├── ngx_wasm_lua_resolver.c │ │ └── ngx_wasm_lua_resolver.h │ ├── metrics │ │ ├── ngx_wa_histogram.c │ │ ├── ngx_wa_metrics.c │ │ └── ngx_wa_metrics.h │ ├── ngx_wa_readers.c │ ├── ngx_wa_readers.h │ ├── ngx_wasm_socket_tcp.c │ ├── ngx_wasm_socket_tcp.h │ ├── ngx_wasm_socket_tcp_readers.c │ ├── ngx_wasm_socket_tcp_readers.h │ ├── ngx_wasm_ssl.c │ ├── ngx_wasm_ssl.h │ ├── ngx_wasm_subsystem.c │ ├── ngx_wasm_subsystem.h │ ├── proxy_wasm │ │ ├── ngx_proxy_wasm.c │ │ ├── ngx_proxy_wasm.h │ │ ├── ngx_proxy_wasm_foreign_call.c │ │ ├── ngx_proxy_wasm_foreign_call.h │ │ ├── ngx_proxy_wasm_host.c │ │ ├── ngx_proxy_wasm_maps.c │ │ ├── ngx_proxy_wasm_maps.h │ │ ├── ngx_proxy_wasm_properties.c │ │ ├── ngx_proxy_wasm_properties.h │ │ └── ngx_proxy_wasm_util.c │ └── shm │ │ ├── ngx_wa_shm.c │ │ ├── ngx_wa_shm.h │ │ ├── ngx_wa_shm_kv.c │ │ ├── ngx_wa_shm_kv.h │ │ ├── ngx_wa_shm_queue.c │ │ └── ngx_wa_shm_queue.h ├── http │ ├── ngx_http_wasm.h │ ├── ngx_http_wasm_directives.c │ ├── ngx_http_wasm_escape.c │ ├── ngx_http_wasm_filter_module.c │ ├── ngx_http_wasm_headers.c │ ├── ngx_http_wasm_headers.h │ ├── ngx_http_wasm_headers_request.c │ ├── ngx_http_wasm_headers_response.c │ ├── ngx_http_wasm_headers_shims.c │ ├── ngx_http_wasm_host.c │ ├── ngx_http_wasm_local_response.c │ ├── ngx_http_wasm_module.c │ ├── ngx_http_wasm_trailers.h │ ├── ngx_http_wasm_trailers_response.c │ ├── ngx_http_wasm_util.c │ ├── ngx_http_wasm_util.h │ └── proxy_wasm │ │ ├── ngx_http_proxy_wasm.c │ │ ├── ngx_http_proxy_wasm.h │ │ ├── ngx_http_proxy_wasm_dispatch.c │ │ └── ngx_http_proxy_wasm_dispatch.h ├── ipc │ ├── ngx_ipc.c │ ├── ngx_ipc.h │ └── ngx_ipc_core_module.c ├── ngx_wasmx.c ├── ngx_wasmx.h ├── stream │ ├── ngx_stream_wasm.h │ ├── ngx_stream_wasm_module.c │ └── proxy_wasm │ │ └── ngx_stream_proxy_wasm.h └── wasm │ ├── ngx_wasm.h │ ├── ngx_wasm_core_host.c │ ├── ngx_wasm_core_module.c │ ├── ngx_wasm_directives.c │ ├── ngx_wasm_ops.c │ ├── ngx_wasm_ops.h │ ├── ngx_wasm_util.c │ ├── vm │ ├── ngx_wavm.c │ ├── ngx_wavm.h │ ├── ngx_wavm_host.c │ └── ngx_wavm_host.h │ ├── wasi │ ├── ngx_wasi.h │ └── ngx_wasi_preview1_host.c │ └── wrt │ ├── ngx_wrt.h │ ├── ngx_wrt_utils.c │ ├── ngx_wrt_v8.c │ ├── ngx_wrt_wasmer.c │ └── ngx_wrt_wasmtime.c ├── t ├── 01-wasm │ ├── 001-wasm_block.t │ ├── 002-shm_queue_sanity.t │ ├── 003-shm_kv_sanity.t │ ├── 004-runtime_blocks.t │ ├── 005-metrics_block.t │ ├── directives │ │ ├── 001-module_directive.t │ │ ├── 002-compiler_directive.t │ │ ├── 003-shm_directives.t │ │ ├── 004-resolver_directive.t │ │ ├── 005-socket_directives.t │ │ ├── 006-backtraces_directive.t │ │ ├── 007-flag_directive.t │ │ ├── 008-flag_directive_wasmtime.t │ │ ├── 009-flag_directive_wasmer.t │ │ ├── 010-flag_directive_v8.t │ │ ├── 011-metrics_directives.t │ │ └── 011-wasmtime_cache_config_directive.t │ └── hfuncs │ │ └── 001-log.t ├── 02-http │ ├── 001-sanity.t │ ├── 002-wasm_oob.t │ ├── 003-produced_response_headers.t │ ├── 004-postpone_rewrite.t │ ├── 005-postpone_access.t │ ├── 100-filters_coverage.t │ ├── directives │ │ ├── 001-wasm_call_directive.t │ │ └── 002-resolver_add_directive.t │ └── hfuncs │ │ ├── 001-resp_get_status.t │ │ ├── 002-resp_set_status.t │ │ ├── 003-say.t │ │ └── 004-local_response.t ├── 03-proxy_wasm │ ├── 001-on_root_phases.t │ ├── 002-on_root_phases_failures.t │ ├── 003-on_tick.t │ ├── 004-on_http_phases.t │ ├── 005-on_http_phases_failures.t │ ├── 006-on_http_next_action.t │ ├── 007-on_http_instance_isolation.t │ ├── 008-on_http_response_body_buffering.t │ ├── 009-proxy_wasm_oob.t │ ├── 010-eagain_sanity.t │ ├── 100-flag_req_headers_in_access.t │ ├── directives │ │ ├── 001-proxy_wasm_directive.t │ │ ├── 002-proxy_wasm_isolation_directive.t │ │ └── 003-proxy_wasm_lua_resolver_directive.t │ ├── hfuncs │ │ ├── 000-nyi.t │ │ ├── 001-get_vm_configuration.t │ │ ├── 100-proxy_log.t │ │ ├── 101-proxy_get_current_time.t │ │ ├── 102-proxy_send_local_response.t │ │ ├── 103-proxy_get_http_request_headers.t │ │ ├── 104-proxy_get_http_response_headers.t │ │ ├── 105-proxy_get_http_request_header.t │ │ ├── 106-proxy_get_http_response_header.t │ │ ├── 107-proxy_add_http_request_header.t │ │ ├── 108-proxy_add_http_response_header.t │ │ ├── 109-proxy_set_http_request_headers.t │ │ ├── 110-proxy_set_http_response_headers.t │ │ ├── 111-proxy_set_http_request_header.t │ │ ├── 112-proxy_set_http_response_header.t │ │ ├── 113-proxy_get_http_request_body.t │ │ ├── 114-proxy_set_http_request_body.t │ │ ├── 115-proxy_get_http_response_body.t │ │ ├── 116-proxy_set_http_response_body.t │ │ ├── 117-proxy_properties_get.t │ │ ├── 118-proxy_properties_get_nyi.t │ │ ├── 119-proxy_properties_get_ngx.t │ │ ├── 120-proxy_properties_get_host.t │ │ ├── 121-proxy_properties_set.t │ │ ├── 122-proxy_properties_set_ngx.t │ │ ├── 123-proxy_properties_set_host.t │ │ ├── 130-proxy_dispatch_http.t │ │ ├── 131-proxy_dispatch_http_timeouts.t │ │ ├── 132-proxy_dispatch_http_ssl.t │ │ ├── 133-proxy_dispatch_http_edge_cases.t │ │ ├── 140-proxy_call_foreign_function.t │ │ ├── 200-buffers_and_maps_bad_args.t │ │ ├── contexts │ │ │ ├── 002-set_tick_period.t │ │ │ ├── 100-proxy_log.t │ │ │ ├── 107-proxy_add_http_request_header.t │ │ │ ├── 108-proxy_add_http_response_header.t │ │ │ ├── 109-proxy_set_http_request_headers.t │ │ │ ├── 110-proxy_set_http_response_headers.t │ │ │ ├── 111-proxy_set_http_request_header.t │ │ │ ├── 112-proxy_set_http_response_header.t │ │ │ ├── 113-proxy_get_http_request_body.t │ │ │ ├── 114-proxy_set_http_request_body.t │ │ │ ├── 115-proxy_get_http_response_body.t │ │ │ ├── 116-proxy_set_http_response_body.t │ │ │ ├── 130-proxy_dispatch_http.t │ │ │ ├── 131-proxy_get_http_dispatch_response_body.t │ │ │ ├── 140-proxy_foreign_function_resolve_lua.t │ │ │ └── metrics │ │ │ │ ├── 001-proxy_define_metric.t │ │ │ │ ├── 010-proxy_increment_metric.t │ │ │ │ ├── 020-proxy_record_metric.t │ │ │ │ └── 030-proxy_get_metric.t │ │ ├── foreign │ │ │ └── 001-resolve_lua.t │ │ ├── metrics │ │ │ ├── 001-proxy_define_metric.t │ │ │ ├── 002-proxy_define_metric_edge_cases.t │ │ │ ├── 010-proxy_increment_metric.t │ │ │ ├── 011-proxy_increment_metric_edge_cases.t │ │ │ ├── 020-proxy_record_metric.t │ │ │ ├── 021-proxy_record_metric_edge_cases.t │ │ │ ├── 030-proxy_get_metric.t │ │ │ └── 031-proxy_get_metric_edge_cases.t │ │ └── shm │ │ │ ├── 001-kv_get_set.t │ │ │ ├── 002-kv_misuse.t │ │ │ ├── 003-kv_edge_cases.t │ │ │ ├── 004-kv_eviction.t │ │ │ ├── 100-queue_push_pop.t │ │ │ ├── 101-queue_misuse.t │ │ │ ├── 102-queue_push_edge_case.t │ │ │ └── 103-queue_pop_edge_case.t │ └── sdks │ │ ├── 001-rust_sdk.t │ │ ├── 002-go_sdk │ │ ├── 001-helloworld.t │ │ ├── 002-http_headers.t │ │ ├── 003-postpone_requests.t.off │ │ ├── 004-foreign_call_on_tick.t.off │ │ ├── 005-dispatch_call_on_tick.t │ │ ├── 006-http_auth_random.t │ │ ├── 007-http_body.t │ │ ├── 008-json_validation.t │ │ ├── 009-http_routing.t │ │ ├── 010-shared_data.t │ │ ├── 011-shared_queue.t.off │ │ ├── 012-metrics.t.off │ │ ├── 013-vm_plugin_configuration.t │ │ └── 014-multiple_dispatches.t.off │ │ └── 003-assemblyscript_sdk.t ├── 04-openresty │ ├── 001-sanity.t │ ├── 002-dynamic_module.t │ ├── 003-postpone_rewrite.t │ ├── 004-postpone_access.t │ ├── ffi │ │ ├── 001-get_main_vm.t │ │ ├── 100-proxy_wasm_new.t │ │ ├── 101-proxy_wasm_load.t │ │ ├── 103-proxy_wasm_attach.t │ │ ├── 200-proxy_wasm_and_lua_sanity.t │ │ ├── 300-proxy_wasm_properties_get_ngx.t │ │ ├── 301-proxy_wasm_properties_get_host.t │ │ ├── 302-proxy_wasm_properties_set_ngx.t │ │ ├── 303-proxy_wasm_properties_set_host.t │ │ ├── 304-proxy_wasm_set_host_properties_handlers.t │ │ ├── 305-proxy_wasm_host_properties_getter.t │ │ ├── 306-proxy_wasm_host_properties_setter.t │ │ └── shm │ │ │ ├── 000-setup_zones.t │ │ │ ├── 001-kv_get.t │ │ │ ├── 002-kv_set.t │ │ │ ├── 010-iterate_keys.t │ │ │ ├── 011-get_keys.t │ │ │ ├── 020-metrics_define.t │ │ │ ├── 021-metrics_increment.t │ │ │ ├── 022-metrics_record.t │ │ │ ├── 023-metrics_record_custom_histogram.t │ │ │ ├── 024-metrics_get.t │ │ │ ├── 025-metrics_get_by_name.t │ │ │ ├── 026-metrics_iterate_keys.t │ │ │ └── 027-metrics_get_keys.t │ └── lua-bridge │ │ ├── 001-sanity.t │ │ ├── 002-proxy_wasm_lua_resolver_sanity.t │ │ └── 003-proxy_wasm_lua_resolver_timeouts.t ├── 05-wasi │ ├── 001-sanity.t │ └── wasi-p1 │ │ ├── args_get.t │ │ ├── args_sizes_get.t │ │ ├── clock_time_get.t │ │ ├── environ_get.t │ │ ├── environ_sizes_get.t │ │ ├── fd_close.t │ │ ├── fd_fdstat_get.t │ │ ├── fd_fdstat_set_flags.t │ │ ├── fd_prestat_dir_name.t │ │ ├── fd_prestat_get.t │ │ ├── fd_read.t │ │ ├── fd_seek.t │ │ ├── fd_write.t │ │ ├── path_open.t │ │ ├── poll_oneoff.t │ │ ├── random_get.t │ │ └── sched_yield.t ├── 06-others │ ├── 001-socket_buffer_reuse.t │ ├── 002-resolver_add_sanity.t │ ├── 010-client_connection_abort.t │ ├── 011-upstream_connection_abort.t │ ├── 020-metrics_sighup.t │ └── 021-histograms_sighup.t ├── 07-ipc │ └── 001-ipc_block.t ├── 10-build │ ├── 001-build_options.t │ ├── 002-runtime_linking.t │ ├── 003-dynamic_module.t │ └── 004-ngx_wasm_rs_linking.t ├── 11-bench │ ├── 001-bench_hash.t │ ├── 002-bench_fannkuch_redux.t │ └── 003-bench_proxy_wasm.t ├── TestBuild.pm ├── TestWasmX.pm ├── TestWasmX │ └── Lua.pm ├── data │ ├── badssl_cert.pem │ ├── cert.pem │ ├── hostname_cert.pem │ ├── hostname_key.pem │ └── key.pem └── lib │ ├── Cargo.lock │ ├── Cargo.toml │ ├── ngx-lua-tests │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── lua_bridge.rs │ ├── ngx-rust-tests │ ├── Cargo.toml │ └── src │ │ └── lib.rs │ ├── proxy-wasm-tests │ ├── benchmarks │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── fannkuch_redux.rs │ │ │ └── filter.rs │ ├── context-checks │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── hostcalls.rs │ │ │ └── lib.rs │ ├── hostcalls │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── filter.rs │ │ │ ├── foreign_callbacks │ │ │ └── mod.rs │ │ │ ├── lib.rs │ │ │ ├── tests │ │ │ ├── echo.rs │ │ │ ├── host.rs │ │ │ └── mod.rs │ │ │ └── types │ │ │ ├── mod.rs │ │ │ ├── test_http.rs │ │ │ └── test_root.rs │ ├── instance-lifecycle │ │ ├── Cargo.toml │ │ └── src │ │ │ └── filter.rs │ ├── on-phases │ │ ├── Cargo.toml │ │ └── src │ │ │ └── filter.rs │ ├── on-tick │ │ ├── Cargo.toml │ │ └── src │ │ │ └── filter.rs │ └── rust-sdk-ver-zero-one │ │ ├── Cargo.toml │ │ └── src │ │ └── filter.rs │ ├── wasi-host-tests │ ├── Cargo.toml │ └── src │ │ └── lib.rs │ └── wasi-vm-tests │ ├── Cargo.toml │ └── src │ └── lib.rs ├── util ├── _lib.sh ├── build.sh ├── changelog.sh ├── clean.sh ├── morestyle.pl ├── parse-valgrind.awk ├── reindex.sh ├── release.sh ├── runtime.sh ├── runtimes │ ├── v8.sh │ ├── wasmer.sh │ └── wasmtime.sh ├── sdk.sh ├── sdks │ ├── assemblyscript.sh │ └── go.sh ├── setup_dev.sh ├── style.sh └── test.sh └── valgrind.suppress /.actrc: -------------------------------------------------------------------------------- 1 | -P ubuntu-latest=wasmx-build-ubuntu 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.t linguist-language=Text 2 | -------------------------------------------------------------------------------- /.github/actions/cleanup/action.yml: -------------------------------------------------------------------------------- 1 | name: cleanup 2 | 3 | runs: 4 | using: 'composite' 5 | steps: 6 | - name: Cleanup httpbin proxy + server 7 | shell: bash 8 | run: | 9 | docker stop httpbin httpbin_proxy 10 | pkill dnsmasq 11 | -------------------------------------------------------------------------------- /.github/actions/load-docker-image/action.yml: -------------------------------------------------------------------------------- 1 | name: load-docker-image 2 | decription: | 3 | Pull a docker image, cache and load it. 4 | 5 | inputs: 6 | image: 7 | required: true 8 | type: string 9 | cache_dir: 10 | required: false 11 | type: string 12 | default: "$GITHUB_WORKSPACE/.docker-images-cache" 13 | 14 | runs: 15 | using: 'composite' 16 | steps: 17 | - name: Create cache directory 18 | shell: bash 19 | run: mkdir -p ${{ inputs.cache_dir }} 20 | 21 | - name: Setup cache 22 | uses: actions/cache@v4 23 | with: 24 | path: ${{ inputs.cache_dir }} 25 | key: pulled-docker-images 26 | 27 | - name: Setup cache path 28 | id: cache_setup 29 | shell: bash 30 | run: | 31 | filename="$(echo ${{ inputs.image }} | sed 's/\//_/g').tar" 32 | cache_path="${{ inputs.cache_dir }}/$filename" 33 | 34 | if [ -f "$cache_path" ]; then 35 | echo "cache_hit=true" >> $GITHUB_OUTPUT 36 | else 37 | echo "cache_hit=false" >> $GITHUB_OUTPUT 38 | fi 39 | 40 | echo "cache_path=$cache_path" >> $GITHUB_OUTPUT 41 | 42 | - name: Pull Docker image 43 | if: steps.cache_setup.outputs.cache_hit == 'false' 44 | shell: bash 45 | run: | 46 | docker pull ${{ inputs.image }} 47 | docker save -o ${{ steps.cache_setup.outputs.cache_path }} ${{ inputs.image }} 48 | 49 | - name: Load Docker image from cache 50 | if: steps.cache_setup.outputs.cache-hit == 'true' 51 | shell: bash 52 | run: docker load -i ${{ steps.cache_setup.outputs.cache_path }} 53 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates 2 | version: 2 3 | updates: 4 | - package-ecosystem: github-actions 5 | directory: / 6 | schedule: 7 | interval: monthly 8 | labels: 9 | - "pr/dependabot" 10 | commit-message: 11 | prefix: "chore(ci) " 12 | 13 | - package-ecosystem: cargo 14 | directory: /lib 15 | schedule: 16 | interval: monthly 17 | labels: 18 | - "pr/dependabot" 19 | groups: 20 | production-dependencies: 21 | dependency-type: "production" 22 | patterns: 23 | - "*" 24 | development-dependencies: 25 | dependency-type: "development" 26 | patterns: 27 | - "*" 28 | commit-message: 29 | prefix: "chore(deps) " 30 | 31 | - package-ecosystem: cargo 32 | directories: 33 | - "/t/lib/ngx-lua-tests" 34 | - "/t/lib/ngx-rust-tests" 35 | - "/t/lib/wasi-host-tests" 36 | - "/t/lib/wasi-vm-tests" 37 | - "/t/lib/proxy-wasm-tests/benchmarks" 38 | - "/t/lib/proxy-wasm-tests/context-checks" 39 | - "/t/lib/proxy-wasm-tests/hostcalls" 40 | - "/t/lib/proxy-wasm-tests/instance-lifecycle" 41 | - "/t/lib/proxy-wasm-tests/on-phases" 42 | - "/t/lib/proxy-wasm-tests/on-tick" 43 | schedule: 44 | interval: monthly 45 | groups: 46 | production-dependencies: 47 | dependency-type: "production" 48 | patterns: 49 | - "*" 50 | development-dependencies: 51 | dependency-type: "development" 52 | patterns: 53 | - "*" 54 | ignore: 55 | - dependency-name: "wasi" 56 | versions: [">0.11"] 57 | labels: 58 | - "pr/dependabot" 59 | commit-message: 60 | prefix: "chore(tests) " 61 | 62 | - package-ecosystem: cargo 63 | directory: /t/lib/proxy-wasm-tests/rust-sdk-ver-zero-one 64 | schedule: 65 | interval: monthly 66 | groups: 67 | production-dependencies: 68 | dependency-type: "production" 69 | patterns: 70 | - "*" 71 | development-dependencies: 72 | dependency-type: "development" 73 | patterns: 74 | - "*" 75 | ignore: 76 | # do not update beyond proxy-wasm 0.1.x in rust-sdk-ver-zero-one 77 | - dependency-name: "proxy-wasm" 78 | versions: [">0.1"] 79 | labels: 80 | - "pr/dependabot" 81 | commit-message: 82 | prefix: "chore(tests) " 83 | -------------------------------------------------------------------------------- /.github/workflows/job-build-tests.yml: -------------------------------------------------------------------------------- 1 | name: Build tests 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | os: 7 | required: true 8 | type: string 9 | cc: 10 | required: true 11 | type: string 12 | ngx: 13 | required: true 14 | type: string 15 | runtime: 16 | required: true 17 | type: string 18 | wasmtime: 19 | required: true 20 | type: string 21 | wasmer: 22 | required: true 23 | type: string 24 | v8: 25 | required: true 26 | type: string 27 | 28 | defaults: 29 | run: 30 | shell: bash 31 | 32 | env: 33 | CC: ${{ inputs.cc }} 34 | NGX_WASM_RUNTIME: ${{ inputs.runtime }} 35 | 36 | jobs: 37 | build: 38 | name: 'Build' 39 | #if: ${{ false }} 40 | runs-on: ${{ inputs.os }} 41 | timeout-minutes: 45 42 | steps: 43 | - name: 'Setup Ubuntu deps - gcc' 44 | if: ${{ !env.ACT && contains(inputs.os, 'ubuntu') && contains(inputs.cc, 'gcc') }} 45 | run: sudo apt-get update && sudo apt-get install -y ${CC} libstdc++-${CC#*-}-dev 46 | 47 | - name: 'Setup Ubuntu deps - clang' 48 | if: ${{ !env.ACT && contains(inputs.os, 'ubuntu') && contains(inputs.cc, 'clang') }} 49 | run: sudo apt-get update && sudo apt-get install -y ${CC} 50 | 51 | - name: 'Setup macOS deps' 52 | if: ${{ !env.ACT && contains(inputs.os, 'macos') }} 53 | run: brew install ninja openssh 54 | 55 | - uses: actions/checkout@v4 56 | - name: 'Setup cache - work/ dir' 57 | uses: actions/cache@v4 58 | if: ${{ !env.ACT }} 59 | with: 60 | path: | 61 | work/downloads 62 | work/runtimes 63 | work/openssl 64 | key: work-${{ runner.os }}-${{ inputs.cc }}-${{ inputs.ngx }}-${{ inputs.runtime }}-${{ hashFiles('util/**/*.sh', 'util/**/*.pl', 'util/**/*.awk', '.github/**/*.yml', '.github/**/*.sh', '.github/**/*.js', 'rust-toolchain', 'Makefile') }} 65 | - name: Setup Wasm runtime 66 | run: ./util/runtime.sh -R ${{ inputs.runtime }} -V ${{ inputs[inputs.runtime] }} 67 | - run: make setup 68 | - run: make test-build 69 | -------------------------------------------------------------------------------- /.github/workflows/job-clang-analyzer.yml: -------------------------------------------------------------------------------- 1 | name: Clang analyzer 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | cc: 7 | required: true 8 | type: string 9 | ngx: 10 | required: true 11 | type: string 12 | openresty: 13 | required: true 14 | type: string 15 | runtime: 16 | required: true 17 | type: string 18 | wasmtime: 19 | required: true 20 | type: string 21 | wasmer: 22 | required: true 23 | type: string 24 | v8: 25 | required: true 26 | type: string 27 | ssl: 28 | required: true 29 | type: string 30 | debug: 31 | required: true 32 | type: string 33 | 34 | defaults: 35 | run: 36 | shell: bash 37 | 38 | env: 39 | CC: ${{ inputs.cc }} 40 | NGX_IPC: 1 41 | NGX_BUILD_OPENRESTY: ${{ inputs.openresty }} 42 | NGX_BUILD_DEBUG: ${{ inputs.debug == 'debug' && 1 || 0 }} 43 | NGX_BUILD_SSL: ${{ inputs.ssl == 'ssl' && 1 || 0 }} 44 | NGX_BUILD_CLANG_ANALYZER: 1 45 | 46 | jobs: 47 | analyzer: 48 | name: 'Clang analyzer' 49 | runs-on: ubuntu-latest 50 | timeout-minutes: 30 51 | steps: 52 | - run: | 53 | sudo apt-get update 54 | sudo apt-get install -y $(echo ${{ inputs.cc }} | sed s/clang/clang-tools/) 55 | sudo update-alternatives --install /usr/bin/scan-build scan-build /usr/bin/$(echo ${{ inputs.cc }} | sed s/clang/scan-build/) 100 56 | - uses: actions/checkout@v4 57 | - name: 'Setup cache - work/ dir' 58 | uses: actions/cache@v4 59 | if: ${{ !env.ACT }} 60 | with: 61 | path: | 62 | work/downloads 63 | work/runtimes 64 | work/openssl 65 | key: work-${{ runner.os }}-${{ inputs.cc }}-${{ inputs.ngx }}-${{ inputs.openresty }}-${{ inputs.runtime }}-${{ hashFiles('util/**/*.sh', 'util/**/*.pl', 'util/**/*.awk', '.github/**/*.yml', '.github/**/*.sh', '.github/**/*.js', 'rust-toolchain') }} 66 | - name: Setup Wasm runtime 67 | run: ./util/runtime.sh -R ${{ inputs.runtime }} -V ${{ inputs[inputs.runtime] }} 68 | - run: make setup 69 | - run: make 70 | - uses: actions/upload-artifact@v4 71 | if: ${{ failure() && !env.ACT }} 72 | with: 73 | name: ${{ github.job }}-sha-${{ github.sha }}-run-${{ github.run_number }}-${{ inputs.ngx != '' && format('nginx-{0}', inputs.ngx) || format('openresty-{0}', inputs.openresty) }}-${{ inputs.runtime }}-${{ inputs.ssl }}-${{ inputs.hup }}-${{ inputs.debug }} 74 | path: work/scans/* 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | work/ 2 | dist/ 3 | buildroot/ 4 | target/ 5 | t/servroot* 6 | *.data* 7 | *.perf* 8 | *.dump 9 | *.svg 10 | *.log* 11 | *.gcov 12 | *.wasm 13 | vgcore.* 14 | *.o 15 | *.a 16 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2020-2024 Kong Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | At Kong, we take security issues very seriously. If you believe you have found a 6 | security vulnerability in our project, we encourage you to disclose it 7 | responsibly. Please report any potential security vulnerabilities to us by 8 | sending an email to [vulnerability@konghq.com](mailto:vulnerability@konghq.com). 9 | 10 | ## How to Report 11 | 12 | 1. **Do not publicly disclose the vulnerability**: Please do not create a GitHub 13 | issue or post the vulnerability on public forums. Instead, contact us 14 | directly at [vulnerability@konghq.com](mailto:vulnerability@konghq.com). 15 | 16 | 2. **Provide detailed information**: When reporting a vulnerability, please 17 | include as much information as possible to help us understand and reproduce 18 | the issue. This may include: 19 | - Description of the vulnerability 20 | - Steps to reproduce the issue 21 | - Potential impact 22 | - Any relevant logs or screenshots 23 | 24 | ## What to Expect 25 | 26 | - **Acknowledgment**: We will acknowledge receipt of your vulnerability report 27 | within 48 hours. 28 | - **Investigation**: Our security team will investigate the report and will keep 29 | you informed of the progress. We aim to resolve critical vulnerabilities 30 | within 30 days of confirmation. 31 | - **Disclosure**: We prefer coordinated disclosure and will work with you to 32 | schedule the disclosure of the vulnerability in a way that minimizes the risk 33 | to users. 34 | 35 | ## Bug Bounty Program 36 | 37 | We encourage security researchers to participate in our bug bounty program as 38 | outlined on the [Kong Vulnerability 39 | Disclosure](https://konghq.com/compliance/bug-bounty) page. This program 40 | provides rewards for discovering and reporting security vulnerabilities in 41 | accordance with our disclosure guidelines. 42 | 43 | Thank you for helping to keep ngx_wasm_module secure. 44 | 45 | For more information on our security policies and guidelines, please visit the 46 | [Kong Vulnerability Disclosure](https://konghq.com/compliance/bug-bounty) page. 47 | 48 | ## Contact 49 | 50 | For any questions or further assistance, please contact us at 51 | [vulnerability@konghq.com](mailto:vulnerability@konghq.com). 52 | -------------------------------------------------------------------------------- /asan.suppress: -------------------------------------------------------------------------------- 1 | global:ngx_modules 2 | global:ngx_module_names 3 | global:ngx_module_order 4 | -------------------------------------------------------------------------------- /assets/ci/Dockerfile.nginx: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | RUN rm /etc/nginx/conf.d/default.conf 3 | COPY ./assets/ci/nginx.conf /etc/nginx/nginx.conf 4 | COPY ./t/data/hostname_cert.pem /etc/nginx/hostname_cert.pem 5 | COPY ./t/data/hostname_key.pem /etc/nginx/hostname_key.pem 6 | -------------------------------------------------------------------------------- /assets/ci/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | user nginx; 3 | pid /var/run/nginx.pid; 4 | error_log /var/log/nginx/error.log info; 5 | 6 | events { 7 | worker_connections 512; 8 | } 9 | 10 | http { 11 | access_log /var/log/nginx/access.log; 12 | 13 | server { 14 | listen *:80; 15 | listen *:443 ssl; 16 | server_name httpbin.org; 17 | 18 | ssl_protocols TLSv1.2 TLSv1.3; 19 | ssl_certificate /etc/nginx/hostname_cert.pem; 20 | ssl_certificate_key /etc/nginx/hostname_key.pem; 21 | 22 | location / { 23 | proxy_pass http://httpbin; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/Dockerfile.amd64.archlinux: -------------------------------------------------------------------------------- 1 | FROM amd64/archlinux:latest 2 | COPY . /ngx_wasm_module 3 | 4 | RUN pacman -Syyu --noconfirm \ 5 | cmake \ 6 | clang \ 7 | make \ 8 | gcc \ 9 | python \ 10 | git \ 11 | pkg-config \ 12 | which \ 13 | ninja 14 | 15 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 16 | ENV PATH $CARGO_HOME/bin:$PATH 17 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 18 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 19 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 20 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/Dockerfile.amd64.centos7: -------------------------------------------------------------------------------- 1 | # Use Python 3.8+ (required by V8's GN build system) 2 | # See https://hub.docker.com/r/centos/python-38-centos7 3 | FROM centos/python-38-centos7 4 | COPY . /ngx_wasm_module 5 | USER root 6 | 7 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/*.repo && \ 8 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/*.repo && \ 9 | yum-config-manager --disable centos-sclo-sclo && \ 10 | yum update -y && \ 11 | yum install -y epel-release && \ 12 | yum install -y centos-release-scl && \ 13 | yum install -y \ 14 | devtoolset-11 \ 15 | devtoolset-11-gcc-c++ \ 16 | devtoolset-11-libatomic-devel \ 17 | ninja-build \ 18 | clang \ 19 | cmake3 \ 20 | make \ 21 | gcc \ 22 | git \ 23 | glib2-devel \ 24 | perl \ 25 | perl-IPC-Cmd \ 26 | perl-Test-Simple 27 | 28 | RUN ln -nfs $(which cmake3) /usr/bin/cmake 29 | 30 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 31 | ENV PATH $CARGO_HOME/bin:$PATH 32 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 33 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 34 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 35 | 36 | # bypass "multiple definitions of 'assertions'" linker error from wasm.h: 37 | # https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h#L29 38 | # and ensure a more recent libstdc++ is found 39 | ENV LD_FLAGS="-Wl,--allow-multiple-definition -L/opt/rh/devtoolset-8/root/usr/lib/gcc/x86_64-redhat-linux/8" 40 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/Dockerfile.amd64.centos8: -------------------------------------------------------------------------------- 1 | FROM amd64/centos:8 2 | COPY . /ngx_wasm_module 3 | 4 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-Linux-* && \ 5 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-Linux-* && \ 6 | dnf update -y && \ 7 | dnf --enablerepo=powertools install -y \ 8 | scl-utils \ 9 | gcc-toolset-11 \ 10 | gcc-toolset-11-gcc-c++ \ 11 | gcc-toolset-11-libatomic-devel \ 12 | ninja-build \ 13 | clang \ 14 | cmake \ 15 | make \ 16 | libatomic \ 17 | perl \ 18 | python39 \ 19 | git \ 20 | glib2-devel 21 | 22 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 23 | ENV PATH $CARGO_HOME/bin:$PATH 24 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 25 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 26 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 27 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/Dockerfile.amd64.ubuntu-18.04: -------------------------------------------------------------------------------- 1 | FROM amd64/ubuntu:18.04 2 | COPY . /ngx_wasm_module 3 | 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | 6 | # Install Python 3.8+ (required by V8's GN build system) 7 | RUN apt-get update && \ 8 | apt-get install -y software-properties-common && \ 9 | add-apt-repository -y ppa:deadsnakes/ppa && \ 10 | add-apt-repository -y ppa:ubuntu-toolchain-r/test && \ 11 | apt-get update && \ 12 | apt-get install -y python3.8 && \ 13 | ln -nfs $(which python3.8) /usr/bin/python3 14 | 15 | RUN apt-get update && \ 16 | apt-get install -y --no-install-recommends \ 17 | ca-certificates \ 18 | build-essential \ 19 | ninja-build \ 20 | gcc-11 \ 21 | libstdc++-11-dev \ 22 | git \ 23 | pkg-config \ 24 | libglib2.0-dev \ 25 | clang \ 26 | curl 27 | 28 | # Install CMake >= 3.12 (required by wabt-sys, 29 | # which is required by cwabt, used by the V8 backend). 30 | RUN apt-get install -y --no-install-recommends \ 31 | python3-pip \ 32 | python3-setuptools && \ 33 | pip3 install --upgrade pip && \ 34 | pip3 install scikit-build && \ 35 | pip3 install cmake 36 | 37 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 38 | ENV PATH $CARGO_HOME/bin:$PATH 39 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 40 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 41 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 42 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/Dockerfile.ubuntu-20.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | COPY . /ngx_wasm_module 3 | 4 | ARG GOLANG_VERSION=1.21.7 5 | ARG TINYGO_VERSION=0.31.1 6 | ARG DEBIAN_FRONTEND=noninteractive 7 | RUN apt-get update && \ 8 | apt-get install -y \ 9 | ca-certificates \ 10 | build-essential \ 11 | ninja-build \ 12 | python3 \ 13 | cmake \ 14 | gcc-10 \ 15 | libstdc++-10-dev \ 16 | git \ 17 | pkg-config \ 18 | libglib2.0-dev \ 19 | clang \ 20 | curl \ 21 | binfmt-support \ 22 | qemu-user-static 23 | 24 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 25 | ENV PATH $CARGO_HOME/bin:$PATH 26 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 27 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 28 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 29 | -------------------------------------------------------------------------------- /assets/release/Dockerfiles/skip.Dockerfile.amd64.alpinelinux: -------------------------------------------------------------------------------- 1 | FROM amd64/alpine:3.17 2 | COPY . /ngx_wasm_module 3 | 4 | RUN apk update && apk upgrade && apk add --no-cache \ 5 | ca-certificates \ 6 | linux-headers \ 7 | build-base \ 8 | coreutils \ 9 | perl-dev \ 10 | libc-dev \ 11 | libgcc \ 12 | alpine-sdk \ 13 | clang \ 14 | make \ 15 | bash \ 16 | curl \ 17 | tar \ 18 | cmake \ 19 | gcc \ 20 | python3 \ 21 | git \ 22 | pkgconf \ 23 | which \ 24 | ninja && \ 25 | update-ca-certificates && \ 26 | ln -sf /usr/bin/pkgconf /usr/bin/pkg-config 27 | 28 | RUN mkdir -p /root/.ssh && ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts 29 | 30 | # force CC to clang 31 | ENV CC=clang 32 | 33 | ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo 34 | ENV PATH $CARGO_HOME/bin:$PATH 35 | RUN mkdir -p "$CARGO_HOME" && mkdir -p "$RUSTUP_HOME" && \ 36 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable && \ 37 | chmod -R a=rwX $CARGO_HOME $RUSTUP_HOME 38 | -------------------------------------------------------------------------------- /assets/release/INSTALL: -------------------------------------------------------------------------------- 1 | To compile this module alongside Nginx, first obtain a copy of the desired 2 | Nginx version: 3 | 4 | $ curl -LO https://nginx.org/download/nginx-1.19.9.tar.gz 5 | $ tar -xf nginx-*.tar.gz 6 | $ cd nginx-* 7 | 8 | Ensure one of the supported WebAssembly runtime libraries is available in your 9 | system (libwasmtime, libwasmer, or libwee8 for V8). 10 | 11 | When configuring Nginx, add this module and specify the Wasm runtime headers 12 | and library with: 13 | 14 | $ ./configure --add-module=/path/to/ngx_wasm_module \ 15 | --with-cc-opt='-O3 -I/path/to/wasmtime/include' \ 16 | --with-ld-opt='-L/path/to/wasmtime/lib -lwasmtime' 17 | 18 | Note: when linking against libwasmer, set the 'NGX_WASM_RUNTIME=wasmer' 19 | environment variable as well. When linking against libwee8 for V8 support, 20 | set it to 'NGX_WASM_RUNTIME=v8'. 21 | 22 | Build/install Nginx with: 23 | 24 | $ make -j4 && make install 25 | 26 | Finally, verify that the produced binary has been compiled with ngx_wasm_module: 27 | 28 | $ nginx -V # output should contain '--add-module=/path/to/ngx_wasm_module' 29 | 30 | Note: make sure that the 'nginx' binary in your '$PATH' is the one that you just 31 | installed, or else specify the intended binary appropriately to the shell (e.g. 32 | '$ /path/to/nginx ...'). 33 | 34 | For more in-depth installation instructions and examples, consult the 35 | repository's extended documentation (mind your release version): 36 | 37 | https://github.com/Kong/ngx_wasm_module/blob/main/docs/INSTALL.md 38 | -------------------------------------------------------------------------------- /assets/release/README: -------------------------------------------------------------------------------- 1 | The nginx executable is a pre-compiled Nginx binary which includes 2 | ngx_wasm_module as an addon. 3 | 4 | Verify the binary: 5 | 6 | $ ./nginx -V 7 | 8 | Start Nginx with: 9 | 10 | $ ./nginx 11 | 12 | This will start Nginx using the current directory as a prefix (i.e. working 13 | directory). See nginx.conf for configuration. 14 | 15 | Stop Nginx with: 16 | 17 | $ ./nginx -s stop 18 | 19 | For ngx_wasm_module usage instructions, consult the repository's extended 20 | documentation (mind your release version): 21 | 22 | https://github.com/Kong/ngx_wasm_module/blob/main/docs/README.md 23 | -------------------------------------------------------------------------------- /assets/release/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes auto; 2 | error_log error.log info; 3 | 4 | env RUST_BACKTRACE=full; 5 | 6 | events {} 7 | 8 | wasm { 9 | # https://github.com/wasmx-proxy/proxy-wasm-rust-filter-echo 10 | #module echo_filter proxy_wasm_filter_echo.wasm; 11 | } 12 | 13 | http { 14 | server { 15 | listen 9000; 16 | 17 | location / { 18 | #proxy_wasm echo_filter; 19 | return 200; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /auto/runtime: -------------------------------------------------------------------------------- 1 | if [ $ngx_found = yes ]; then 2 | return 3 | fi 4 | 5 | ngx_feature="$ngx_wasm_runtime_name library" 6 | ngx_feature_path= 7 | ngx_feature_libs= 8 | 9 | if [ -z "$ngx_wasm_runtime_lib_name" ]; then 10 | ngx_wasm_runtime_lib_name="$ngx_wasm_runtime_name" 11 | fi 12 | 13 | if [ -n "$ngx_wasm_runtime_inc" ]; then 14 | ngx_feature="$ngx_feature, $ngx_wasm_runtime_inc" 15 | ngx_feature_path="$ngx_wasm_runtime_inc" 16 | fi 17 | 18 | if [ -n "$ngx_wasm_runtime_lib" ]; then 19 | ngx_wasm_rpath="" 20 | 21 | if [ $NGX_RPATH = YES ]; then 22 | ngx_wasm_rpath="$(echo "$ngx_wasm_runtime_lib" | sed 's/-L/-R/g')" 23 | 24 | elif [ "$NGX_WASM_RUNTIME_NO_RPATH" != 1 ]; then 25 | ngx_wasm_rpath="$(echo "$ngx_wasm_runtime_lib" | sed 's/-L/-Wl,-rpath,/g')" 26 | fi 27 | 28 | ngx_feature="$ngx_feature, $ngx_wasm_runtime_lib $ngx_wasm_rpath -l$ngx_wasm_runtime_lib_name" 29 | ngx_feature_libs="$ngx_wasm_runtime_lib $ngx_wasm_rpath -l$ngx_wasm_runtime_lib_name" 30 | fi 31 | 32 | if [ -n "$ngx_wasm_runtime_opt" ]; then 33 | ngx_feature="$ngx_feature ($ngx_wasm_runtime_opt)" 34 | ngx_feature_libs="$ngx_wasm_runtime_opt" 35 | fi 36 | 37 | if [ -z "$ngx_feature_libs" -a -n "$ngx_wasm_runtime_lib_name" ]; then 38 | ngx_feature="$ngx_feature, -l$ngx_wasm_runtime_lib_name" 39 | ngx_feature_libs="-l$ngx_wasm_runtime_lib_name" 40 | fi 41 | 42 | if [ -n "$ngx_wasm_runtime_pre_libs" ]; then 43 | ngx_feature="$ngx_wasm_runtime_pre_libs $ngx_feature" 44 | ngx_feature_libs="$ngx_wasm_runtime_pre_libs $ngx_feature_libs" 45 | fi 46 | 47 | if [ -n "$ngx_wasm_runtime_post_libs" ]; then 48 | ngx_feature="$ngx_feature $ngx_wasm_runtime_post_libs" 49 | ngx_feature_libs="$ngx_feature_libs $ngx_wasm_runtime_post_libs" 50 | fi 51 | 52 | ngx_feature_run=yes 53 | ngx_feature_test="wasm_engine_t *e = wasm_engine_new(); 54 | assert(e); 55 | wasm_engine_delete(e);" 56 | 57 | . auto/feature 58 | 59 | # vim:ft=sh ts=4 sts=4 sw=4: 60 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # https://docs.codecov.io/docs/codecovyml-reference 2 | codecov: 3 | require_ci_to_pass: yes 4 | notify: 5 | wait_for_ci: yes 6 | 7 | coverage: 8 | precision: 5 9 | round: down 10 | range: "75...90" 11 | status: 12 | project: 13 | default: 14 | target: auto 15 | threshold: 3% 16 | flags: 17 | - unit 18 | paths: 19 | - src 20 | patch: 21 | default: 22 | target: 50% 23 | threshold: 3% 24 | flags: 25 | - unit 26 | paths: 27 | - src 28 | 29 | flag_management: 30 | individual_flags: 31 | - name: unit 32 | paths: 33 | - src/ 34 | after_n_builds: 9 35 | - name: valgrind 36 | paths: 37 | - src/ 38 | after_n_builds: 5 39 | 40 | comment: 41 | layout: "header, reach, diff, files, flags" 42 | behavior: default 43 | require_changes: false 44 | require_base: no 45 | require_head: yes 46 | -------------------------------------------------------------------------------- /docs/PROXY_WASM_HOST_DIFFERENCES.md: -------------------------------------------------------------------------------- 1 | # Proxy-Wasm Host Differences 2 | 3 | Listed here are noteworthy internal discrepancies (implementation differences) 4 | between ngx_wasm_module and other Proxy-Wasm host implementations. 5 | 6 | ## Table of Contents 7 | 8 | - [Metrics Prefixing](#metrics-prefixing) 9 | 10 | ## Metrics Prefixing 11 | 12 | - Envoy internally prefixes metric names with `wasmcustom.*` and only exposes 13 | this prefix in the output of the `/metrics` endpoint. 14 | - For internal implementation reasons, ngx_wasm_module prefixes metric names 15 | with `pw.[filter_name].*`, where `filter_name` is the name of the filter 16 | that defined the metric. Only the ngx_wasm_module FFI library may expose the 17 | existence of this prefix. 18 | 19 | Proxy-Wasm SDK users need not worry as metric names are never exposed through 20 | the SDK in the first place. 21 | 22 | [Back to TOC](#table-of-contents) 23 | -------------------------------------------------------------------------------- /docs/adr/000-template.md: -------------------------------------------------------------------------------- 1 | # [short title of solved problem and solution] 2 | 3 | * Status: [proposed | rejected | accepted | deprecated | … | superseded by [ADR-0005](0005-example.md)] 4 | * Deciders: [list everyone involved in the decision] 5 | * Date: [YYYY-MM-DD when the decision was last updated] 6 | 7 | Technical Story: [description | ticket/issue URL] 8 | 9 | ## Context and Problem Statement 10 | 11 | [Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.] 12 | 13 | ## Decision Drivers 14 | 15 | * [driver 1, e.g., a force, facing concern, …] 16 | * [driver 2, e.g., a force, facing concern, …] 17 | * … 18 | 19 | ## Considered Options 20 | 21 | * [option 1] 22 | * [option 2] 23 | * [option 3] 24 | * … 25 | 26 | ## Decision Outcome 27 | 28 | Chosen option: "[option 1]", because [justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force force | … | comes out best (see below)]. 29 | 30 | ### Positive Consequences 31 | 32 | * [e.g., improvement of quality attribute satisfaction, follow-up decisions required, …] 33 | * … 34 | 35 | ### Negative Consequences 36 | 37 | * [e.g., compromising quality attribute, follow-up decisions required, …] 38 | * … 39 | 40 | ## Pros and Cons of the Options 41 | 42 | ### [option 1] 43 | 44 | [example | description | pointer to more information | …] 45 | 46 | * Good, because [argument a] 47 | * Good, because [argument b] 48 | * Bad, because [argument c] 49 | * … 50 | 51 | ### [option 2] 52 | 53 | [example | description | pointer to more information | …] 54 | 55 | * Good, because [argument a] 56 | * Good, because [argument b] 57 | * Bad, because [argument c] 58 | * … 59 | 60 | ### [option 3] 61 | 62 | [example | description | pointer to more information | …] 63 | 64 | * Good, because [argument a] 65 | * Good, because [argument b] 66 | * Bad, because [argument c] 67 | * … 68 | 69 | ## Links 70 | 71 | * [Link type] [Link to ADR] 72 | * … 73 | 74 | 75 | -------------------------------------------------------------------------------- /lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "ngx-rust", 4 | "ngx-wasm-rs", 5 | ] 6 | -------------------------------------------------------------------------------- /lib/ngx-rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ngx" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /lib/ngx-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | name = "ngx" 9 | -------------------------------------------------------------------------------- /lib/ngx-rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod log; 2 | pub use log::*; 3 | 4 | pub mod resp; 5 | pub use resp::*; 6 | -------------------------------------------------------------------------------- /lib/ngx-rust/src/log.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! ngx_log { 3 | ($lvl:ident, $fmt:expr, $($arg:tt)*) => { 4 | let msg = format!("{}", format_args!($fmt, $($arg)*)); 5 | ngx_log_err(NgxLogErrLvl::$lvl, msg); 6 | }; 7 | ($lvl:ident, $($arg:tt)*) => { 8 | let msg = format!("{}", format_args!("{}", $($arg)*)); 9 | ngx_log_err(NgxLogErrLvl::$lvl, msg); 10 | }; 11 | } 12 | 13 | pub enum NgxLogErrLvl { 14 | Stderr, 15 | Emerg, 16 | Alert, 17 | Crit, 18 | Err, 19 | Warn, 20 | Notice, 21 | Info, 22 | Debug, 23 | } 24 | 25 | extern "C" { 26 | fn ngx_log(level: u32, msg: *const u8, size: i32); 27 | } 28 | 29 | pub fn ngx_log_err(level: NgxLogErrLvl, msg: String) { 30 | let lvl: u32 = match level { 31 | NgxLogErrLvl::Stderr => 0, 32 | NgxLogErrLvl::Emerg => 1, 33 | NgxLogErrLvl::Alert => 2, 34 | NgxLogErrLvl::Crit => 3, 35 | NgxLogErrLvl::Err => 4, 36 | NgxLogErrLvl::Warn => 5, 37 | NgxLogErrLvl::Notice => 6, 38 | NgxLogErrLvl::Info => 7, 39 | NgxLogErrLvl::Debug => 8, 40 | }; 41 | 42 | unsafe { 43 | ngx_log(lvl, msg.as_ptr(), msg.len() as i32) 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/ngx-rust/src/resp.rs: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | fn ngx_http_resp_get_status() -> i32; 3 | fn ngx_http_resp_set_status(status: i32); 4 | fn ngx_http_resp_say(body: *const u8, size: i32); 5 | fn ngx_http_local_response( 6 | status: i32, 7 | reason: *const u8, 8 | reason_len: i32, 9 | body: *const u8, 10 | body_len: i32, 11 | ); 12 | fn ngx_http_discard_local_response(); 13 | } 14 | 15 | pub fn ngx_resp_get_status() -> i32 { 16 | unsafe { ngx_http_resp_get_status() } 17 | } 18 | 19 | pub fn ngx_resp_set_status(status: i32) { 20 | unsafe { ngx_http_resp_set_status(status) } 21 | } 22 | 23 | pub fn ngx_resp_say(body: Option<&str>) { 24 | unsafe { 25 | ngx_http_resp_say( 26 | body.unwrap_or_default().as_ptr(), 27 | body.unwrap_or_default().len() as i32, 28 | ) 29 | } 30 | } 31 | 32 | pub fn ngx_resp_local(status: i32, reason: Option<&str>, body: Option<&str>) { 33 | unsafe { 34 | ngx_http_local_response( 35 | status, 36 | reason.unwrap_or_default().as_ptr(), 37 | reason.unwrap_or_default().len() as i32, 38 | body.unwrap_or_default().as_ptr(), 39 | body.unwrap_or_default().len() as i32, 40 | ) 41 | } 42 | } 43 | 44 | pub fn ngx_resp_discard_local() { 45 | unsafe { ngx_http_discard_local_response() } 46 | } 47 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-wasm" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | ngx-wasm-wat = { path = "lib/wat", optional = true } 9 | ngx-wasm-backtrace = { path = "lib/backtrace" } 10 | 11 | [features] 12 | wat = ["dep:ngx-wasm-wat"] 13 | 14 | [lib] 15 | name = "ngx_wasm_rs" 16 | crate-type = ["staticlib", "cdylib"] 17 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/include/ngx_wasm_backtrace.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_BACKTRACE_H_INCLUDED_ 2 | #define _NGX_WASM_BACKTRACE_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | typedef struct { 11 | uint32_t idx; 12 | wasm_byte_vec_t *name; 13 | } ngx_wasm_backtrace_name_t; 14 | 15 | 16 | typedef struct { 17 | uint64_t size; 18 | ngx_wasm_backtrace_name_t *table; 19 | } ngx_wasm_backtrace_name_table_t; 20 | 21 | 22 | ngx_wasm_backtrace_name_table_t* ngx_wasm_backtrace_get_name_table( 23 | const wasm_byte_vec_t *wasm); 24 | void ngx_wasm_backtrace_free_name_table(ngx_wasm_backtrace_name_table_t* t); 25 | void ngx_wasm_backtrace_demangle(const wasm_byte_vec_t *mangled, 26 | wasm_byte_vec_t *demangled); 27 | void ngx_wasm_backtrace_drop_byte_vec(const wasm_byte_vec_t *vec); 28 | 29 | 30 | #endif /* _NGX_WASM_BACKTRACE_H_INCLUDED_ */ 31 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/include/ngx_wasm_wat.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_WAT_H_INCLUDED_ 2 | #define _NGX_WASM_WAT_H_INCLUDED_ 3 | 4 | #include 5 | 6 | /* 7 | Reads a buffer containing textual .wat data, parses it, 8 | and writes a buffer containing .wasm data. 9 | 10 | Parameters: 11 | * wat: pointer to a wasm_byte_vec_t containing the input in .wat format. 12 | * wasm: pointer to a wasm_byte_vec_t that will contain the generated .wasm data. 13 | This needs to point to an allocated struct, but its given contents are 14 | ignored; the contents are filled by this function in case of a 15 | successful parse. 16 | 17 | Return value: 18 | * NULL in case of a successful parse, or a pointer to a newly allocated 19 | wasm_byte_vec_t containing the error message, owned by the caller. 20 | */ 21 | wasm_byte_vec_t* ngx_wasm_wat_to_wasm(const wasm_byte_vec_t *wat, 22 | wasm_byte_vec_t *wasm); 23 | 24 | #endif /* _NGX_WASM_WAT_H_INCLUDED_ */ 25 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/backtrace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-wasm-backtrace" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | ngx-wasm-c-api = { path = "../c-api" } 9 | wasmparser = "0.102" 10 | rustc-demangle = "0.1" 11 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/backtrace/README.md: -------------------------------------------------------------------------------- 1 | # Backtrace handling module 2 | 3 | Operations for turning WASM trap objects into human-readable backtraces. 4 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/backtrace/src/backtrace.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryInto; 2 | 3 | // see specification at: 4 | // https://webassembly.github.io/spec/core/appendix/custom.html#name-section 5 | fn read_name_section( 6 | mut reader: wasmparser::BinaryReader, 7 | ) -> Result, wasmparser::BinaryReaderError> { 8 | let mut table: Vec<(u32, String)> = Vec::new(); 9 | 10 | while !reader.eof() { 11 | let id = reader.read_u8()?; 12 | let size = reader.read_var_u32()?; 13 | 14 | if id != 1 { 15 | reader.read_bytes(size.try_into().unwrap())?; 16 | continue; 17 | } 18 | 19 | let len = reader.read_var_u32()?; 20 | 21 | for _ in 0..len { 22 | let idx = reader.read_var_u32()?; 23 | let name = reader.read_string()?; 24 | 25 | table.push((idx, name.to_string())); 26 | } 27 | } 28 | 29 | Ok(table) 30 | } 31 | 32 | pub(crate) fn get_function_name_table( 33 | wasm_slice: &[u8], 34 | ) -> Result, wasmparser::BinaryReaderError> { 35 | for payload in wasmparser::Parser::new(0).parse_all(wasm_slice).flatten() { 36 | if let wasmparser::Payload::CustomSection(s) = payload { 37 | if s.name() == "name" { 38 | let reader = wasmparser::BinaryReader::new(s.data()); 39 | return read_name_section(reader); 40 | } 41 | } 42 | } 43 | 44 | Ok(Vec::new()) 45 | } 46 | 47 | pub(crate) fn demangle(mangled: &str) -> String { 48 | rustc_demangle::demangle(mangled).to_string() 49 | } 50 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/backtrace/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod backtrace; 2 | pub mod c_api; 3 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/c-api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-wasm-c-api" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/c-api/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[repr(C)] 2 | pub struct wasm_byte_vec_t { 3 | pub size: usize, 4 | pub data: *mut u8, 5 | } 6 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/wat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-wasm-wat" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | ngx-wasm-c-api = { path = "../c-api" } 9 | wabt = "0.10.0" 10 | regex = "1.5.6" 11 | libc = "*" 12 | unescape = "0.1.0" 13 | lazy_static = "*" 14 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/wat/README.md: -------------------------------------------------------------------------------- 1 | # .wat processing module 2 | 3 | Functionality for converting `.wat` data (text-based WebAssembly) 4 | into `.wasm` data (binary WebAssembly executable by all VMs). 5 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/lib/wat/src/lib.rs: -------------------------------------------------------------------------------- 1 | use ngx_wasm_c_api::*; 2 | use regex::Regex; 3 | use std::mem; 4 | use unescape::unescape; 5 | 6 | #[macro_use] 7 | extern crate lazy_static; 8 | 9 | fn extract_message(err: &str) -> Option { 10 | static PAT: &str = r#"Error\(Parse\("[^:]+:[^:]+:[^:]+: error: (.*).*"\)\)$"#; 11 | lazy_static! { 12 | static ref RE: Regex = Regex::new(PAT).unwrap(); 13 | } 14 | 15 | let caps = RE.captures(err)?; 16 | let cap = caps.get(1)?; 17 | let u = unescape(cap.as_str())?; 18 | if let Some((first, _)) = u.split_once('\n') { 19 | Some(first.to_string()) 20 | } else { 21 | Some(u) 22 | } 23 | } 24 | 25 | fn vec_into_wasm_byte_vec_t(bv: *mut wasm_byte_vec_t, v: Vec) { 26 | unsafe { 27 | // FIXME Update this when vec_into_raw_parts is stabilized 28 | let mut v = mem::ManuallyDrop::new(v); 29 | (*bv).size = v.len(); 30 | (*bv).data = v.as_mut_ptr(); 31 | } 32 | } 33 | 34 | /// # Safety 35 | /// 36 | /// This function should be called with a valid wat wasm_byte_vec_t pointer. 37 | #[no_mangle] 38 | pub unsafe extern "C" fn ngx_wasm_wat_to_wasm( 39 | wat: *const wasm_byte_vec_t, 40 | wasm: *mut wasm_byte_vec_t, 41 | ) -> Option> { 42 | let empty = Vec::new(); 43 | let mut wat_slice = empty.as_ref(); 44 | 45 | unsafe { 46 | if (*wat).size > 0 { 47 | wat_slice = std::slice::from_raw_parts((*wat).data, (*wat).size); 48 | } 49 | } 50 | 51 | match wabt::wat2wasm(wat_slice) { 52 | Ok(mut wasm_vec) => { 53 | wasm_vec.shrink_to_fit(); 54 | vec_into_wasm_byte_vec_t(wasm, wasm_vec); 55 | None 56 | } 57 | Err(e) => { 58 | let err = e.to_string(); 59 | let msg = extract_message(&err).unwrap_or(err); 60 | let mut bytes = msg.into_bytes(); 61 | 62 | let res = Box::new(wasm_byte_vec_t { 63 | size: bytes.len(), 64 | data: bytes.as_mut_ptr(), 65 | }); 66 | mem::forget(bytes); 67 | Some(res) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/ngx-wasm-rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use ngx_wasm_backtrace; 2 | #[cfg(feature = "wat")] 3 | pub use ngx_wasm_wat; 4 | -------------------------------------------------------------------------------- /lib/resty/wasmx.lua: -------------------------------------------------------------------------------- 1 | -- vim:set ts=4 sw=4 sts=4 et: 2 | 3 | local ffi = require "ffi" 4 | local base = require "resty.core.base" 5 | 6 | 7 | local C = ffi.C 8 | local assert = assert 9 | local get_string_buf = base.get_string_buf 10 | local get_size_ptr = base.get_size_ptr 11 | local DEBUG_MODE = ngx.config.debug 12 | 13 | 14 | ffi.cdef [[ 15 | typedef struct { 16 | ngx_str_t *name; 17 | ngx_str_t *config; 18 | } ngx_wasm_filter_t; 19 | 20 | typedef unsigned char u_char; 21 | typedef intptr_t ngx_int_t; 22 | typedef uintptr_t ngx_uint_t; 23 | typedef ngx_uint_t ngx_msec_t; 24 | typedef struct ngx_log_s ngx_log_t; 25 | typedef struct ngx_wavm_t ngx_wasm_vm_t; 26 | typedef struct ngx_wasm_ops_plan_t ngx_wasm_plan_t; 27 | 28 | typedef ngx_int_t (*ngx_proxy_wasm_properties_ffi_handler_pt)(void *data, 29 | ngx_str_t *key, ngx_str_t *value, ngx_str_t *err); 30 | 31 | ngx_wasm_vm_t *ngx_wasm_ffi_main_vm(); 32 | ]] 33 | 34 | 35 | local ERR_BUF_SIZE = 256 36 | 37 | 38 | local _M = { 39 | FFI_DECLINED = base.FFI_DECLINED, 40 | FFI_ABORT = base.FFI_ABORT -- nil in OpenResty 1.21.4.1 41 | and base.FFI_ABORT 42 | or -6, 43 | FFI_BUSY = base.FFI_BUSY -- nil in OpenResty 1.25.3.2 44 | and base.FFI_BUSY 45 | or -3, 46 | FFI_ERROR = base.FFI_ERROR, 47 | FFI_DONE = base.FFI_DONE, 48 | FFI_OK = base.FFI_OK, 49 | 50 | get_request = base.get_request, 51 | } 52 | 53 | 54 | function _M.get_main_vm() 55 | return C.ngx_wasm_ffi_main_vm() 56 | end 57 | 58 | 59 | function _M.get_err_ptr() 60 | local errbuf = get_string_buf(ERR_BUF_SIZE) 61 | local errlen = get_size_ptr() 62 | 63 | errlen[0] = 0 64 | 65 | return errbuf, errlen 66 | end 67 | 68 | 69 | function _M.assert_debug(...) 70 | if DEBUG_MODE then 71 | return assert(...) 72 | end 73 | end 74 | 75 | 76 | return _M 77 | -------------------------------------------------------------------------------- /lib/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | -------------------------------------------------------------------------------- /lib/v8bridge/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build clean install libv8bridge 2 | 3 | TARGET ?= /usr/local 4 | V8_INCDIR ?= /usr/local/include 5 | CXXFLAGS += -I $(V8_INCDIR) -std=c++20 -O3 6 | 7 | build: libv8bridge 8 | 9 | libv8bridge: bridge.o 10 | ar rcs libv8bridge.a bridge.o 11 | 12 | install: 13 | cp ./libv8bridge.a $(TARGET)/lib/libv8bridge.a 14 | cp ./bridge.h $(TARGET)/include/v8bridge.h 15 | 16 | clean: 17 | find . '(' -name "*.o" -o -name "*.a" ')' -a -exec rm '{}' ';' 18 | -------------------------------------------------------------------------------- /lib/v8bridge/bridge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bridge.h" 3 | 4 | extern "C" int ngx_v8_enable_wasm_trap_handler(int use_v8_signal_handler) { 5 | return v8::V8::EnableWebAssemblyTrapHandler(use_v8_signal_handler); 6 | } 7 | 8 | extern "C" void ngx_v8_set_flags(const char *flags) { 9 | v8::V8::SetFlagsFromString(flags); 10 | } -------------------------------------------------------------------------------- /lib/v8bridge/bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WRT_V8_BRIDGE_H_INCLUDED_ 2 | #define _NGX_WRT_V8_BRIDGE_H_INCLUDED_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int ngx_v8_enable_wasm_trap_handler(int use_v8_signal_handler); 9 | void ngx_v8_set_flags(const char *flags); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* _NGX_WRT_V8_BRIDGE_H_INCLUDED_ */ 16 | -------------------------------------------------------------------------------- /lsan.suppress: -------------------------------------------------------------------------------- 1 | leak:src/core/nginx.c 2 | -------------------------------------------------------------------------------- /src/common/ddebug.h: -------------------------------------------------------------------------------- 1 | #ifndef _DDEBUG_H_INCLUDED_ 2 | #define _DDEBUG_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #if defined(DDEBUG) && (DDEBUG) 11 | # if (NGX_HAVE_VARIADIC_MACROS) 12 | # define dd(...) fprintf(stderr, "%s: ", __func__); \ 13 | fprintf(stderr, __VA_ARGS__); \ 14 | fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__) 15 | # else 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | static ngx_inline void 22 | dd(const char *fmt, ...) 23 | { 24 | } 25 | # endif 26 | #else 27 | # if (NGX_HAVE_VARIADIC_MACROS) 28 | # define dd(...) 29 | # else 30 | #include 31 | 32 | static ngx_inline void 33 | dd(const char *fmt, ...) 34 | { 35 | } 36 | # endif 37 | #endif 38 | 39 | 40 | #endif /* _DDEBUG_H_INCLUDED_ */ 41 | -------------------------------------------------------------------------------- /src/common/lua/ngx_wasm_lua_resolver.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_LUA_RESOLVER_H_INCLUDED_ 2 | #define _NGX_WASM_LUA_RESOLVER_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | #define NGX_WASM_LUA_RESOLVE_ERR 100 9 | 10 | 11 | ngx_int_t ngx_wasm_lua_resolver_resolve(ngx_resolver_ctx_t *rslv_ctx); 12 | 13 | 14 | #endif /* _NGX_WASM_LUA_RESOLVER_H_INCLUDED_ */ 15 | -------------------------------------------------------------------------------- /src/common/ngx_wa_readers.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | 9 | #if 0 10 | static void 11 | ngx_wa_read_log(ngx_buf_t *src, ngx_chain_t *buf_in, char *fmt) 12 | { 13 | size_t chunk_len; 14 | ngx_buf_t *buf; 15 | 16 | if (src) { 17 | dd("src %s: %p: %.*s (pos: %p, last: %p)", 18 | fmt, src, (int) ngx_buf_size(src), src->pos, 19 | src->pos, src->last); 20 | } 21 | 22 | for (/* void */; buf_in; buf_in = buf_in->next) { 23 | buf = buf_in->buf; 24 | chunk_len = buf->last - buf->pos; 25 | 26 | dd("buf_in %s: %p: %.*s", fmt, buf, 27 | (int) chunk_len, buf->pos); 28 | } 29 | } 30 | 31 | 32 | ngx_int_t 33 | ngx_wa_read_all(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes) 34 | { 35 | if (bytes == 0) { 36 | return NGX_OK; 37 | } 38 | 39 | buf_in->buf->last += bytes; 40 | src->pos += bytes; 41 | 42 | return NGX_AGAIN; 43 | } 44 | 45 | 46 | ngx_int_t 47 | ngx_wa_read_line(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes) 48 | { 49 | u_char *dst; 50 | u_char c; 51 | 52 | if (bytes == 0) { 53 | return NGX_ERROR; 54 | } 55 | 56 | dst = buf_in->buf->last; 57 | 58 | while (bytes--) { 59 | c = *src->pos++; 60 | 61 | switch (c) { 62 | case LF: 63 | buf_in->buf->last = dst; 64 | 65 | return NGX_OK; 66 | 67 | case CR: 68 | break; 69 | 70 | default: 71 | *dst++ = c; 72 | break; 73 | } 74 | } 75 | 76 | buf_in->buf->last = dst; 77 | 78 | return NGX_AGAIN; 79 | } 80 | #endif 81 | 82 | 83 | ngx_int_t 84 | ngx_wa_read_bytes(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes, 85 | size_t *rest) 86 | { 87 | if (bytes == 0) { 88 | return NGX_ERROR; 89 | } 90 | 91 | if ((size_t) bytes >= *rest) { 92 | src->pos += *rest; 93 | buf_in->buf->last = src->pos; 94 | *rest = 0; 95 | 96 | return NGX_OK; 97 | } 98 | 99 | buf_in->buf->last += bytes; 100 | src->pos += bytes; 101 | *rest -= bytes; 102 | 103 | return NGX_AGAIN; 104 | } 105 | -------------------------------------------------------------------------------- /src/common/ngx_wa_readers.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WA_READERS_H_INCLUDED_ 2 | #define _NGX_WA_READERS_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | #if 0 9 | ngx_int_t ngx_wa_read_all(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes); 10 | ngx_int_t ngx_wa_read_line(ngx_buf_t *src, ngx_chain_t *buf_in, ssize_t bytes); 11 | #endif 12 | ngx_int_t ngx_wa_read_bytes(ngx_buf_t *src, ngx_chain_t *buf_in, 13 | ssize_t bytes, size_t *rest); 14 | 15 | 16 | #endif /* _NGX_WA_READERS_H_INCLUDED_ */ 17 | -------------------------------------------------------------------------------- /src/common/ngx_wasm_socket_tcp_readers.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_SOCKET_TCP_READERS_H_INCLUDED_ 2 | #define _NGX_WASM_SOCKET_TCP_READERS_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | typedef struct ngx_wasm_socket_tcp_s ngx_wasm_socket_tcp_t; 9 | 10 | 11 | #ifdef NGX_WASM_HTTP 12 | typedef struct { 13 | ngx_pool_t *pool; 14 | ngx_log_t *log; 15 | ngx_wasm_socket_tcp_t *sock; 16 | ngx_http_wasm_req_ctx_t *rctx; 17 | ngx_http_request_t fake_r; 18 | ngx_http_status_t status; 19 | ngx_http_chunked_t chunked; 20 | ngx_http_upstream_conf_t uconf; 21 | ngx_uint_t status_code; 22 | ngx_chain_t *chunks; 23 | ngx_chain_t *body; 24 | size_t headers_len; 25 | size_t body_len; 26 | size_t rest; 27 | unsigned header_done:1; 28 | } ngx_wasm_http_reader_ctx_t; 29 | 30 | 31 | ngx_int_t ngx_wasm_read_http_response(ngx_buf_t *src, ngx_chain_t *buf_in, 32 | ssize_t bytes, ngx_wasm_http_reader_ctx_t *in_ctx); 33 | ngx_int_t ngx_wasm_http_reader_init(ngx_wasm_http_reader_ctx_t *in_ctx); 34 | #endif 35 | 36 | 37 | #endif /* _NGX_WASM_SOCKET_TCP_READERS_H_INCLUDED_ */ 38 | -------------------------------------------------------------------------------- /src/common/ngx_wasm_ssl.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | 9 | /* Modified from `ngx_ssl_trusted_certificate` */ 10 | ngx_int_t 11 | ngx_wasm_trusted_certificate(ngx_ssl_t *ssl, ngx_str_t *cert, 12 | ngx_int_t depth) 13 | { 14 | SSL_CTX_set_verify(ssl->ctx, SSL_CTX_get_verify_mode(ssl->ctx), 15 | ngx_wasm_ssl_verify_callback); 16 | 17 | SSL_CTX_set_verify_depth(ssl->ctx, depth); 18 | 19 | if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL) 20 | == 0) 21 | { 22 | ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 23 | "SSL_CTX_load_verify_locations(\"%s\") failed", 24 | cert->data); 25 | return NGX_ERROR; 26 | } 27 | 28 | /* 29 | * SSL_CTX_load_verify_locations() may leave errors in the error queue 30 | * while returning success 31 | */ 32 | 33 | ERR_clear_error(); 34 | 35 | return NGX_OK; 36 | } 37 | 38 | 39 | int 40 | ngx_wasm_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store) 41 | { 42 | return 1; 43 | } 44 | -------------------------------------------------------------------------------- /src/common/ngx_wasm_ssl.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_SSL_H_INCLUDED_ 2 | #define _NGX_WASM_SSL_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | typedef struct ngx_wasm_ssl_conf_s { 10 | ngx_str_t trusted_certificate; 11 | ngx_ssl_t ssl; 12 | 13 | ngx_flag_t verify_cert; 14 | ngx_flag_t verify_host; 15 | ngx_flag_t no_verify_warn; 16 | } ngx_wasm_ssl_conf_t; 17 | 18 | 19 | ngx_wasm_ssl_conf_t *ngx_wasm_core_ssl_conf(ngx_cycle_t *cycle); 20 | 21 | ngx_int_t ngx_wasm_trusted_certificate(ngx_ssl_t *ssl, 22 | ngx_str_t *cert, ngx_int_t depth); 23 | int ngx_wasm_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); 24 | 25 | 26 | #endif /* _NGX_WASM_SSL_H_INCLUDED_ */ 27 | -------------------------------------------------------------------------------- /src/common/ngx_wasm_subsystem.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | 9 | ngx_inline ngx_wasm_phase_t * 10 | ngx_wasm_phase_lookup(ngx_wasm_subsystem_t *subsys, ngx_uint_t phaseidx) 11 | { 12 | ngx_wasm_phase_t *phase = subsys->phases; 13 | 14 | while (phase->index != phaseidx) { 15 | phase++; 16 | 17 | if (phase->name.len == 0) { 18 | return NULL; 19 | } 20 | } 21 | 22 | return phase; 23 | } 24 | 25 | 26 | ngx_inline void 27 | ngx_wasm_set_resume_handler(ngx_wasm_subsys_env_t *env) 28 | { 29 | #if (NGX_WASM_HTTP) 30 | ngx_http_wasm_req_ctx_t *rctx; 31 | 32 | if (env->subsys->kind == NGX_WASM_SUBSYS_HTTP) { 33 | rctx = env->ctx.rctx; 34 | 35 | ngx_http_wasm_set_resume_handler(rctx); 36 | } 37 | #endif 38 | } 39 | 40 | 41 | ngx_inline void 42 | ngx_wasm_resume(ngx_wasm_subsys_env_t *env) 43 | { 44 | #if (NGX_WASM_HTTP) 45 | ngx_http_wasm_req_ctx_t *rctx; 46 | 47 | if (env->subsys->kind == NGX_WASM_SUBSYS_HTTP) { 48 | rctx = env->ctx.rctx; 49 | 50 | ngx_http_wasm_resume(rctx); 51 | } 52 | #endif 53 | } 54 | -------------------------------------------------------------------------------- /src/common/ngx_wasm_subsystem.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASM_SUBSYSTEM_H_INCLUDED_ 2 | #define _NGX_WASM_SUBSYSTEM_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #if (NGX_WASM_HTTP) 7 | #include 8 | #endif 9 | #if (NGX_WASM_STREAM) 10 | #include 11 | #endif 12 | 13 | 14 | #define ngx_wasm_continue(env) \ 15 | ngx_wasm_set_resume_handler(env); \ 16 | (env)->state = NGX_WASM_STATE_CONTINUE 17 | 18 | #define ngx_wasm_error(env) \ 19 | (env)->state = NGX_WASM_STATE_ERROR 20 | 21 | #define ngx_wasm_yield(env) \ 22 | (env)->state = NGX_WASM_STATE_YIELD; \ 23 | ngx_wasm_set_resume_handler(env) 24 | 25 | #define ngx_wasm_continuing(env) \ 26 | ((env)->state == NGX_WASM_STATE_CONTINUE) 27 | 28 | #define ngx_wasm_yielding(env) \ 29 | ((env)->state == NGX_WASM_STATE_YIELD) 30 | 31 | #define ngx_wasm_errored(env) \ 32 | ((env)->state == NGX_WASM_STATE_ERROR) 33 | 34 | #define ngx_wasm_bad_subsystem(env) \ 35 | ngx_wasm_log_error(NGX_LOG_WASM_NYI, env->connection->log, 0, \ 36 | "unexpected subsystem kind: %d", \ 37 | env->subsys->kind); \ 38 | ngx_wa_assert(0) 39 | 40 | 41 | ngx_wasm_phase_t *ngx_wasm_phase_lookup(ngx_wasm_subsystem_t *subsys, 42 | ngx_uint_t phaseidx); 43 | void ngx_wasm_set_resume_handler(ngx_wasm_subsys_env_t *env); 44 | void ngx_wasm_resume(ngx_wasm_subsys_env_t *env); 45 | 46 | 47 | #endif /* _NGX_WASM_SUBSYSTEM_H_INCLUDED_ */ 48 | -------------------------------------------------------------------------------- /src/common/proxy_wasm/ngx_proxy_wasm_foreign_call.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_PROXY_WASM_FOREIGN_CALLBACK_H_INCLUDED_ 2 | #define _NGX_PROXY_WASM_FOREIGN_CALLBACK_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #ifdef NGX_WASM_HTTP 10 | #include 11 | #endif 12 | 13 | 14 | struct ngx_proxy_wasm_foreign_call_s { 15 | ngx_proxy_wasm_exec_t *pwexec; 16 | #if (NGX_WASM_HTTP) 17 | ngx_http_wasm_req_ctx_t *rctx; 18 | #endif 19 | ngx_proxy_wasm_foreign_function_e fcode; 20 | ngx_chain_t *args_out; 21 | }; 22 | 23 | 24 | void ngx_proxy_wasm_foreign_call_destroy(ngx_proxy_wasm_foreign_call_t *call); 25 | 26 | 27 | #if (NGX_WASM_HTTP) 28 | ngx_int_t ngx_proxy_wasm_foreign_call_resolve_lua(ngx_wavm_instance_t *instance, 29 | ngx_http_wasm_req_ctx_t *rctx, ngx_str_t *fargs, ngx_wavm_ptr_t *ret_data, 30 | int32_t *ret_size, wasm_val_t rets[]); 31 | #endif 32 | 33 | 34 | #endif /* _NGX_PROXY_WASM_FOREIGN_CALLBACK_H_INCLUDED_ */ 35 | -------------------------------------------------------------------------------- /src/common/proxy_wasm/ngx_proxy_wasm_maps.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_PROXY_WASM_MAPS_H_INCLUDED_ 2 | #define _NGX_PROXY_WASM_MAPS_H_INCLUDED_ 3 | 4 | #include 5 | 6 | 7 | typedef enum { 8 | NGX_PROXY_WASM_MAP_SET = 0, 9 | NGX_PROXY_WASM_MAP_ADD, 10 | NGX_PROXY_WASM_MAP_REMOVE, 11 | } ngx_proxy_wasm_map_op_e; 12 | 13 | 14 | typedef struct ngx_proxy_wasm_maps_key_s ngx_proxy_wasm_maps_key_t; 15 | 16 | typedef ngx_str_t * (*ngx_proxy_wasm_maps_key_get_pt)( 17 | ngx_wavm_instance_t *instance, 18 | ngx_proxy_wasm_map_type_e map_type); 19 | typedef ngx_int_t (*ngx_proxy_wasm_maps_key_set_pt)( 20 | ngx_wavm_instance_t *instance, ngx_str_t *value, 21 | ngx_proxy_wasm_map_type_e map_type); 22 | 23 | 24 | struct ngx_proxy_wasm_maps_key_s { 25 | ngx_str_t key; 26 | ngx_uint_t map_type; 27 | ngx_proxy_wasm_maps_key_get_pt get_; 28 | ngx_proxy_wasm_maps_key_set_pt set_; 29 | }; 30 | 31 | 32 | ngx_list_t *ngx_proxy_wasm_maps_get_all(ngx_wavm_instance_t *instance, 33 | ngx_proxy_wasm_map_type_e map_type, ngx_array_t *extras); 34 | ngx_int_t ngx_proxy_wasm_maps_set_all(ngx_wavm_instance_t *instance, 35 | ngx_proxy_wasm_map_type_e map_type, ngx_array_t *pairs); 36 | ngx_str_t *ngx_proxy_wasm_maps_get(ngx_wavm_instance_t *instance, 37 | ngx_proxy_wasm_map_type_e map_type, ngx_str_t *key); 38 | ngx_int_t ngx_proxy_wasm_maps_set(ngx_wavm_instance_t *instance, 39 | ngx_proxy_wasm_map_type_e map_type, ngx_str_t *key, ngx_str_t *value, 40 | ngx_uint_t map_op); 41 | 42 | 43 | #endif /* _NGX_PROXY_WASM_MAPS_H_INCLUDED_ */ 44 | -------------------------------------------------------------------------------- /src/common/proxy_wasm/ngx_proxy_wasm_properties.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_PROXY_WASM_PROPERTIES_H_INCLUDED_ 2 | #define _NGX_PROXY_WASM_PROPERTIES_H_INCLUDED_ 3 | 4 | #include 5 | 6 | 7 | void ngx_proxy_wasm_properties_init(ngx_conf_t *cf); 8 | void ngx_proxy_wasm_properties_unmarsh_path(ngx_str_t *from, u_char **to); 9 | ngx_int_t ngx_proxy_wasm_properties_get(ngx_proxy_wasm_ctx_t *pwctx, 10 | ngx_str_t *path, ngx_str_t *value, ngx_str_t *err); 11 | ngx_int_t ngx_proxy_wasm_properties_set(ngx_proxy_wasm_ctx_t *pwctx, 12 | ngx_str_t *path, ngx_str_t *value, ngx_str_t *err); 13 | ngx_int_t ngx_proxy_wasm_properties_set_host(ngx_proxy_wasm_ctx_t *pwctx, 14 | ngx_str_t *path, ngx_str_t *value, unsigned is_const, unsigned retrieve); 15 | #if (NGX_WASM_LUA) 16 | ngx_int_t ngx_proxy_wasm_properties_set_ffi_handlers( 17 | ngx_proxy_wasm_ctx_t *pwctx, 18 | ngx_proxy_wasm_properties_ffi_handler_pt getter, 19 | ngx_proxy_wasm_properties_ffi_handler_pt setter, 20 | void *data); 21 | #endif 22 | 23 | 24 | #endif /* _NGX_PROXY_WASM_PROPERTIES_H_INCLUDED_ */ 25 | -------------------------------------------------------------------------------- /src/common/shm/ngx_wa_shm.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WA_SHM_H_INCLUDED_ 2 | #define _NGX_WA_SHM_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | #define NGX_WA_SHM_MIN_SIZE (3 * ngx_pagesize) 9 | #define NGX_WA_SHM_INDEX_NOTFOUND -1 10 | 11 | 12 | typedef enum { 13 | NGX_WA_SHM_TYPE_KV, 14 | NGX_WA_SHM_TYPE_QUEUE, 15 | NGX_WA_SHM_TYPE_METRICS, 16 | } ngx_wa_shm_type_e; 17 | 18 | 19 | typedef enum { 20 | NGX_WA_SHM_EVICTION_LRU, 21 | NGX_WA_SHM_EVICTION_SLRU, 22 | NGX_WA_SHM_EVICTION_NONE, 23 | } ngx_wa_shm_eviction_e; 24 | 25 | 26 | typedef struct { 27 | ngx_wa_shm_type_e type; 28 | ngx_wa_shm_eviction_e eviction; 29 | ngx_str_t name; 30 | ngx_log_t *log; 31 | ngx_slab_pool_t *shpool; 32 | void *data; 33 | } ngx_wa_shm_t; 34 | 35 | 36 | typedef struct { 37 | ngx_str_t name; 38 | ngx_shm_zone_t *zone; 39 | } ngx_wa_shm_mapping_t; 40 | 41 | 42 | ngx_int_t ngx_wa_shm_init(ngx_cycle_t *cycle); 43 | ngx_int_t ngx_wa_shm_init_zone(ngx_shm_zone_t *shm_zone, void *data); 44 | ngx_int_t ngx_wa_shm_init_process(ngx_cycle_t *cycle); 45 | ngx_int_t ngx_wa_shm_lookup_index(ngx_str_t *name); 46 | 47 | 48 | static ngx_inline void 49 | ngx_wa_shm_lock(ngx_wa_shm_t *shm) 50 | { 51 | ngx_shmtx_lock(&shm->shpool->mutex); 52 | } 53 | 54 | 55 | static ngx_inline void 56 | ngx_wa_shm_unlock(ngx_wa_shm_t *shm) 57 | { 58 | ngx_shmtx_unlock(&shm->shpool->mutex); 59 | } 60 | 61 | 62 | static ngx_inline unsigned 63 | ngx_wa_shm_locked(ngx_wa_shm_t *shm) 64 | { 65 | return (ngx_pid_t) *shm->shpool->mutex.lock == ngx_pid; 66 | } 67 | 68 | 69 | #endif /* _NGX_WA_SHM_H_INCLUDED_ */ 70 | -------------------------------------------------------------------------------- /src/common/shm/ngx_wa_shm_kv.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WA_SHM_KV_H_INCLUDED_ 2 | #define _NGX_WA_SHM_KV_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | typedef struct { 9 | ngx_rbtree_t rbtree; 10 | ngx_rbtree_node_t sentinel; 11 | ngx_uint_t nelts; 12 | union { 13 | ngx_queue_t lru_queue; 14 | ngx_queue_t slru_queues[0]; 15 | } eviction; 16 | } ngx_wa_shm_kv_t; 17 | 18 | 19 | typedef struct { 20 | ngx_str_t namespace; 21 | ngx_str_t key; 22 | ngx_shm_zone_t *zone; 23 | ngx_wa_shm_t *shm; 24 | } ngx_wa_shm_kv_key_t; 25 | 26 | 27 | typedef struct { 28 | ngx_str_node_t key; 29 | ngx_str_t value; 30 | uint32_t cas; 31 | ngx_queue_t queue; 32 | } ngx_wa_shm_kv_node_t; 33 | 34 | 35 | ngx_wa_shm_kv_t *ngx_wa_shm_get_kv(ngx_wa_shm_t *shm); 36 | 37 | ngx_int_t ngx_wa_shm_kv_init(ngx_wa_shm_t *shm); 38 | ngx_int_t ngx_wa_shm_kv_get_locked(ngx_wa_shm_t *shm, 39 | ngx_str_t *key, uint32_t *key_hash, ngx_str_t **value_out, uint32_t *cas); 40 | ngx_int_t ngx_wa_shm_kv_set_locked(ngx_wa_shm_t *shm, 41 | ngx_str_t *key, ngx_str_t *value, uint32_t cas, unsigned *written); 42 | ngx_int_t ngx_wa_shm_kv_resolve_key(ngx_str_t *key, ngx_wa_shm_kv_key_t *out); 43 | 44 | 45 | #endif /* _NGX_WA_SHM_KV_H_INCLUDED_ */ 46 | -------------------------------------------------------------------------------- /src/common/shm/ngx_wa_shm_queue.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WA_SHM_QUEUE_H_INCLUDED_ 2 | #define _NGX_WA_SHM_QUEUE_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | typedef void *(*ngx_wa_shm_queue_alloc_pt)(size_t size, void *alloc_ctx); 9 | 10 | 11 | ngx_int_t ngx_wa_shm_queue_init(ngx_wa_shm_t *shm); 12 | ngx_int_t ngx_wa_shm_queue_push_locked(ngx_wa_shm_t *shm, ngx_str_t *data); 13 | ngx_int_t ngx_wa_shm_queue_pop_locked(ngx_wa_shm_t *shm, 14 | ngx_str_t *data_out, ngx_wa_shm_queue_alloc_pt alloc, void *alloc_ctx); 15 | ngx_int_t ngx_wa_shm_queue_resolve(ngx_log_t *log, uint32_t token, 16 | ngx_shm_zone_t **out); 17 | 18 | 19 | #endif /* _NGX_WA_SHM_QUEUE_H_INCLUDED_ */ 20 | -------------------------------------------------------------------------------- /src/http/ngx_http_wasm_trailers.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_HTTP_WASM_TRAILERS_H_INCLUDED_ 2 | #define _NGX_HTTP_WASM_TRAILERS_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | size_t ngx_http_wasm_resp_trailers_count(ngx_http_request_t *r); 9 | 10 | 11 | #endif /* _NGX_HTTP_WASM_TRAILERS_H_INCLUDED_ */ 12 | -------------------------------------------------------------------------------- /src/http/ngx_http_wasm_trailers_response.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | 7 | #include 8 | 9 | 10 | #ifdef NGX_WASM_RESPONSE_TRAILERS 11 | size_t 12 | ngx_http_wasm_resp_trailers_count(ngx_http_request_t *r) 13 | { 14 | return ngx_wasm_list_nelts(&r->headers_out.trailers); 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /src/http/ngx_http_wasm_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_HTTP_WASM_UTIL_H_INCLUDED_ 2 | #define _NGX_HTTP_WASM_UTIL_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | typedef enum { 9 | NGX_HTTP_WASM_ESCAPE_URI = 0, 10 | NGX_HTTP_WASM_ESCAPE_URI_COMPONENT, 11 | NGX_HTTP_WASM_ESCAPE_ARGS, 12 | NGX_HTTP_WASM_ESCAPE_HEADER_NAME, 13 | NGX_HTTP_WASM_ESCAPE_HEADER_VALUE, 14 | } ngx_http_wasm_escape_kind; 15 | 16 | 17 | ngx_uint_t ngx_http_wasm_escape(u_char *dst, u_char *src, size_t size, 18 | ngx_http_wasm_escape_kind kind); 19 | ngx_str_t *ngx_http_copy_escaped(ngx_str_t *dst, ngx_pool_t *pool, 20 | ngx_http_wasm_escape_kind kind); 21 | ngx_int_t ngx_http_wasm_read_client_request_body(ngx_http_request_t *r, 22 | ngx_http_client_body_handler_pt post_handler); 23 | ngx_int_t ngx_http_wasm_send_chain_link(ngx_http_request_t *r, ngx_chain_t *in); 24 | 25 | /* proxy-wasm with wasm ops */ 26 | ngx_int_t ngx_http_wasm_ops_add_filter(ngx_wasm_ops_plan_t *plan, 27 | ngx_str_t *name, ngx_str_t *config, ngx_wavm_t *vm); 28 | 29 | /* fake requests */ 30 | ngx_connection_t *ngx_http_wasm_create_fake_connection(ngx_pool_t *pool); 31 | ngx_http_request_t *ngx_http_wasm_create_fake_request(ngx_connection_t *c); 32 | void ngx_http_wasm_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc); 33 | ngx_int_t ngx_http_wasm_create_fake_rctx(ngx_proxy_wasm_exec_t *pwexec, 34 | ngx_http_wasm_req_ctx_t **out); 35 | 36 | 37 | #endif /* _NGX_HTTP_WASM_UTIL_H_INCLUDED_ */ 38 | -------------------------------------------------------------------------------- /src/http/proxy_wasm/ngx_http_proxy_wasm.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_HTTP_PROXY_WASM_H_INCLUDED_ 2 | #define _NGX_HTTP_PROXY_WASM_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | void ngx_http_proxy_wasm_on_request_body_handler(ngx_http_request_t *r); 11 | 12 | 13 | static ngx_inline ngx_http_wasm_req_ctx_t * 14 | ngx_http_proxy_wasm_get_rctx(ngx_wavm_instance_t *instance) 15 | { 16 | ngx_proxy_wasm_exec_t *pwexec; 17 | ngx_proxy_wasm_ctx_t *pwctx; 18 | ngx_http_wasm_req_ctx_t *rctx; 19 | 20 | pwexec = ngx_proxy_wasm_instance2pwexec(instance); 21 | pwctx = pwexec->parent; 22 | if (pwctx == NULL) { 23 | return NULL; 24 | } 25 | 26 | rctx = (ngx_http_wasm_req_ctx_t *) pwctx->data; 27 | 28 | return rctx; 29 | } 30 | 31 | 32 | static ngx_inline ngx_http_request_t * 33 | ngx_http_proxy_wasm_get_req(ngx_wavm_instance_t *instance) 34 | { 35 | ngx_http_wasm_req_ctx_t *rctx; 36 | 37 | rctx = ngx_http_proxy_wasm_get_rctx(instance); 38 | 39 | return rctx->r; 40 | } 41 | 42 | 43 | extern ngx_proxy_wasm_subsystem_t ngx_http_proxy_wasm; 44 | 45 | 46 | #endif /* _NGX_HTTP_PROXY_WASM_H_INCLUDED_ */ 47 | -------------------------------------------------------------------------------- /src/ipc/ngx_ipc.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | -------------------------------------------------------------------------------- /src/ipc/ngx_ipc.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_IPC_H_INCLUDED_ 2 | #define _NGX_IPC_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | #define NGX_IPC_MODULE 0x00495043 /* "IPC" */ 9 | #define NGX_IPC_CONF 0x00400000 10 | 11 | #define ngx_ipc_core_cycle_get_conf(cycle) \ 12 | (ngx_get_conf(cycle->conf_ctx, ngx_wasmx_module)) \ 13 | ? (*(ngx_get_conf(cycle->conf_ctx, ngx_wasmx_module))) \ 14 | [ngx_ipc_core_module.ctx_index] \ 15 | : NULL 16 | 17 | 18 | typedef struct { 19 | ngx_wa_create_conf_pt create_conf; 20 | ngx_wa_init_conf_pt init_conf; 21 | ngx_wa_init_pt init; 22 | } ngx_ipc_module_t; 23 | 24 | 25 | typedef struct { 26 | void *p; /* stub */ 27 | } ngx_ipc_core_conf_t; 28 | 29 | 30 | extern ngx_module_t ngx_ipc_core_module; 31 | 32 | 33 | #endif /* _NGX_IPC_H_INCLUDED_ */ 34 | -------------------------------------------------------------------------------- /src/ipc/ngx_ipc_core_module.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | 8 | 9 | static void *ngx_ipc_core_create_conf(ngx_conf_t *cf); 10 | static char *ngx_ipc_core_init_conf(ngx_conf_t *cf, void *conf); 11 | static ngx_int_t ngx_ipc_core_init(ngx_cycle_t *cycle); 12 | static ngx_int_t ngx_ipc_core_init_process(ngx_cycle_t *cycle); 13 | 14 | 15 | static ngx_command_t ngx_ipc_core_commands[] = { 16 | ngx_null_command 17 | }; 18 | 19 | 20 | static ngx_ipc_module_t ngx_ipc_core_module_ctx = { 21 | ngx_ipc_core_create_conf, /* create configuration */ 22 | ngx_ipc_core_init_conf, /* init configuration */ 23 | ngx_ipc_core_init /* init module */ 24 | }; 25 | 26 | 27 | ngx_module_t ngx_ipc_core_module = { 28 | NGX_MODULE_V1, 29 | &ngx_ipc_core_module_ctx, /* module context */ 30 | ngx_ipc_core_commands, /* module directives */ 31 | NGX_IPC_MODULE, /* module type */ 32 | NULL, /* init master */ 33 | NULL, /* init module */ 34 | ngx_ipc_core_init_process, /* init process */ 35 | NULL, /* init thread */ 36 | NULL, /* exit thread */ 37 | NULL, /* exit process */ 38 | NULL, /* exit master */ 39 | NGX_MODULE_V1_PADDING 40 | }; 41 | 42 | 43 | static void * 44 | ngx_ipc_core_create_conf(ngx_conf_t *cf) 45 | { 46 | ngx_cycle_t *cycle = cf->cycle; 47 | ngx_ipc_core_conf_t *icf; 48 | 49 | icf = ngx_pcalloc(cycle->pool, sizeof(ngx_ipc_core_conf_t)); 50 | if (icf == NULL) { 51 | return NULL; 52 | } 53 | 54 | return icf; 55 | } 56 | 57 | 58 | static char * 59 | ngx_ipc_core_init_conf(ngx_conf_t *cf, void *conf) 60 | { 61 | return NGX_CONF_OK; 62 | } 63 | 64 | 65 | static ngx_int_t 66 | ngx_ipc_core_init(ngx_cycle_t *cycle) 67 | { 68 | ngx_log_debug0(NGX_LOG_DEBUG_ALL, cycle->log, 0, 69 | "ipc core module initializing"); 70 | return NGX_OK; 71 | } 72 | 73 | 74 | static ngx_int_t 75 | ngx_ipc_core_init_process(ngx_cycle_t *cycle) 76 | { 77 | return NGX_OK; 78 | } 79 | -------------------------------------------------------------------------------- /src/stream/ngx_stream_wasm.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_STREAM_WASM_H_INCLUDED_ 2 | #define _NGX_STREAM_WASM_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | struct ngx_stream_wasm_ctx_s { 10 | ngx_stream_session_t *s; 11 | ngx_connection_t *connection; 12 | ngx_pool_t *pool; /* r->pool */ 13 | ngx_wasm_op_ctx_t opctx; 14 | void *data; /* per-stream extra context */ 15 | 16 | ngx_chain_t *free_bufs; 17 | ngx_chain_t *busy_bufs; 18 | }; 19 | 20 | 21 | #endif /* _NGX_STREAM_WASM_H_INCLUDED_ */ 22 | -------------------------------------------------------------------------------- /src/stream/ngx_stream_wasm_module.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | static ngx_command_t ngx_stream_wasm_module_cmds[] = { 12 | ngx_null_command 13 | }; 14 | 15 | 16 | static ngx_stream_module_t ngx_stream_wasm_module_ctx = { 17 | NULL, /* preconfiguration */ 18 | NULL, /* postconfiguration */ 19 | 20 | NULL, /* create main configuration */ 21 | NULL, /* init main configuration */ 22 | 23 | NULL, /* create server configuration */ 24 | NULL /* merge server configuration */ 25 | }; 26 | 27 | 28 | ngx_module_t ngx_stream_wasm_module = { 29 | NGX_MODULE_V1, 30 | &ngx_stream_wasm_module_ctx, /* module context */ 31 | ngx_stream_wasm_module_cmds, /* module directives */ 32 | NGX_STREAM_MODULE, /* module type */ 33 | NULL, /* init master */ 34 | NULL, /* init module */ 35 | NULL, /* init process */ 36 | NULL, /* init thread */ 37 | NULL, /* exit thread */ 38 | NULL, /* exit process */ 39 | NULL, /* exit master */ 40 | NGX_MODULE_V1_PADDING 41 | }; 42 | -------------------------------------------------------------------------------- /src/stream/proxy_wasm/ngx_stream_proxy_wasm.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_STREAM_PROXY_WASM_H_INCLUDED_ 2 | #define _NGX_STREAM_PROXY_WASM_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | 8 | 9 | #endif /* _NGX_STREAM_PROXY_WASM_H_INCLUDED_ */ 10 | -------------------------------------------------------------------------------- /src/wasm/wasi/ngx_wasi.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_WASI_H_INCLUDED_ 2 | #define _NGX_WASI_H_INCLUDED_ 3 | 4 | 5 | #include 6 | 7 | 8 | #define WASI_CLOCKID_REALTIME 0 9 | #define WASI_CLOCKID_MONOTONIC 1 10 | 11 | #define WASI_ERRNO_SUCCESS 0 12 | #define WASI_ERRNO_BADF 8 13 | #define WASI_ERRNO_EFAULT 21 14 | #define WASI_ERRNO_NOTDIR 54 15 | #define WASI_ERRNO_NOTSUP 58 16 | 17 | 18 | extern ngx_wavm_host_def_t ngx_wasip1_host; 19 | 20 | 21 | #endif /* _NGX_WASI_H_INCLUDED_ */ 22 | -------------------------------------------------------------------------------- /src/wasm/wrt/ngx_wrt_utils.c: -------------------------------------------------------------------------------- 1 | #ifndef DDEBUG 2 | #define DDEBUG 0 3 | #endif 4 | #include "ddebug.h" 5 | 6 | #include 7 | #include 8 | 9 | 10 | static ngx_wrt_flag_handler_t * 11 | get_flag_handler(ngx_str_t *flag_name) 12 | { 13 | size_t i; 14 | ngx_str_t *n; 15 | 16 | for (i = 0; ngx_wrt.flag_handlers[i].flag_name.len; i++) { 17 | n = &ngx_wrt.flag_handlers[i].flag_name; 18 | if (ngx_str_eq(flag_name->data, flag_name->len, n->data, n->len)) { 19 | return &ngx_wrt.flag_handlers[i]; 20 | } 21 | } 22 | 23 | return NULL; 24 | } 25 | 26 | 27 | ngx_int_t 28 | ngx_wrt_add_flag(ngx_array_t *flags, ngx_str_t *name, ngx_str_t *value) 29 | { 30 | ngx_wrt_flag_t *flag; 31 | ngx_wrt_flag_handler_t *flag_handler = get_flag_handler(name); 32 | 33 | if (flag_handler) { 34 | if (flag_handler->handler) { 35 | flag = ngx_array_push(flags); 36 | flag->name = *name; 37 | flag->value = *value; 38 | return NGX_OK; 39 | } 40 | 41 | return NGX_DECLINED; 42 | } 43 | 44 | return NGX_ABORT; 45 | } 46 | 47 | 48 | ngx_int_t 49 | ngx_wrt_apply_flags(wasm_config_t *config, ngx_wavm_conf_t *conf, 50 | ngx_log_t *log) 51 | { 52 | size_t i; 53 | ngx_int_t rc = NGX_OK; 54 | ngx_str_t *name, *value; 55 | ngx_wrt_flag_t *flag = conf->flags.elts; 56 | ngx_wrt_flag_handler_t *handler; 57 | 58 | for (i = 0; i < conf->flags.nelts; i++) { 59 | name = &flag[i].name; 60 | value = &flag[i].value; 61 | 62 | ngx_wavm_log_error(NGX_LOG_INFO, log, NULL, 63 | "setting flag: \"%V=%V\"", name, value); 64 | 65 | handler = get_flag_handler(name); 66 | 67 | ngx_wa_assert(handler); 68 | ngx_wa_assert(handler->handler); 69 | 70 | rc = handler->handler(config, name, value, log, 71 | handler->wrt_config_set); 72 | if (rc != NGX_OK) { 73 | break; 74 | } 75 | } 76 | 77 | return rc; 78 | } 79 | -------------------------------------------------------------------------------- /t/01-wasm/001-wasm_block.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: wasm{} - empty block 13 | --- valgrind 14 | --- main_config 15 | wasm {} 16 | --- error_log 17 | initializing "main" wasm VM 18 | --- no_error_log 19 | [error] 20 | [crit] 21 | 22 | 23 | 24 | === TEST 2: wasm{} - no block, no VM 25 | --- main_config 26 | --- no_error_log 27 | wasm VM 28 | [error] 29 | [crit] 30 | 31 | 32 | 33 | === TEST 3: wasm{} - duplicated block 34 | --- main_config 35 | wasm {} 36 | wasm {} 37 | --- error_log 38 | "wasm" directive is duplicate 39 | --- no_error_log 40 | [error] 41 | [crit] 42 | --- must_die 43 | 44 | 45 | 46 | === TEST 4: wasm{} - unknown directive 47 | --- main_config 48 | wasm { 49 | unknown; 50 | } 51 | --- error_log 52 | unknown directive "unknown" 53 | --- no_error_log 54 | [error] 55 | [crit] 56 | --- must_die 57 | 58 | 59 | 60 | === TEST 5: wasm{} - invalid content 61 | --- main_config 62 | wasm { 63 | { 64 | } 65 | --- error_log 66 | unexpected "{" 67 | --- no_error_log 68 | [error] 69 | [crit] 70 | --- must_die 71 | -------------------------------------------------------------------------------- /t/01-wasm/002-shm_queue_sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | workers(2); 8 | master_on(); 9 | 10 | plan_tests(5); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: queue - with minimum size 16 | --- valgrind 17 | --- skip_no_debug 18 | --- main_config eval 19 | qq{ 20 | wasm { 21 | shm_queue test $::min_shm_size; 22 | } 23 | } 24 | --- error_log eval 25 | [ 26 | qr/\"test\" shm: initialization/, 27 | qr/\"test\" shm queue: initialized \(\d+ bytes available\)/ 28 | ] 29 | --- no_error_log 30 | [error] 31 | [crit] 32 | -------------------------------------------------------------------------------- /t/01-wasm/003-shm_kv_sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | workers(2); 8 | master_on(); 9 | 10 | plan_tests(5); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: kv - with minimum size 16 | --- valgrind 17 | --- skip_no_debug 18 | --- main_config eval 19 | qq{ 20 | wasm { 21 | shm_kv test $::min_shm_size; 22 | } 23 | } 24 | --- error_log 25 | "test" shm: initialization 26 | "test" shm store: initialized 27 | --- no_error_log 28 | [error] 29 | [crit] 30 | 31 | 32 | 33 | === TEST 2: kv - with default namespace 34 | --- skip_no_debug 35 | --- main_config eval 36 | qq{ 37 | wasm { 38 | shm_kv * $::min_shm_size; 39 | } 40 | } 41 | --- error_log 42 | "*" shm: initialization 43 | "*" shm store: initialized 44 | --- no_error_log 45 | [error] 46 | [crit] 47 | -------------------------------------------------------------------------------- /t/01-wasm/005-metrics_block.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: metrics{} - empty block 13 | --- valgrind 14 | --- main_config 15 | wasm { 16 | metrics {} 17 | } 18 | --- no_error_log 19 | [error] 20 | [crit] 21 | [emerg] 22 | 23 | 24 | 25 | === TEST 2: metrics{} - duplicated block 26 | --- main_config 27 | wasm { 28 | metrics {} 29 | metrics {} 30 | } 31 | --- error_log: is duplicate 32 | --- no_error_log 33 | [error] 34 | [crit] 35 | --- must_die 36 | 37 | 38 | 39 | === TEST 3: metrics{} - bad context 40 | --- http_config 41 | metrics {} 42 | --- error_log: is not allowed here 43 | --- no_error_log 44 | [error] 45 | [crit] 46 | --- must_die 47 | -------------------------------------------------------------------------------- /t/01-wasm/directives/004-resolver_directive.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: resolver directive - sanity 13 | --- valgrind 14 | --- main_config 15 | wasm { 16 | resolver 8.8.8.8; 17 | } 18 | --- no_error_log 19 | [error] 20 | [crit] 21 | [emerg] 22 | 23 | 24 | 25 | === TEST 2: resolver directive - duplicated 26 | --- main_config 27 | wasm { 28 | resolver 8.8.8.8; 29 | resolver 8.8.8.8; 30 | } 31 | --- error_log 32 | "resolver" directive is duplicate 33 | --- no_error_log 34 | [error] 35 | [crit] 36 | --- must_die 37 | 38 | 39 | 40 | === TEST 3: resolver directive - bad IP 41 | --- main_config 42 | wasm { 43 | resolver bad; 44 | } 45 | --- error_log 46 | host not found in resolver "bad" 47 | --- no_error_log 48 | [error] 49 | [crit] 50 | --- must_die 51 | 52 | 53 | 54 | === TEST 4: resolver_timeout directive - sanity 55 | --- main_config 56 | wasm { 57 | resolver 8.8.8.8; 58 | resolver_timeout 5s; 59 | } 60 | --- no_error_log 61 | [error] 62 | [crit] 63 | [emerg] 64 | 65 | 66 | 67 | === TEST 5: resolver_timeout directive - bad value 68 | --- main_config 69 | wasm { 70 | resolver 8.8.8.8; 71 | resolver_timeout bad; 72 | } 73 | --- error_log 74 | "resolver_timeout" directive invalid value 75 | --- no_error_log 76 | [error] 77 | [crit] 78 | --- must_die 79 | -------------------------------------------------------------------------------- /t/01-wasm/directives/005-socket_directives.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: wasm socket directives - sanity 13 | --- main_config 14 | wasm { 15 | socket_connect_timeout 1s; 16 | socket_send_timeout 1s; 17 | socket_read_timeout 1s; 18 | socket_buffer_size 1024; 19 | socket_large_buffers 1 1024; 20 | socket_buffer_reuse off; 21 | } 22 | --- no_error_log 23 | [error] 24 | [crit] 25 | [emerg] 26 | -------------------------------------------------------------------------------- /t/01-wasm/hfuncs/001-log.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | add_block_preprocessor(sub { 8 | my $block = shift; 9 | my $main_config = <<_EOC_; 10 | wasm { 11 | module ngx_rust_tests $t::TestWasmX::crates/ngx_rust_tests.wasm; 12 | } 13 | _EOC_ 14 | 15 | if (!defined $block->main_config) { 16 | $block->set_value("main_config", $main_config); 17 | } 18 | }); 19 | 20 | plan_tests(3); 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: log: logs in 'log' phase 26 | --- valgrind 27 | --- config 28 | location /t { 29 | wasm_call log ngx_rust_tests log_notice_hello; 30 | return 200; 31 | } 32 | --- error_log eval 33 | qr/\[notice\] .*? hello world while logging request/ 34 | --- no_error_log 35 | [error] 36 | 37 | 38 | 39 | === TEST 2: log: logs in 'rewrite' phase 40 | --- config 41 | location /t { 42 | wasm_call rewrite ngx_rust_tests log_notice_hello; 43 | return 200; 44 | } 45 | --- error_log eval 46 | qr/\[notice\] .*? hello world , client: 127\.0\.0\.1/ 47 | --- no_error_log 48 | [error] 49 | -------------------------------------------------------------------------------- /t/02-http/001-sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: 13 | --- valgrind 14 | --- config 15 | location /t { 16 | root html; 17 | } 18 | --- error_code: 404 19 | --- response_body_like: 404 Not Found 20 | --- error_log eval 21 | qr/\[error\] .*? No such file or directory/ 22 | --- no_error_log 23 | [crit] 24 | -------------------------------------------------------------------------------- /t/02-http/002-wasm_oob.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: wasm - oob memory read 13 | --- main_config 14 | wasm { 15 | module a $TEST_NGINX_HTML_DIR/a.wat; 16 | } 17 | --- config 18 | location /t { 19 | wasm_call rewrite a oob_read; 20 | return 200; 21 | } 22 | --- user_files 23 | >>> a.wat 24 | (module 25 | (memory (;0;) 25) 26 | (func (export "oob_read") 27 | i32.const 0x20000000 28 | i32.load 29 | drop) 30 | ) 31 | --- error_code: 500 32 | --- error_log eval 33 | qr/(\[error\] .*? out of bounds|wasm trap: out of bounds memory access|Uncaught RuntimeError: memory access out of bounds)/ 34 | --- no_error_log 35 | [crit] 36 | [alert] 37 | 38 | 39 | 40 | === TEST 2: wasm - oob memory write 41 | --- main_config 42 | wasm { 43 | module a $TEST_NGINX_HTML_DIR/a.wat; 44 | } 45 | --- config 46 | location /t { 47 | wasm_call rewrite a oob_write; 48 | return 200; 49 | } 50 | --- user_files 51 | >>> a.wat 52 | (module 53 | (memory (;0;) 25) 54 | (func (export "oob_write") 55 | i32.const 0x20000000 56 | i32.const 42 57 | i32.store) 58 | ) 59 | --- error_code: 500 60 | --- error_log eval 61 | qr/(\[error\] .*? out of bounds|wasm trap: out of bounds|Uncaught RuntimeError: memory access out of bounds)/ 62 | --- no_error_log 63 | [crit] 64 | [alert] 65 | -------------------------------------------------------------------------------- /t/02-http/005-postpone_access.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_debug(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: wasm_postpone_access - default (disabled) 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- config 17 | location /t { 18 | echo "ok"; 19 | } 20 | --- response_body 21 | ok 22 | --- grep_error_log eval: qr/wasm access handler/ 23 | --- grep_error_log_out 24 | wasm access handler 25 | 26 | 27 | 28 | === TEST 2: wasm_postpone_access - disabled 29 | --- load_nginx_modules: ngx_http_echo_module 30 | --- config 31 | location /t { 32 | wasm_postpone_access off; 33 | echo "ok"; 34 | } 35 | --- response_body 36 | ok 37 | --- grep_error_log eval: qr/wasm access handler/ 38 | --- grep_error_log_out 39 | wasm access handler 40 | 41 | 42 | 43 | === TEST 3: wasm_postpone_access - enabled 44 | --- load_nginx_modules: ngx_http_echo_module 45 | --- config 46 | location /t { 47 | wasm_postpone_access on; 48 | echo "ok"; 49 | } 50 | --- response_body 51 | ok 52 | --- grep_error_log eval: qr/wasm access handler/ 53 | --- grep_error_log_out 54 | wasm access handler 55 | wasm access handler 56 | 57 | 58 | 59 | === TEST 4: wasm_postpone_access - enabled in server{} block 60 | --- load_nginx_modules: ngx_http_echo_module 61 | --- config 62 | wasm_postpone_access on; 63 | 64 | location /t { 65 | echo "ok"; 66 | } 67 | --- response_body 68 | ok 69 | --- grep_error_log eval: qr/wasm access handler/ 70 | --- grep_error_log_out 71 | wasm access handler 72 | wasm access handler 73 | 74 | 75 | 76 | === TEST 5: wasm_postpone_access - enabled in http{} block 77 | --- load_nginx_modules: ngx_http_echo_module 78 | --- http_config 79 | wasm_postpone_access on; 80 | --- config 81 | location /t { 82 | echo "ok"; 83 | } 84 | --- response_body 85 | ok 86 | --- grep_error_log eval: qr/wasm access handler/ 87 | --- grep_error_log_out 88 | wasm access handler 89 | wasm access handler 90 | 91 | 92 | 93 | === TEST 6: wasm_postpone_access - enabled in http{} block, disabled in location{} 94 | --- load_nginx_modules: ngx_http_echo_module 95 | --- http_config 96 | wasm_postpone_access on; 97 | --- config 98 | location /t { 99 | wasm_postpone_access off; 100 | echo "ok"; 101 | } 102 | --- response_body 103 | ok 104 | --- grep_error_log eval: qr/wasm access handler/ 105 | --- grep_error_log_out 106 | wasm access handler 107 | -------------------------------------------------------------------------------- /t/02-http/hfuncs/001-resp_get_status.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | add_block_preprocessor(sub { 8 | my $block = shift; 9 | my $main_config = <<_EOC_; 10 | wasm { 11 | module ngx_rust_tests $t::TestWasmX::crates/ngx_rust_tests.wasm; 12 | } 13 | _EOC_ 14 | 15 | if (!defined $block->main_config) { 16 | $block->set_value("main_config", $main_config); 17 | } 18 | }); 19 | 20 | plan_tests(3); 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: resp_get_status: 'rewrite' phase 26 | --- config 27 | location /t { 28 | wasm_call rewrite ngx_rust_tests log_resp_status; 29 | return 200; 30 | } 31 | --- error_log 32 | resp status: 0 33 | --- no_error_log 34 | [error] 35 | 36 | 37 | 38 | === TEST 2: resp_get_status: 'content' phase 39 | --- load_nginx_modules: ngx_http_echo_module 40 | --- config 41 | location /t { 42 | wasm_call content ngx_rust_tests log_resp_status; 43 | echo ok; 44 | } 45 | --- error_log 46 | resp status: 0 47 | --- no_error_log 48 | [error] 49 | 50 | 51 | 52 | === TEST 3: resp_get_status: gets status in 'log' phase 53 | --- config 54 | location /t { 55 | wasm_call log ngx_rust_tests log_resp_status; 56 | return 200; 57 | } 58 | --- error_log eval 59 | qr/\[notice\] .*? resp status: 200/ 60 | --- no_error_log 61 | [error] 62 | -------------------------------------------------------------------------------- /t/02-http/hfuncs/002-resp_set_status.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | add_block_preprocessor(sub { 8 | my $block = shift; 9 | my $main_config = <<_EOC_; 10 | wasm { 11 | module ngx_rust_tests $t::TestWasmX::crates/ngx_rust_tests.wasm; 12 | } 13 | _EOC_ 14 | 15 | if (!defined $block->main_config) { 16 | $block->set_value("main_config", $main_config); 17 | } 18 | }); 19 | 20 | plan_tests(3); 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: resp_set_status: sets status code in 'rewrite' phase 26 | --- SKIP 27 | --- config 28 | location /t { 29 | wasm_call rewrite ngx_rust_tests set_resp_status; 30 | } 31 | --- response_body 32 | --- no_error_log 33 | [error] 34 | 35 | 36 | 37 | === TEST 2: resp_set_status: sets status code in 'content' phase 38 | --- config 39 | location /t { 40 | wasm_call content ngx_rust_tests set_resp_status; 41 | wasm_call content ngx_rust_tests say_hello; 42 | } 43 | --- error_code: 201 44 | --- response_body 45 | hello say 46 | --- no_error_log 47 | [error] 48 | 49 | 50 | 51 | === TEST 3: resp_set_status: bad usage in 'log' phase 52 | --- config 53 | location /t { 54 | return 200; 55 | wasm_call log ngx_rust_tests set_resp_status; 56 | } 57 | --- ignore_response_body 58 | --- grep_error_log eval: qr/(\[error\] .*?|.*?host trap).*/ 59 | --- grep_error_log_out eval 60 | qr/.*?(\[error\]|Uncaught RuntimeError: |\s+)host trap \(bad usage\): headers already sent.*/ 61 | --- no_error_log 62 | [alert] 63 | -------------------------------------------------------------------------------- /t/02-http/hfuncs/003-say.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(3); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: say: produce response in 'rewrite' phase 13 | --- wasm_modules: ngx_rust_tests 14 | --- config 15 | location /t { 16 | wasm_call rewrite ngx_rust_tests say_hello; 17 | } 18 | --- response_body 19 | hello say 20 | --- no_error_log 21 | [error] 22 | 23 | 24 | 25 | === TEST 2: say: produce response in 'content' phase 26 | --- wasm_modules: ngx_rust_tests 27 | --- config 28 | location /t { 29 | wasm_call content ngx_rust_tests say_hello; 30 | } 31 | --- response_body 32 | hello say 33 | --- no_error_log 34 | [error] 35 | 36 | 37 | 38 | === TEST 3: say: produce response in 'header_filter' phase 39 | --- load_nginx_modules: ngx_http_echo_module ngx_http_headers_more_filter_module 40 | --- wasm_modules: ngx_rust_tests 41 | --- config 42 | location /t { 43 | # force the Content-Length header value since say 44 | # will set it only once otherwise 45 | more_set_headers 'Content-Length: 20'; 46 | wasm_call content ngx_rust_tests say_hello; 47 | wasm_call header_filter ngx_rust_tests say_hello; 48 | } 49 | --- response_body 50 | hello say 51 | hello say 52 | --- no_error_log 53 | [error] 54 | 55 | 56 | 57 | === TEST 4: say: 'log' phase 58 | Should produce a trap. 59 | --- wasm_modules: ngx_rust_tests 60 | --- config 61 | location /t { 62 | return 200; 63 | wasm_call log ngx_rust_tests say_hello; 64 | } 65 | --- ignore_response_body 66 | --- grep_error_log eval: qr/(\[error\] .*?|.*?host trap).*/ 67 | --- grep_error_log_out eval 68 | qr/.*?(\[error\]|Uncaught RuntimeError: |\s+)host trap \(bad usage\): headers already sent.*/ 69 | --- no_error_log 70 | [crit] 71 | -------------------------------------------------------------------------------- /t/02-http/hfuncs/004-local_response.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | BEGIN { 4 | $ENV{MOCKEAGAIN} = 'w'; 5 | $ENV{MOCKEAGAIN_VERBOSE} ||= 1; 6 | $ENV{TEST_NGINX_EVENT_TYPE} = 'poll'; 7 | } 8 | 9 | use strict; 10 | use lib '.'; 11 | use t::TestWasmX; 12 | 13 | plan_tests(4); 14 | run_tests(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: local_response - pre-ops flush with status + reason 19 | --- wasm_modules: ngx_rust_tests 20 | --- config 21 | location /t { 22 | wasm_call rewrite ngx_rust_tests local_reason; 23 | } 24 | --- error_code: 201 25 | --- raw_response_headers_like 26 | HTTP/1.1 201 REASON\s 27 | --- no_error_log 28 | [error] 29 | [crit] 30 | 31 | 32 | 33 | === TEST 2: local_response - pre-ops flush with body 34 | --- load_nginx_modules: ngx_http_echo_module 35 | --- wasm_modules: ngx_rust_tests 36 | --- config 37 | location /t { 38 | wasm_call rewrite ngx_rust_tests local_response; 39 | echo fail; 40 | } 41 | --- response_body 42 | hello world 43 | --- no_error_log 44 | [error] 45 | [crit] 46 | 47 | 48 | 49 | === TEST 3: local_response - post-ops flush with body 50 | --- load_nginx_modules: ngx_http_echo_module 51 | --- wasm_modules: ngx_rust_tests 52 | --- config 53 | location /t { 54 | wasm_call content ngx_rust_tests local_response; 55 | echo fail; 56 | } 57 | --- response_body 58 | hello world 59 | --- no_error_log 60 | [error] 61 | [crit] 62 | 63 | 64 | 65 | === TEST 4: local_response - can be discarded 66 | --- load_nginx_modules: ngx_http_echo_module 67 | --- wasm_modules: ngx_rust_tests 68 | --- config 69 | location /t { 70 | wasm_call rewrite ngx_rust_tests local_response; 71 | wasm_call rewrite ngx_rust_tests discard_local_response; 72 | echo ok; 73 | } 74 | --- response_body 75 | ok 76 | --- no_error_log 77 | [error] 78 | [crit] 79 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/001-on_root_phases.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(5); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - on_vm_start without configuration 13 | --- wasm_modules: on_phases 14 | --- config 15 | location /t { 16 | proxy_wasm on_phases; 17 | return 200; 18 | } 19 | --- response_body 20 | --- error_log eval 21 | qr/\[info\] .*? on_vm_start, config_size: 0/ 22 | --- no_error_log 23 | [error] 24 | [crit] 25 | 26 | 27 | 28 | === TEST 2: proxy_wasm - on_vm_start with configuration 29 | --- main_config eval 30 | qq{ 31 | wasm { 32 | module on_phases $ENV{TEST_NGINX_CRATES_DIR}/on_phases.wasm 'foo=bar'; 33 | } 34 | } 35 | --- config 36 | location /t { 37 | proxy_wasm on_phases; 38 | return 200; 39 | } 40 | --- response_body 41 | --- error_log eval 42 | qr/\[info\] .*? on_vm_start, config_size: 7/ 43 | --- no_error_log 44 | [error] 45 | [crit] 46 | 47 | 48 | 49 | === TEST 3: proxy_wasm - on_configure without configuration 50 | --- wasm_modules: on_phases 51 | --- config 52 | location /t { 53 | proxy_wasm on_phases; 54 | return 200; 55 | } 56 | --- response_body 57 | --- error_log eval 58 | qr/\[info\] .*? on_configure, config_size: 0/ 59 | --- no_error_log 60 | [error] 61 | [crit] 62 | 63 | 64 | 65 | === TEST 4: proxy_wasm - on_configure with configuration 66 | --- wasm_modules: on_phases 67 | --- config 68 | location /t { 69 | proxy_wasm on_phases 'key=value foo=bar'; 70 | return 200; 71 | } 72 | --- response_body 73 | --- error_log eval 74 | [ 75 | qr/\[info\] .*? #0 on_configure, config_size: 17/, 76 | qr/\[info\] .*? #0 config: key=value foo=bar/ 77 | ] 78 | --- no_error_log 79 | [error] 80 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/005-on_http_phases_failures.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | use Test::Nginx::Socket skip_all => 'HTTP trailers support is not ready yet'; 7 | 8 | plan_tests(5); 9 | run_tests(); 10 | 11 | __DATA__ 12 | 13 | === TEST 1: proxy_wasm - trap on_response_trailers 14 | --- wasm_modules: hostcalls 15 | --- config 16 | location /t { 17 | proxy_wasm hostcalls 'on=response_trailers test=/t/trap'; 18 | return 200; 19 | } 20 | --- response_body 21 | --- error_log eval 22 | [ 23 | qr/\[crit\] .*? panicked at/, 24 | qr/custom trap/, 25 | ] 26 | --- no_error_log 27 | [emerg] 28 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/009-proxy_wasm_oob.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(3); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - proxy_get_header_map_value() with oob key 13 | --- wasm_modules: hostcalls 14 | --- config 15 | location /t { 16 | proxy_wasm hostcalls 'test=/t/safety/proxy_get_header_map_value_oob_key'; 17 | } 18 | --- error_code: 500 19 | --- error_log eval 20 | qr/host trap \(bad usage\): invalid slice pointer passed to host function/ 21 | --- no_error_log 22 | [alert] 23 | 24 | 25 | 26 | === TEST 2: proxy_wasm - proxy_get_header_map_value() with oob return data 27 | --- wasm_modules: hostcalls 28 | --- config 29 | location /t { 30 | proxy_wasm hostcalls 'test=/t/safety/proxy_get_header_map_value_oob_return_data'; 31 | } 32 | --- error_code: 500 33 | --- error_log eval 34 | qr/host trap \(bad usage\): invalid data pointer passed to host function/ 35 | --- no_error_log 36 | [alert] 37 | 38 | 39 | 40 | === TEST 3: proxy_wasm - proxy_get_header_map_value() with misaligned return data 41 | --- wasm_modules: hostcalls 42 | --- config 43 | location /t { 44 | proxy_wasm hostcalls 'test=/t/safety/proxy_get_header_map_value_misaligned_return_data'; 45 | } 46 | --- error_code: 500 47 | --- error_log eval 48 | qr/host trap \(bad usage\): invalid data pointer passed to host function/ 49 | --- no_error_log 50 | [alert] 51 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/010-eagain_sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | BEGIN { 4 | $ENV{MOCKEAGAIN} = 'rw'; 5 | $ENV{MOCKEAGAIN_VERBOSE} ||= 0; 6 | $ENV{TEST_NGINX_EVENT_TYPE} = 'poll'; 7 | } 8 | 9 | use strict; 10 | use lib '.'; 11 | use t::TestWasmX; 12 | 13 | plan_tests(5); 14 | run_tests(); 15 | 16 | __DATA__ 17 | 18 | === TEST 1: EAGAIN - reading request body 19 | --- load_nginx_modules: ngx_http_echo_module 20 | --- wasm_modules: on_phases 21 | --- config 22 | location /t { 23 | proxy_wasm on_phases; 24 | echo_sleep 0.3; 25 | echo ok; 26 | } 27 | --- request 28 | POST /t 29 | 30 | Hello world 31 | --- response_body 32 | ok 33 | --- grep_error_log eval: qr/#\d+ on_(request|log).*?(?=(, client|\s+while))/ 34 | --- grep_error_log_out eval 35 | qr/\A#\d+ on_request_headers, 3 headers, eof: false 36 | #\d+ on_request_body, 11 bytes, eof: true 37 | #\d+ on_log\Z/ 38 | --- no_error_log 39 | [error] 40 | [crit] 41 | 42 | 43 | 44 | === TEST 2: EAGAIN - reading request body in subrequest 45 | --- load_nginx_modules: ngx_http_echo_module 46 | --- wasm_modules: on_phases 47 | --- config 48 | location /subrequest { 49 | internal; 50 | proxy_wasm on_phases; 51 | echo_sleep 0.3; 52 | echo ok; 53 | } 54 | 55 | location /t { 56 | echo_subrequest POST '/subrequest' -b 'Hello world'; 57 | } 58 | --- response_body 59 | ok 60 | --- grep_error_log eval: qr/#\d+ on_(request|log).*?(?=(, client|\s+while))/ 61 | --- grep_error_log_out eval 62 | qr/\A#\d+ on_request_headers, 3 headers, eof: false 63 | #\d+ on_request_body, 11 bytes, eof: true\Z/ 64 | --- no_error_log 65 | [error] 66 | [crit] 67 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/directives/002-proxy_wasm_isolation_directive.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(6); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm_isolation directive - no wasm{} configuration block 13 | --- main_config 14 | --- config 15 | proxy_wasm_isolation none; 16 | --- error_log eval 17 | qr/\[emerg\] .*? "proxy_wasm_isolation" directive is specified but config has no "wasm" section/ 18 | --- no_error_log 19 | [warn] 20 | [error] 21 | [alert] 22 | [crit] 23 | --- must_die 24 | 25 | 26 | 27 | === TEST 2: proxy_wasm_isolation directive - invalid number of arguments 28 | --- config 29 | location /t { 30 | proxy_wasm_isolation none none; 31 | } 32 | --- error_log eval 33 | qr/\[emerg\] .*? invalid number of arguments in "proxy_wasm_isolation" directive/ 34 | --- no_error_log 35 | [warn] 36 | [error] 37 | [alert] 38 | [crit] 39 | --- must_die 40 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/directives/003-proxy_wasm_lua_resolver_directive.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(6); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm_lua_resolver directive - missing Lua support in http{} 13 | --- skip_eval: 6: $::nginxV =~ m/openresty/ 14 | --- config 15 | location /t { 16 | proxy_wasm_lua_resolver on; 17 | } 18 | --- error_log eval 19 | qr/\[emerg\] .*? \[wasm\] proxy_wasm_lua_resolver requires lua support/ 20 | --- no_error_log 21 | [warn] 22 | [error] 23 | [alert] 24 | [crit] 25 | --- must_die 26 | 27 | 28 | 29 | === TEST 2: proxy_wasm_lua_resolver directive - missing Lua support in wasm{} 30 | --- skip_eval: 6: $::nginxV =~ m/openresty/ 31 | --- main_config 32 | wasm { 33 | proxy_wasm_lua_resolver on; 34 | } 35 | --- error_log eval 36 | qr/\[emerg\] .*? \[wasm\] proxy_wasm_lua_resolver requires lua support/ 37 | --- no_error_log 38 | [warn] 39 | [error] 40 | [alert] 41 | [crit] 42 | --- must_die 43 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/000-nyi.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - NYI host function 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: hostcalls 15 | --- config 16 | location /t { 17 | proxy_wasm hostcalls 'test=/t/nyi_host_func'; 18 | echo fail; 19 | } 20 | --- error_code: 500 21 | --- response_body_like: 500 Internal Server Error 22 | --- error_log eval 23 | qr/host trap \(function not yet implemented\): proxy_close_stream/, 24 | --- no_error_log 25 | [crit] 26 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/001-get_vm_configuration.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(5); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - get_vm_configuration() on_vm_start, no config 13 | --- main_config eval 14 | --- wasm_modules: hostcalls 15 | --- config 16 | location /t { 17 | proxy_wasm hostcalls; 18 | return 200; 19 | } 20 | --- ignore_response_body 21 | --- error_log eval 22 | qr/\[info\] .*? no vm config/ 23 | --- no_error_log 24 | [error] 25 | vm config: 26 | cannot parse vm config 27 | 28 | 29 | 30 | === TEST 2: proxy_wasm - get_vm_configuration() on_vm_start, with config 31 | --- valgrind 32 | --- main_config eval 33 | qq{ 34 | wasm { 35 | module hostcalls $ENV{TEST_NGINX_CRATES_DIR}/hostcalls.wasm 'hello=world'; 36 | } 37 | } 38 | --- config 39 | location /t { 40 | proxy_wasm hostcalls; 41 | return 200; 42 | } 43 | --- ignore_response_body 44 | --- error_log eval 45 | qr/\[info\] .*? vm config: hello=world/ 46 | --- no_error_log 47 | [error] 48 | no vm config 49 | cannot parse vm config 50 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/100-proxy_log.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(9); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - proxy_log() logs all levels 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: hostcalls 15 | --- config 16 | location /t { 17 | proxy_wasm hostcalls 'test=/t/log/levels'; 18 | echo ok; 19 | } 20 | --- response_body 21 | ok 22 | --- error_log eval 23 | [ 24 | qr/\[debug\] .*? \*\d+ \[proxy-wasm\]\["hostcalls" #\d+\] proxy_log trace$/, 25 | qr/\[info\] .*? \*\d+ \[proxy-wasm\]\["hostcalls" #\d+\] proxy_log info, client:/, 26 | qr/\[warn\] .*? \*\d+ \[proxy-wasm\]\["hostcalls" #\d+\] proxy_log warn, client:/, 27 | qr/\[error\] .*? \*\d+ \[proxy-wasm\]\["hostcalls" #\d+\] proxy_log error, client:/, 28 | qr/\[crit\] .*? \*\d+ \[proxy-wasm\]\["hostcalls" #\d+\] proxy_log critical, client:/ 29 | ] 30 | --- no_error_log 31 | [alert] 32 | [stub] 33 | 34 | 35 | 36 | === TEST 2: proxy_wasm - proxy_log() bad log level 37 | --- load_nginx_modules: ngx_http_echo_module 38 | --- wasm_modules: hostcalls 39 | --- config 40 | location /t { 41 | proxy_wasm hostcalls 'test=/t/bad_log_level'; 42 | echo fail; 43 | } 44 | --- error_code: 500 45 | --- response_body_like: 500 Internal Server Error 46 | --- error_log eval 47 | [ 48 | qr/\[alert\] .*? NYI - proxy_log bad log_level: 100/, 49 | qr/\[crit\] .*? panicked at/, 50 | qr/unexpected status: 2/, 51 | ] 52 | --- no_error_log 53 | [emerg] 54 | [stub1] 55 | [stub2] 56 | [stub3] 57 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/101-proxy_get_current_time.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - get_current_time() gets current time 13 | should produce a log with the current time (ms as ~ns) 14 | --- wasm_modules: hostcalls 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- config 17 | location /t { 18 | proxy_wasm hostcalls 'test=/t/log/current_time'; 19 | echo ok; 20 | } 21 | --- response_body 22 | ok 23 | --- error_log eval 24 | qr/\[info\] .*? now: SystemTime\(\d+\.\d+s\)/, 25 | --- no_error_log 26 | [error] 27 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/140-proxy_call_foreign_function.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - call_foreign_function() unknown function 13 | --- wasm_modules: hostcalls 14 | --- config 15 | location /t { 16 | proxy_wasm hostcalls 'test=/t/call_foreign_function \ 17 | name=foo'; 18 | } 19 | --- error_code: 500 20 | --- error_log eval 21 | qr/host trap \(internal error\): unknown foreign function/ 22 | --- no_error_log 23 | [crit] 24 | [emerg] 25 | 26 | 27 | 28 | === TEST 2: proxy_wasm - call_foreign_function() known function 29 | --- skip_eval: 4: $::nginxV =~ m/openresty/ 30 | --- wasm_modules: hostcalls 31 | --- config 32 | location /t { 33 | proxy_wasm hostcalls 'test=/t/call_foreign_function \ 34 | name=resolve_lua'; 35 | } 36 | --- error_code: 500 37 | --- error_log eval 38 | qr/host trap \(internal error\): cannot resolve, no lua support/ 39 | --- no_error_log 40 | [crit] 41 | [emerg] 42 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/200-buffers_and_maps_bad_args.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(5); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - set_buffer() bad buffer type 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: hostcalls 15 | --- config 16 | location /t { 17 | proxy_wasm hostcalls 'test=/t/bad_set_buffer_type'; 18 | echo fail; 19 | } 20 | --- error_code: 500 21 | --- response_body_like: 500 Internal Server Error 22 | --- error_log eval 23 | [ 24 | qr/\[alert\] .*? NYI - set_buffer bad buf_type: 100/, 25 | qr/\[crit\] .*? panicked at/, 26 | qr/unexpected status: 2/, 27 | ] 28 | 29 | 30 | 31 | === TEST 2: proxy_wasm - get_buffer() bad buffer type 32 | --- load_nginx_modules: ngx_http_echo_module 33 | --- wasm_modules: hostcalls 34 | --- config 35 | location /t { 36 | proxy_wasm hostcalls 'test=/t/bad_get_buffer_type'; 37 | echo fail; 38 | } 39 | --- error_code: 500 40 | --- response_body_like: 500 Internal Server Error 41 | --- error_log eval 42 | [ 43 | qr/\[alert\] .*? NYI - get_buffer bad buf_type: 100/, 44 | qr/\[crit\] .*? panicked at/, 45 | qr/unexpected status: 2/, 46 | ] 47 | 48 | 49 | 50 | === TEST 3: proxy_wasm - set_map() bad map type 51 | --- load_nginx_modules: ngx_http_echo_module 52 | --- wasm_modules: hostcalls 53 | --- config 54 | location /t { 55 | proxy_wasm hostcalls 'test=/t/bad_set_map_type'; 56 | echo fail; 57 | } 58 | --- error_code: 500 59 | --- response_body_like: 500 Internal Server Error 60 | --- error_log eval 61 | [ 62 | qr/\[alert\] .*? NYI - set_map bad map_type: 100/, 63 | qr/\[crit\] .*? panicked at/, 64 | qr/unexpected status: 2/, 65 | ] 66 | 67 | 68 | 69 | === TEST 4: proxy_wasm - get_map() bad map type 70 | --- load_nginx_modules: ngx_http_echo_module 71 | --- wasm_modules: hostcalls 72 | --- config 73 | location /t { 74 | proxy_wasm hostcalls 'test=/t/bad_get_map_type'; 75 | echo fail; 76 | } 77 | --- error_code: 500 78 | --- response_body_like: 500 Internal Server Error 79 | --- error_log eval 80 | [ 81 | qr/\[alert\] .*? NYI - get_map bad map_type: 100/, 82 | qr/\[crit\] .*? panicked at/, 83 | qr/unexpected status: 2/, 84 | ] 85 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/contexts/131-proxy_get_http_dispatch_response_body.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_hup(); 8 | skip_no_debug(); 9 | 10 | plan_tests(4); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: proxy_wasm contexts - get_http_dispatch_response_body on_tick 16 | --- wasm_modules: context_checks 17 | --- config 18 | location /t { 19 | proxy_wasm context_checks 'on_tick=get_dispatch_response_body_buffer'; 20 | return 200; 21 | } 22 | --- ignore_response_body 23 | --- error_log 24 | [error] 25 | can only get dispatch response body during "on_http_dispatch_response" 26 | --- no_error_log 27 | [crit] 28 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/001-proxy_define_metric.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | our $workers = 2; 8 | 9 | workers($workers); 10 | if ($workers > 1) { 11 | master_on(); 12 | } 13 | 14 | plan_tests(4); 15 | run_tests(); 16 | 17 | __DATA__ 18 | 19 | === TEST 1: proxy_wasm - define_metric() counter 20 | --- valgrind 21 | --- wasm_modules: hostcalls 22 | --- load_nginx_modules: ngx_http_echo_module 23 | --- config 24 | location /t { 25 | proxy_wasm hostcalls 'on_configure=define_metrics \ 26 | metrics=c1'; 27 | echo ok; 28 | } 29 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] defined metric \w+ as \d+/ 30 | --- grep_error_log_out eval 31 | qr/.*? defined metric c1 as \d+/ 32 | --- no_error_log 33 | [error] 34 | [crit] 35 | 36 | 37 | 38 | === TEST 2: proxy_wasm - define_metric() gauge 39 | --- valgrind 40 | --- wasm_modules: hostcalls 41 | --- load_nginx_modules: ngx_http_echo_module 42 | --- config 43 | location /t { 44 | proxy_wasm hostcalls 'on_configure=define_metrics \ 45 | metrics=g1'; 46 | echo ok; 47 | } 48 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] defined metric \w+ as \d+/ 49 | --- grep_error_log_out eval 50 | qr/.*? defined metric g1 as \d+/ 51 | --- no_error_log 52 | [error] 53 | [crit] 54 | 55 | 56 | 57 | === TEST 3: proxy_wasm - define_metric() histogram 58 | --- valgrind 59 | --- wasm_modules: hostcalls 60 | --- load_nginx_modules: ngx_http_echo_module 61 | --- config 62 | location /t { 63 | proxy_wasm hostcalls 'on_configure=define_metrics \ 64 | metrics=h1'; 65 | echo ok; 66 | } 67 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] defined metric \w+ as \d+/ 68 | --- grep_error_log_out eval 69 | qr/.*? defined metric h1 as \d+/ 70 | --- no_error_log 71 | [error] 72 | [crit] 73 | 74 | 75 | 76 | === TEST 4: proxy_wasm - define_metric() redefinition 77 | Definition happens only once, a second call defining an existing metric simply returns its id. 78 | --- skip_no_debug 79 | --- valgrind 80 | --- wasm_modules: hostcalls 81 | --- load_nginx_modules: ngx_http_echo_module 82 | --- config 83 | location /t { 84 | proxy_wasm hostcalls 'on_configure=define_metrics \ 85 | metrics=c1,g1,h1'; 86 | proxy_wasm hostcalls 'on_configure=define_metrics \ 87 | metrics=c1,g1,h1'; 88 | echo ok; 89 | } 90 | --- error_log eval 91 | qr/wasm returning existing metric id "\d+"/ 92 | --- no_error_log 93 | [error] 94 | [crit] 95 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/010-proxy_increment_metric.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_hup(); 8 | 9 | our $workers = 2; 10 | 11 | workers($workers); 12 | master_on(); 13 | 14 | plan_tests(4); 15 | run_tests(); 16 | 17 | __DATA__ 18 | 19 | === TEST 1: proxy_wasm - increment_metric() sanity 20 | A counter's value should reflect increments made by all workers. 21 | 22 | --- valgrind 23 | --- load_nginx_modules: ngx_http_echo_module 24 | --- wasm_modules: hostcalls 25 | --- config 26 | location /t { 27 | proxy_wasm hostcalls 'on_configure=define_and_increment_counters \ 28 | metrics=c1'; 29 | echo ok; 30 | } 31 | --- error_log eval 32 | qr/c1: $::workers at Configure/ 33 | --- no_error_log 34 | [error] 35 | [crit] 36 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/011-proxy_increment_metric_edge_cases.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm - increment_metric() gauge 13 | --- valgrind 14 | --- load_nginx_modules: ngx_http_echo_module 15 | --- wasm_modules: hostcalls 16 | --- config eval 17 | qq{ 18 | location /t { 19 | proxy_wasm hostcalls 'on_configure=define_metrics \ 20 | on=request_headers \ 21 | test=/t/metrics/increment_gauges \ 22 | metrics=g1,g2'; 23 | echo ok; 24 | } 25 | } 26 | --- error_code: 500 27 | --- error_log eval 28 | qr/host trap \(internal error\): could not increment metric id "\d+": metric not a counter/ 29 | --- no_error_log 30 | [crit] 31 | [emerg] 32 | 33 | 34 | 35 | === TEST 2: proxy_wasm - increment_metric() invalid metric id 36 | --- valgrind 37 | --- load_nginx_modules: ngx_http_echo_module 38 | --- wasm_modules: hostcalls 39 | --- config 40 | location /t { 41 | proxy_wasm hostcalls 'on=request_headers \ 42 | test=/t/metrics/increment_invalid_counter'; 43 | echo ok; 44 | } 45 | --- error_code: 500 46 | --- error_log eval 47 | qr/host trap \(internal error\): could not increment metric id "\d+": metric not found/ 48 | --- no_error_log 49 | [crit] 50 | [emerg] 51 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/020-proxy_record_metric.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_hup(); 8 | 9 | workers(2); 10 | master_on(); 11 | 12 | plan_tests(5); 13 | run_tests(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: proxy_wasm - record_metric() gauge 18 | A gauge's value is equal to the last value set by any of the workers. 19 | The first filter, bound to worker 0, sets g1 to 1; the second one, bound to 20 | worker 1, sets g1 to 2. 21 | 22 | --- skip_no_debug 23 | --- wasm_modules: hostcalls 24 | --- load_nginx_modules: ngx_http_echo_module 25 | --- config 26 | location /t { 27 | proxy_wasm hostcalls 'on_configure=define_metrics \ 28 | on_tick=set_gauges \ 29 | tick_period=100 \ 30 | n_sync_calls=1 \ 31 | on_worker=0 \ 32 | value=1 \ 33 | metrics=g1'; 34 | 35 | proxy_wasm hostcalls 'on_configure=define_metrics \ 36 | on_tick=set_gauges \ 37 | tick_period=500 \ 38 | n_sync_calls=1 \ 39 | on_worker=1 \ 40 | value=2 \ 41 | metrics=g1'; 42 | echo ok; 43 | } 44 | --- wait: 1 45 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] record \d+ on g1/ 46 | --- grep_error_log_out eval 47 | qr/.*? record 1 on g1.* 48 | .*? record 2 on g1.*/ 49 | --- no_error_log 50 | [error] 51 | [crit] 52 | [emerg] 53 | 54 | 55 | 56 | === TEST 2: proxy_wasm - record_metric() histogram 57 | Record values to a histogram so that each of its bins has counter equals to 1. 58 | 59 | --- skip_no_debug 60 | --- valgrind 61 | --- load_nginx_modules: ngx_http_echo_module 62 | --- wasm_modules: hostcalls 63 | --- config eval 64 | my $filters; 65 | 66 | foreach my $exp (0 .. 17) { 67 | my $v = 2 ** $exp; 68 | $filters .= " 69 | proxy_wasm hostcalls 'on_configure=define_metrics \ 70 | test=/t/metrics/record_histograms \ 71 | metrics=h1 \ 72 | value=$v';"; 73 | } 74 | 75 | qq{ 76 | location /t { 77 | $filters 78 | echo ok; 79 | } 80 | } 81 | --- error_log eval 82 | [ 83 | "growing histogram", 84 | qr/histogram: 1: 1; 2: 1; 4: 1; 8: 1; 16: 1; 32: 1; 64: 1; 128: 1; 256: 1; 512: 1; 1024: 1; 2048: 1; 4096: 1; 8192: 1; 16384: 1; 32768: 1; 65536: 1; 4294967295: 1; SUM: 262143/ 85 | ] 86 | --- no_error_log 87 | [error] 88 | [crit] 89 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/030-proxy_get_metric.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm metrics - get_metric() counter 13 | --- valgrind 14 | --- load_nginx_modules: ngx_http_echo_module 15 | --- wasm_modules: hostcalls 16 | --- config 17 | location /t { 18 | proxy_wasm hostcalls 'on_configure=define_and_increment_counters \ 19 | metrics=c1 \ 20 | on=request_headers \ 21 | test=/t/log/metrics'; 22 | echo ok; 23 | } 24 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] c1: 1.*/ 25 | --- grep_error_log_out eval 26 | qr/.*? c1: 1 .*/ 27 | --- no_error_log 28 | [crit] 29 | [emerg] 30 | 31 | 32 | 33 | === TEST 2: proxy_wasm metrics - get_metric() gauge 34 | --- valgrind 35 | --- load_nginx_modules: ngx_http_echo_module 36 | --- wasm_modules: hostcalls 37 | --- config 38 | location /t { 39 | proxy_wasm hostcalls 'on_configure=define_and_toggle_gauges \ 40 | metrics=g1 \ 41 | on=request_headers \ 42 | test=/t/log/metrics'; 43 | echo ok; 44 | } 45 | --- grep_error_log eval: qr/\["hostcalls" \#\d\] g1: 1.*/ 46 | --- grep_error_log_out eval 47 | qr/.*? g1: 1 .*/ 48 | --- no_error_log 49 | [crit] 50 | [emerg] 51 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/metrics/031-proxy_get_metric_edge_cases.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm metrics - get_metric() histogram 13 | --- valgrind 14 | --- load_nginx_modules: ngx_http_echo_module 15 | --- wasm_modules: hostcalls 16 | --- config 17 | location /t { 18 | proxy_wasm hostcalls 'on=request_headers \ 19 | test=/t/metrics/get_histogram'; 20 | echo ok; 21 | } 22 | --- error_code: 500 23 | --- error_log eval 24 | qr/host trap \(internal error\): could not retrieve metric id "\d+": metric is a histogram/ 25 | --- no_error_log 26 | [crit] 27 | [emerg] 28 | 29 | 30 | 31 | === TEST 2: proxy_wasm metrics - get_metric() invalid metric id 32 | --- valgrind 33 | --- load_nginx_modules: ngx_http_echo_module 34 | --- wasm_modules: hostcalls 35 | --- config 36 | location /t { 37 | proxy_wasm hostcalls 'on=request_headers \ 38 | test=/t/metrics/get_invalid_metric'; 39 | echo ok; 40 | } 41 | --- error_code: 500 42 | --- error_log eval 43 | qr/host trap \(internal error\): could not retrieve metric id "\d+": metric not found/ 44 | --- no_error_log 45 | [crit] 46 | [emerg] 47 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/shm/003-kv_edge_cases.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | our $kv_size = $min_shm_size; 8 | our $eighth_page_size = $page_size / 8; 9 | 10 | plan_tests(5); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: proxy_wasm key/value shm - 'no memory' errors if no eviction policy is active 16 | --- load_nginx_modules: ngx_http_echo_module 17 | --- wasm_modules: hostcalls 18 | --- shm_kv eval: qq/test $::kv_size eviction=none/ 19 | --- config eval 20 | qq{ 21 | location /t { 22 | # only 4 fit 23 | proxy_wasm hostcalls 'test=/t/shm/set_shared_data_by_len key=test/test1 header_ok=set-1 len=$::eighth_page_size'; 24 | proxy_wasm hostcalls 'test=/t/shm/set_shared_data_by_len key=test/test2 header_ok=set-2 len=$::eighth_page_size'; 25 | proxy_wasm hostcalls 'test=/t/shm/set_shared_data_by_len key=test/test3 header_ok=set-3 len=$::eighth_page_size'; 26 | proxy_wasm hostcalls 'test=/t/shm/set_shared_data_by_len key=test/test4 header_ok=set-4 len=$::eighth_page_size'; 27 | proxy_wasm hostcalls 'test=/t/shm/set_shared_data_by_len key=test/test5 header_ok=set-5 len=$::eighth_page_size'; 28 | 29 | echo ok; 30 | } 31 | } 32 | --- error_code: 500 33 | --- response_body_like: 500 Internal Server Error 34 | --- grep_error_log eval: qr/(\[crit\]|.*?failed setting value to shm).*/ 35 | --- grep_error_log_out eval 36 | qr/\[crit\] .*? \[wasm\] "test" shm store: no memory; cannot allocate pair with key size 10 and value size $::eighth_page_size 37 | (.*?\[error\]|Uncaught RuntimeError|\s+).*?host trap \(internal error\): failed setting value to shm \(could not write to slab\).*/ 38 | --- no_error_log 39 | [emerg] 40 | [alert] 41 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/shm/100-queue_push_pop.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(10); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm queue shm - push and pop a value 13 | --- valgrind 14 | --- load_nginx_modules: ngx_http_echo_module 15 | --- wasm_modules: hostcalls 16 | --- shm_queue: test 1m 17 | --- config 18 | location /t { 19 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 20 | queue=test \ 21 | value=hello'; 22 | proxy_wasm hostcalls 'test=/t/shm/dequeue \ 23 | queue=test'; 24 | echo ok; 25 | } 26 | --- response_headers 27 | status-enqueue: 0 28 | status-dequeue: 0 29 | exists: 1 30 | data: hello 31 | --- response_body 32 | ok 33 | --- no_error_log 34 | [error] 35 | [crit] 36 | [emerg] 37 | wrapping around 38 | 39 | 40 | 41 | === TEST 2: proxy_wasm queue shm - pop from empty queue 42 | --- load_nginx_modules: ngx_http_echo_module 43 | --- wasm_modules: hostcalls 44 | --- shm_queue: test 1m 45 | --- config 46 | location /t { 47 | proxy_wasm hostcalls 'test=/t/shm/dequeue queue=test'; 48 | echo ok; 49 | } 50 | --- response_headers 51 | status-dequeue: 0 52 | exists: 0 53 | data: 54 | --- response_body 55 | ok 56 | --- no_error_log 57 | [error] 58 | [crit] 59 | [emerg] 60 | wrapping around 61 | [stub] 62 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/shm/102-queue_push_edge_case.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | our $four_pages_size = $page_size * 3; 8 | our $reserved_space = ($page_size * 2) + 4; 9 | 10 | plan_tests(6); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: proxy_wasm queue shm - push when data_size == buffer_size 16 | --- skip_no_debug 17 | --- load_nginx_modules: ngx_http_echo_module 18 | --- wasm_modules: hostcalls 19 | --- shm_queue eval: qq/test $::four_pages_size/ 20 | --- config eval 21 | my $buffer_size = $::four_pages_size - $::reserved_space; 22 | qq{ 23 | location /t { 24 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 25 | queue=test \ 26 | length=$buffer_size'; 27 | echo ok; 28 | } 29 | } 30 | --- response_headers 31 | status-enqueue: 0 32 | --- response_body 33 | ok 34 | --- error_log 35 | circular_write: wrapping around 36 | --- no_error_log 37 | [error] 38 | [crit] 39 | 40 | 41 | 42 | === TEST 2: proxy_wasm queue shm - push when data size == buffer_size + 1 43 | --- valgrind 44 | --- load_nginx_modules: ngx_http_echo_module 45 | --- wasm_modules: hostcalls 46 | --- shm_queue eval: qq/test $::four_pages_size/ 47 | --- config eval 48 | my $buffer_size_plus_one = $::four_pages_size - $::reserved_space + 1; 49 | qq{ 50 | location /t { 51 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 52 | queue=test \ 53 | length=$buffer_size_plus_one'; 54 | echo ok; 55 | } 56 | } 57 | --- error_code: 500 58 | --- response_body_like: 500 Internal Server Error 59 | --- grep_error_log eval: qr/.*?could not enqueue.*/ 60 | --- grep_error_log_out eval 61 | qr~(\[error\]|Uncaught RuntimeError|\s+).*?host trap \(internal error\): could not enqueue \(queue is full\).*~ 62 | --- no_error_log 63 | [crit] 64 | [emerg] 65 | circular_write: wrapping around 66 | 67 | 68 | 69 | === TEST 3: proxy_wasm queue shm - push when data size == buffer_size - 1 70 | --- load_nginx_modules: ngx_http_echo_module 71 | --- wasm_modules: hostcalls 72 | --- shm_queue eval: qq/test $::four_pages_size/ 73 | --- config eval 74 | my $buffer_size_minus_one = $::four_pages_size - $::reserved_space - 1; 75 | qq{ 76 | location /t { 77 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 78 | queue=test \ 79 | length=$buffer_size_minus_one'; 80 | echo ok; 81 | } 82 | } 83 | --- response_headers 84 | status-enqueue: 0 85 | --- response_body 86 | ok 87 | --- no_error_log 88 | [error] 89 | [crit] 90 | circular_write: wrapping around 91 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/hfuncs/shm/103-queue_pop_edge_case.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | our $four_pages_size = $page_size * 3; 8 | our $reserved_space = ($page_size * 2) + 4; 9 | 10 | plan_tests(10); 11 | run_tests(); 12 | 13 | __DATA__ 14 | 15 | === TEST 1: proxy_wasm queue shm - pop when data size == buffer_size - 1 16 | --- load_nginx_modules: ngx_http_echo_module 17 | --- wasm_modules: hostcalls 18 | --- shm_queue eval: qq/test $::four_pages_size/ 19 | --- config eval 20 | my $buffer_size_minus_one = $::four_pages_size - $::reserved_space - 1; 21 | qq{ 22 | location /t { 23 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 24 | queue=test \ 25 | length=$buffer_size_minus_one'; 26 | proxy_wasm hostcalls 'test=/t/shm/dequeue \ 27 | queue=test'; 28 | echo ok; 29 | } 30 | } 31 | --- response_headers 32 | status-enqueue: 0 33 | status-dequeue: 0 34 | exists: 1 35 | --- response_body 36 | ok 37 | --- no_error_log 38 | [error] 39 | [crit] 40 | circular_read: wrapping around 41 | circular_write: wrapping around 42 | [stub] 43 | 44 | 45 | 46 | === TEST 2: proxy_wasm queue shm - pop when data size == buffer_size 47 | --- skip_no_debug 48 | --- load_nginx_modules: ngx_http_echo_module 49 | --- wasm_modules: hostcalls 50 | --- shm_queue eval: qq/test $::four_pages_size/ 51 | --- config eval 52 | my $buffer_size = $::four_pages_size - $::reserved_space; 53 | qq{ 54 | location /t { 55 | proxy_wasm hostcalls 'test=/t/shm/enqueue \ 56 | queue=test \ 57 | length=$buffer_size'; 58 | proxy_wasm hostcalls 'test=/t/shm/dequeue \ 59 | queue=test'; 60 | echo ok; 61 | } 62 | } 63 | --- response_headers 64 | status-enqueue: 0 65 | status-dequeue: 0 66 | exists: 1 67 | --- response_body 68 | ok 69 | --- error_log 70 | circular_read: wrapping around 71 | circular_write: wrapping around 72 | --- no_error_log 73 | [error] 74 | [crit] 75 | [emerg] 76 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/001-rust_sdk.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: proxy_wasm Rust SDK - 0.1 sanity 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: rust_sdk_ver_zero_one 15 | --- config 16 | location /t { 17 | proxy_wasm rust_sdk_ver_zero_one; 18 | echo ok; 19 | } 20 | --- response_body 21 | ok 22 | --- no_error_log 23 | [error] 24 | [crit] 25 | 26 | 27 | 28 | === TEST 2: proxy_wasm Rust SDK - 0.1 HTTP dispatch 29 | --- load_nginx_modules: ngx_http_echo_module 30 | --- wasm_modules: rust_sdk_ver_zero_one 31 | --- config 32 | location /dispatched { 33 | return 200 "Hello world"; 34 | } 35 | 36 | location /t { 37 | proxy_wasm rust_sdk_ver_zero_one 'test=dispatch \ 38 | host=127.0.0.1:$TEST_NGINX_SERVER_PORT \ 39 | path=/dispatched 40 | on_http_call_response=echo_response_body'; 41 | echo fail; 42 | } 43 | --- response_body 44 | Hello world 45 | --- no_error_log 46 | [error] 47 | [crit] 48 | 49 | 50 | 51 | === TEST 3: proxy_wasm Rust SDK - 0.1 proxy_get_header_map_value() 52 | --- load_nginx_modules: ngx_http_echo_module 53 | --- wasm_modules: rust_sdk_ver_zero_one 54 | --- config 55 | location /t { 56 | proxy_wasm rust_sdk_ver_zero_one 'test=proxy_get_header_map_value'; 57 | echo ok; 58 | } 59 | --- response_body 60 | close 61 | --- no_error_log 62 | [error] 63 | [crit] 64 | 65 | 66 | 67 | === TEST 4: proxy_wasm Rust SDK - 0.1 proxy_get_empty_map_value() 68 | --- load_nginx_modules: ngx_http_echo_module 69 | --- wasm_modules: rust_sdk_ver_zero_one 70 | --- config 71 | location /t { 72 | proxy_wasm rust_sdk_ver_zero_one 'test=proxy_get_empty_map_value'; 73 | echo ok; 74 | } 75 | --- response_body 76 | --- no_error_log 77 | [error] 78 | [crit] 79 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/001-helloworld.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(6); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - helloworld example 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- wasm_modules: go_helloworld 17 | --- config 18 | location /t { 19 | proxy_wasm go_helloworld; 20 | echo_sleep 1.1; 21 | echo ok; 22 | } 23 | --- response_body 24 | ok 25 | --- error_log eval 26 | [ 27 | qr/\[info\] .*? OnPluginStart from Go!/, 28 | qr/\[info\] .*? It's [0-9]+: random value: [0-9]+/, 29 | ] 30 | --- no_error_log 31 | [error] 32 | [crit] 33 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/002-http_headers.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(6); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - http_headers example 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- wasm_modules: go_http_headers 17 | --- config 18 | location /t { 19 | proxy_wasm go_http_headers; 20 | echo ok; 21 | } 22 | --- response_body 23 | ok 24 | --- error_log eval 25 | [ 26 | qr/\[info\] .*? request header --> test: best/, 27 | qr/\[info\] .*? response header <-- Server: (nginx|openresty)/, 28 | ] 29 | --- no_error_log 30 | [error] 31 | [crit] 32 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/003-postpone_requests.t.off: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasm; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(6); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - postpone_requests example 15 | --- SKIP: fails getting stuck, request is never resumed 16 | --- load_nginx_modules: ngx_http_echo_module 17 | --- wasm_modules: go_postpone_requests 18 | --- config 19 | location /t { 20 | proxy_wasm go_postpone_requests; 21 | echo_sleep 1.1; 22 | echo ok; 23 | } 24 | --- response_body 25 | ok 26 | --- error_log eval 27 | [ 28 | qr/\[info\] .*? postpone request with contextID=/, 29 | qr/\[info\] .*? resume request with contextID=/, 30 | ] 31 | --- no_error_log 32 | [error] 33 | [crit] 34 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/004-foreign_call_on_tick.t.off: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasm; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(6); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - foreign_call_on_tick example 15 | --- SKIP: NYI proxy_call_foreign_function 16 | --- load_nginx_modules: ngx_http_echo_module 17 | --- wasm_modules: go_foreign_call_on_tick 18 | --- config 19 | location /t { 20 | proxy_wasm go_foreign_call_on_tick; 21 | echo_sleep 1.1; 22 | echo ok; 23 | } 24 | --- response_body 25 | ok 26 | --- error_log eval 27 | [ 28 | qr/\[info\] .*? foreign function (compress) called: [0-9]+/, 29 | ] 30 | --- no_error_log 31 | [error] 32 | [crit] 33 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/005-dispatch_call_on_tick.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - dispatch_call_on_tick example (resolver error) 15 | Missing IP for "web_service" host requested by the filter. 16 | --- wasm_modules: go_dispatch_call_on_tick 17 | --- config 18 | location /private { 19 | internal; 20 | # the filter does not support HTTP contexts 21 | proxy_wasm go_dispatch_call_on_tick; 22 | } 23 | 24 | location /t { 25 | return 200; 26 | } 27 | --- wait: 1 28 | --- ignore_response_body 29 | --- error_log eval 30 | qr/\[error\] .*? dispatch failed: tcp socket - resolver error: Host not found/ 31 | --- no_error_log 32 | [crit] 33 | [emerg] 34 | [alert] 35 | 36 | 37 | 38 | === TEST 2: proxy_wasm Go SDK - dispatch_call_on_tick example 39 | Connection refused on 127.0.0.1:81 requested by filter. 40 | --- wasm_modules: go_dispatch_call_on_tick 41 | --- config 42 | resolver_add 127.0.0.1 web_service; 43 | 44 | location /private { 45 | internal; 46 | # the filter does not support HTTP contexts 47 | proxy_wasm go_dispatch_call_on_tick; 48 | } 49 | 50 | location /t { 51 | return 200; 52 | } 53 | --- wait: 1 54 | --- ignore_response_body 55 | --- error_log eval 56 | qr/\[error\] .*? dispatch failed: tcp socket - Connection refused/ 57 | --- no_error_log 58 | [crit] 59 | [emerg] 60 | [alert] 61 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/006-http_auth_random.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | our $ExtResolver = $t::TestWasmX::extresolver; 8 | our $ExtTimeout = $t::TestWasmX::exttimeout; 9 | 10 | skip_no_go_sdk(); 11 | 12 | plan_tests(6); 13 | run_tests(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: proxy_wasm Go SDK - http_auth_random example 18 | --- skip_eval: 6: defined $ENV{TEST_NGINX_RANDOMIZE} && $ENV{TEST_NGINX_RANDOMIZE} 19 | --- timeout eval: $::ExtTimeout 20 | --- load_nginx_modules: ngx_http_echo_module 21 | --- main_config eval 22 | qq{ 23 | wasm { 24 | module go_http_auth_random $ENV{TEST_NGINX_CRATES_DIR}/go_http_auth_random.wasm; 25 | } 26 | } 27 | --- http_config 28 | server { 29 | listen 2000; 30 | server_name httpbin; 31 | 32 | location /uuid { 33 | # Generating a uuid seems excessive; $request_id has some 34 | # randomness on a distribution of runs of this test. 35 | echo $request_id; 36 | } 37 | } 38 | --- config eval 39 | qq{ 40 | resolver $::ExtResolver; 41 | resolver_add 127.0.0.1 httpbin; 42 | 43 | location /uuid { 44 | proxy_wasm go_http_auth_random; 45 | echo ok; 46 | } 47 | } 48 | --- request 49 | GET /uuid 50 | --- error_code_like: ^(200|403)$ 51 | --- more_headers 52 | key: value 53 | --- error_log eval 54 | [ 55 | qr/\[info\] .*? request header: key: value/, 56 | qr/\[info\] .*? access (granted|forbidden)/, 57 | qr/\[info\] .*? response header from httpbin/, 58 | ] 59 | --- no_error_log 60 | [error] 61 | [crit] 62 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/009-http_routing.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - http_routing example (configuration A) 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- wasm_modules: go_http_routing 17 | --- config 18 | location /t { 19 | proxy_wasm go_http_routing 'A'; 20 | echo ok; 21 | } 22 | --- more_headers 23 | content-type: text/html 24 | --- request 25 | POST /t 26 | 27 | { "my_key": "my_value" } 28 | --- response_body 29 | ok 30 | --- error_log eval 31 | qr/\[info\] .*? successfully loaded "go_http_routing"/ 32 | --- no_error_log 33 | [error] 34 | [crit] 35 | 36 | 37 | 38 | === TEST 2: proxy_wasm Go SDK - http_routing example (configuration B) 39 | --- SKIP: fails with 'cannot set read-only ":authority" header' 40 | --- wasm_modules: go_http_routing 41 | --- load_nginx_modules: ngx_http_echo_module 42 | --- config 43 | location /t { 44 | proxy_wasm go_http_routing 'B'; 45 | echo ok; 46 | } 47 | --- more_headers 48 | content-type: text/html 49 | --- request 50 | POST /t 51 | 52 | { "my_key": "my_value" } 53 | --- response_body 54 | ok 55 | --- error_log eval 56 | qr/\[info\] .*? successfully loaded "go_http_routing"/ 57 | --- no_error_log 58 | [error] 59 | [crit] 60 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/010-shared_data.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - shared_data example 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- wasm_modules: go_shared_data 17 | --- shm_kv: * 64k 18 | --- config 19 | location /subrequest { 20 | internal; 21 | proxy_wasm go_shared_data; 22 | echo ok; 23 | } 24 | 25 | location /t { 26 | echo_subrequest GET '/subrequest'; 27 | echo_subrequest GET '/subrequest'; 28 | echo_subrequest GET '/subrequest'; 29 | } 30 | --- response_body 31 | ok 32 | ok 33 | ok 34 | --- error_log eval 35 | [ 36 | qr/\[info\] .*? shared value: 10000001/, 37 | qr/\[info\] .*? shared value: 10000002/, 38 | qr/\[info\] .*? shared value: 10000003/, 39 | ] 40 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/011-shared_queue.t.off: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasm; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - shared_queue_sender example 15 | This test entry is a stub, it does not implement a proper test case for this filter 16 | --- SKIP: trap in proxy_on_configure 17 | --- load_nginx_modules: ngx_http_echo_module 18 | --- wasm_modules: go_shared_queue_sender 19 | --- config 20 | location /t { 21 | proxy_wasm go_shared_queue_sender; 22 | echo ok; 23 | } 24 | --- more_headers 25 | content-type: text/html 26 | --- request 27 | POST /t 28 | 29 | { "my_key": "my_value" } 30 | --- response_body 31 | ok 32 | --- error_log eval 33 | qr/\[info\] .*? successfully loaded "go_shared_queue_sender"/ 34 | --- no_error_log 35 | [error] 36 | [crit] 37 | 38 | 39 | 40 | === TEST 2: proxy_wasm Go SDK - shared_queue_receiver example 41 | This test entry is a stub, it does not implement a proper test case for this filter 42 | --- SKIP: trap in proxy_on_configure 43 | --- wasm_modules: go_shared_queue_receiver 44 | --- load_nginx_modules: ngx_http_echo_module 45 | --- config 46 | location /t { 47 | proxy_wasm go_shared_queue_receiver; 48 | echo ok; 49 | } 50 | --- more_headers 51 | content-type: text/html 52 | --- request 53 | POST /t 54 | 55 | { "my_key": "my_value" } 56 | --- response_body 57 | ok 58 | --- error_log eval 59 | qr/\[info\] .*? successfully loaded "go_shared_queue_receiver"/ 60 | --- no_error_log 61 | [error] 62 | [crit] 63 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/012-metrics.t.off: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasm; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - metrics example 15 | --- SKIP: NYI proxy_define_metric 16 | --- load_nginx_modules: ngx_http_echo_module 17 | --- wasm_modules: go_metrics 18 | --- config 19 | location /subrequest { 20 | internal; 21 | proxy_wasm go_metrics; 22 | echo ok; 23 | } 24 | 25 | location /t { 26 | echo_subrequest GET '/subrequest'; 27 | echo_subrequest GET '/subrequest'; 28 | echo_subrequest GET '/subrequest'; 29 | } 30 | --- more_headers 31 | my-custom-header: value 32 | --- response_body 33 | ok 34 | ok 35 | ok 36 | --- error_log eval 37 | qr/\[info\] .*? successfully loaded "go_metrics"/ 38 | --- no_error_log 39 | [error] 40 | [crit] 41 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/013-vm_plugin_configuration.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(5); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - vm_plugin_configuration example 15 | --- load_nginx_modules: ngx_http_echo_module 16 | --- main_config eval 17 | qq{ 18 | wasm { 19 | module go_vm_plugin_configuration $ENV{TEST_NGINX_CRATES_DIR}/go_vm_plugin_configuration.wasm 'hello=world'; 20 | } 21 | 22 | timer_resolution 10ms; 23 | } 24 | --- config 25 | location /tick { 26 | internal; 27 | proxy_wasm go_vm_plugin_configuration 'default config'; 28 | } 29 | 30 | location /t { 31 | echo_sleep 0.1; 32 | echo_status 200; 33 | } 34 | --- ignore_response_body 35 | --- error_log eval 36 | [ 37 | qr/\[info\] .*? successfully loaded "go_vm_plugin_configuration"/, 38 | qr/\[info\] .*? vm config: hello=world/, 39 | qr/\[info\] .*? plugin config: default config/, 40 | ] 41 | --- no_error_log 42 | [error] 43 | -------------------------------------------------------------------------------- /t/03-proxy_wasm/sdks/002-go_sdk/014-multiple_dispatches.t.off: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasm; 6 | 7 | skip_no_go_sdk(); 8 | 9 | plan_tests(7); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: proxy_wasm Go SDK - multiple_dispatches example 15 | --- SKIP: "no :authority" error (filter passes an empty string as ":authority") 16 | --- wasm_modules: go_multiple_dispatches 17 | --- load_nginx_modules: ngx_http_echo_module 18 | --- config 19 | location /subrequest { 20 | internal; 21 | proxy_wasm go_multiple_dispatches; 22 | echo ok; 23 | } 24 | 25 | location /t { 26 | echo_subrequest GET '/subrequest'; 27 | echo_subrequest GET '/subrequest'; 28 | echo_subrequest GET '/subrequest'; 29 | } 30 | --- more_headers 31 | my-custom-header: value 32 | --- response_body 33 | ok 34 | ok 35 | ok 36 | --- error_log eval 37 | qr/\[info\] .*? successfully loaded "go_multiple_dispatches"/ 38 | --- no_error_log 39 | [error] 40 | [crit] 41 | -------------------------------------------------------------------------------- /t/04-openresty/001-sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: OpenResty sanity 15 | --- config 16 | location /t { 17 | content_by_lua_block { 18 | ngx.exit(403) 19 | } 20 | } 21 | --- error_code: 403 22 | --- response_body_like: 403 Forbidden 23 | --- no_error_log 24 | [error] 25 | [crit] 26 | 27 | 28 | 29 | === TEST 2: ngx_wasmx_module sanity 30 | --- valgrind 31 | --- main_config 32 | wasm {} 33 | --- config 34 | location /t { 35 | content_by_lua_block { 36 | ngx.exit(403) 37 | } 38 | } 39 | --- error_code: 403 40 | --- response_body_like: 403 Forbidden 41 | --- error_log 42 | [wasm] "main" wasm VM initialized 43 | --- no_error_log 44 | [error] 45 | -------------------------------------------------------------------------------- /t/04-openresty/002-dynamic_module.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | our $dyn = $ENV{NGX_BUILD_DYNAMIC_MODULE} || 0; 8 | 9 | skip_no_openresty(); 10 | 11 | plan_tests(4); 12 | run_tests(); 13 | 14 | __DATA__ 15 | 16 | === TEST 1: OpenResty + dyn ngx_wasmx_module - Swap necessary modules when loaded in OpenResty 17 | See notes in ngx_wasm_core_module.c 18 | --- skip_eval: 4: $::dyn != 1 19 | --- load_nginx_modules: ngx_http_headers_more_filter_module 20 | --- wasm_modules: on_phases 21 | --- ignore_response_body 22 | --- grep_error_log eval: qr/\[notice\] .*? swapping modules.*/ 23 | --- grep_error_log_out eval 24 | qr/\[notice\] .*? swapping modules: "ngx_http_headers_more_filter_module" .*? and "ngx_http_wasm_filter_module".* 25 | \[notice\] .*? swapping modules: "ngx_http_lua_module" .*? and "ngx_wasm_core_module"/ 26 | --- no_error_log 27 | [error] 28 | [crit] 29 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/001-get_main_vm.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: get_main_vm() - no VM 15 | --- config 16 | location /t { 17 | content_by_lua_block { 18 | local wasmx = require "resty.wasmx" 19 | local vm = wasmx.get_main_vm() 20 | 21 | ngx.say("vm: ", tostring(vm)) 22 | } 23 | } 24 | --- response_body 25 | vm: cdata: NULL 26 | --- no_error_log 27 | [error] 28 | [crit] 29 | 30 | 31 | 32 | === TEST 2: get_main_vm() - main VM 33 | --- main_config 34 | wasm {} 35 | --- config 36 | location /t { 37 | content_by_lua_block { 38 | local wasmx = require "resty.wasmx" 39 | local vm = wasmx.get_main_vm() 40 | 41 | ngx.say("vm: ", tostring(vm)) 42 | } 43 | } 44 | --- response_body eval 45 | qr/vm: cdata: 0x[0-9a-f]+/ 46 | --- no_error_log 47 | [error] 48 | [crit] 49 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/021-metrics_increment.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: shm_metrics - increment() sanity 15 | --- valgrind 16 | --- metrics: 16k 17 | --- config 18 | location /t { 19 | access_by_lua_block { 20 | local shm = require "resty.wasmx.shm" 21 | local pretty = require "pl.pretty" 22 | 23 | local c1 = shm.metrics:define("c1", shm.metrics.COUNTER) 24 | 25 | shm.metrics:increment(c1) -- value defaults to 1 26 | shm.metrics:increment(c1, 10) 27 | 28 | ngx.say("c1: ", pretty.write(shm.metrics:get(c1), "")) 29 | } 30 | } 31 | --- response_body 32 | c1: {type="counter",value=11} 33 | --- no_error_log 34 | [error] 35 | [crit] 36 | 37 | 38 | 39 | === TEST 2: shm_metrics - increment() metric not found 40 | --- metrics: 16k 41 | --- config 42 | location /t { 43 | access_by_lua_block { 44 | local shm = require "resty.wasmx.shm" 45 | 46 | local ok, err = shm.metrics:increment(1, 10) 47 | ngx.say("ok: ", ok) 48 | ngx.say("err: ", err) 49 | } 50 | } 51 | --- response_body 52 | ok: nil 53 | err: metric not found 54 | --- no_error_log 55 | [error] 56 | [crit] 57 | 58 | 59 | 60 | === TEST 3: shm_metrics - increment() bad args 61 | --- metrics: 16k 62 | --- config 63 | location /t { 64 | access_by_lua_block { 65 | local shm = require "resty.wasmx.shm" 66 | 67 | local _, perr = pcall(shm.metrics.increment, {}, false) 68 | ngx.say(perr) 69 | 70 | _, perr = pcall(shm.metrics.increment, {}, 1, false) 71 | ngx.say(perr) 72 | 73 | _, perr = pcall(shm.metrics.increment, {}, 1, 0) 74 | ngx.say(perr) 75 | } 76 | } 77 | --- response_body 78 | metric_id must be a number 79 | value must be > 0 80 | value must be > 0 81 | --- no_error_log 82 | [error] 83 | [crit] 84 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/022-metrics_record.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: shm_metrics - record() sanity 15 | --- valgrind 16 | --- metrics: 16k 17 | --- config 18 | location /t { 19 | access_by_lua_block { 20 | local shm = require "resty.wasmx.shm" 21 | local pretty = require "pl.pretty" 22 | 23 | local g1 = shm.metrics:define("g1", shm.metrics.GAUGE) 24 | local h1 = shm.metrics:define("h1", shm.metrics.HISTOGRAM) 25 | 26 | local bins = { 1, 3, 5 } 27 | local ch1 = shm.metrics:define("ch1", shm.metrics.HISTOGRAM, { bins = bins }) 28 | 29 | assert(shm.metrics:record(g1, 10)) 30 | assert(shm.metrics:record(h1, 100)) 31 | 32 | for i in ipairs({ 1, 2, 3, 4, 5, 6 }) do 33 | assert(shm.metrics:record(ch1, i)) 34 | end 35 | 36 | ngx.say("g1: ", pretty.write(shm.metrics:get(g1), "")) 37 | ngx.say("h1: ", pretty.write(shm.metrics:get(h1), "")) 38 | ngx.say("ch1: ", pretty.write(shm.metrics:get(ch1), "")) 39 | } 40 | } 41 | --- response_body 42 | g1: {type="gauge",value=10} 43 | h1: {sum=100,type="histogram",value={{count=1,ub=128},{count=0,ub=4294967295}}} 44 | ch1: {sum=21,type="histogram",value={{count=1,ub=1},{count=2,ub=3},{count=2,ub=5},{count=1,ub=4294967295}}} 45 | --- no_error_log 46 | [error] 47 | [crit] 48 | 49 | 50 | 51 | === TEST 2: shm_metrics - record() metric not found 52 | --- metrics: 16k 53 | --- config 54 | location /t { 55 | access_by_lua_block { 56 | local shm = require "resty.wasmx.shm" 57 | 58 | local ok, err = shm.metrics:record(1, 10) 59 | ngx.say("ok: ", ok) 60 | ngx.say("err: ", err) 61 | } 62 | } 63 | --- response_body 64 | ok: nil 65 | err: metric not found 66 | --- no_error_log 67 | [error] 68 | [crit] 69 | 70 | 71 | 72 | === TEST 3: shm_metrics - record() bad args 73 | --- metrics: 16k 74 | --- config 75 | location /t { 76 | access_by_lua_block { 77 | local shm = require "resty.wasmx.shm" 78 | 79 | local _, perr = pcall(shm.metrics.record, {}, false) 80 | ngx.say(perr) 81 | 82 | _, perr = pcall(shm.metrics.record, {}, 1, false) 83 | ngx.say(perr) 84 | } 85 | } 86 | --- response_body 87 | metric_id must be a number 88 | value must be a number 89 | --- no_error_log 90 | [error] 91 | [crit] 92 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/023-metrics_record_custom_histogram.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | master_on(); 10 | workers(2); 11 | 12 | plan_tests(4); 13 | run_tests(); 14 | 15 | __DATA__ 16 | 17 | === TEST 1: shm_metrics - record() custom histogram, multiple workers 18 | Metric creation and update by multiple workers is covered in Proxy-Wasm tests; 19 | custom histogram creation and update by multiple workers is covered here 20 | because custom histograms cannot be created from Proxy-Wasm filters yet. 21 | 22 | --- valgrind 23 | --- metrics: 16k 24 | --- http_config 25 | init_worker_by_lua_block { 26 | local shm = require "resty.wasmx.shm" 27 | 28 | local bins = { 1, 3, 5 } 29 | ch1 = shm.metrics:define("ch1", shm.metrics.HISTOGRAM, { bins = bins }) 30 | 31 | for i in ipairs({ 1, 2, 3, 4, 5, 6 }) do 32 | assert(shm.metrics:record(ch1, i)) 33 | end 34 | } 35 | --- config 36 | location /t { 37 | access_by_lua_block { 38 | local shm = require "resty.wasmx.shm" 39 | local pretty = require "pl.pretty" 40 | 41 | ngx.say("ch1: ", pretty.write(shm.metrics:get(ch1), "")) 42 | } 43 | } 44 | --- response_body 45 | ch1: {sum=42,type="histogram",value={{count=2,ub=1},{count=4,ub=3},{count=4,ub=5},{count=2,ub=4294967295}}} 46 | --- no_error_log 47 | [error] 48 | [crit] 49 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/024-metrics_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: shm_metrics - get() sanity 15 | --- valgrind 16 | --- metrics: 16k 17 | --- config 18 | location /t { 19 | access_by_lua_block { 20 | local shm = require "resty.wasmx.shm" 21 | local pretty = require "pl.pretty" 22 | 23 | local bins = { 1, 3, 5 } 24 | 25 | local c1 = shm.metrics:define("c1", shm.metrics.COUNTER) 26 | local g1 = shm.metrics:define("g1", shm.metrics.GAUGE) 27 | local h1 = shm.metrics:define("h1", shm.metrics.HISTOGRAM) 28 | local ch1 = shm.metrics:define("ch1", shm.metrics.HISTOGRAM, { bins = bins }) 29 | 30 | shm.metrics:increment(c1) 31 | shm.metrics:record(g1, 10) 32 | shm.metrics:record(h1, 100) 33 | shm.metrics:record(ch1, 2) 34 | 35 | ngx.say("c1: ", pretty.write(shm.metrics:get(c1), "")) 36 | ngx.say("g1: ", pretty.write(shm.metrics:get(g1), "")) 37 | ngx.say("h1: ", pretty.write(shm.metrics:get(h1), "")) 38 | ngx.say("ch1: ", pretty.write(shm.metrics:get(ch1), "")) 39 | } 40 | } 41 | --- response_body 42 | c1: {type="counter",value=1} 43 | g1: {type="gauge",value=10} 44 | h1: {sum=100,type="histogram",value={{count=1,ub=128},{count=0,ub=4294967295}}} 45 | ch1: {sum=2,type="histogram",value={{count=0,ub=1},{count=1,ub=3},{count=0,ub=5},{count=0,ub=4294967295}}} 46 | --- no_error_log 47 | [error] 48 | [crit] 49 | 50 | 51 | 52 | === TEST 2: shm_metrics - get() metric not found 53 | --- metrics: 16k 54 | --- config 55 | location /t { 56 | access_by_lua_block { 57 | local shm = require "resty.wasmx.shm" 58 | 59 | local m = shm.metrics:get(99) 60 | assert(m == nil) 61 | 62 | ngx.say("ok") 63 | } 64 | } 65 | --- response_body 66 | ok 67 | --- no_error_log 68 | [error] 69 | [crit] 70 | 71 | 72 | 73 | === TEST 3: shm_metrics - get() bad args 74 | --- metrics: 16k 75 | --- config 76 | location /t { 77 | access_by_lua_block { 78 | local shm = require "resty.wasmx.shm" 79 | 80 | local _, perr = pcall(shm.metrics.get, {}, false) 81 | ngx.say(perr) 82 | } 83 | } 84 | --- response_body 85 | metric_id must be a number 86 | --- no_error_log 87 | [error] 88 | [crit] 89 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/026-metrics_iterate_keys.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: shm_metrics - iterate_keys() sanity 15 | --- metrics: 16k 16 | --- config 17 | location /t { 18 | access_by_lua_block { 19 | local shm = require "resty.wasmx.shm" 20 | 21 | local c1 = shm.metrics:define("c1", shm.metrics.COUNTER) 22 | local g1 = shm.metrics:define("g1", shm.metrics.GAUGE) 23 | local h1 = shm.metrics:define("h1", shm.metrics.HISTOGRAM) 24 | 25 | shm.metrics:lock() 26 | 27 | for key in shm.metrics:iterate_keys() do 28 | ngx.say(key) 29 | end 30 | 31 | shm.metrics:unlock() 32 | } 33 | } 34 | --- response_body 35 | lua:c1 36 | lua:g1 37 | lua:h1 38 | --- no_error_log 39 | [error] 40 | [crit] 41 | -------------------------------------------------------------------------------- /t/04-openresty/ffi/shm/027-metrics_get_keys.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX::Lua; 6 | 7 | skip_no_openresty(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: shm_metrics - get_keys() sanity 15 | --- metrics: 16k 16 | --- config 17 | location /t { 18 | access_by_lua_block { 19 | local shm = require "resty.wasmx.shm" 20 | 21 | local c1 = shm.metrics:define("c1", shm.metrics.COUNTER) 22 | local g1 = shm.metrics:define("g1", shm.metrics.GAUGE) 23 | local h1 = shm.metrics:define("h1", shm.metrics.HISTOGRAM) 24 | 25 | local keys = assert(shm.metrics:get_keys()) 26 | 27 | for _, key in ipairs(keys) do 28 | ngx.say(key) 29 | end 30 | } 31 | } 32 | --- response_body 33 | lua:c1 34 | lua:g1 35 | lua:h1 36 | --- no_error_log 37 | [error] 38 | [crit] 39 | -------------------------------------------------------------------------------- /t/05-wasi/001-sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | our $nginxV = $t::TestWasmX::nginxV; 10 | 11 | plan_tests(4); 12 | run_tests(); 13 | 14 | __DATA__ 15 | 16 | === TEST 1: load a WASI function from the VM, not the host 17 | --- skip_eval: 4: $::nginxV =~ m/v8/ 18 | --- wasm_modules: wasi_vm_tests 19 | --- config 20 | location /t { 21 | wasm_call rewrite wasi_vm_tests test_wasi_non_host; 22 | } 23 | --- response_body 24 | test passed 25 | --- no_error_log 26 | [error] 27 | [crit] 28 | 29 | 30 | 31 | === TEST 2: V8 does not provide any non-host WASI functions 32 | 'daemon off' must be set to check exit_code is 2 33 | Valgrind mode already writes 'daemon off' 34 | HUP mode does not catch the worker exit_code 35 | --- skip_eval: 4: $::nginxV !~ m/v8/ || $ENV{TEST_NGINX_USE_HUP} == 1 36 | --- wasm_modules: wasi_vm_tests 37 | --- main_config eval 38 | $ENV{TEST_NGINX_USE_VALGRIND} ? '' : 'daemon off;' 39 | --- config 40 | location /t { 41 | wasm_call rewrite wasi_vm_tests test_wasi_non_host; 42 | } 43 | --- error_log eval 44 | qr/\[emerg\] .*? failed linking "wasi_vm_tests"/ 45 | --- no_error_log 46 | [crit] 47 | [stub] 48 | --- must_die: 2 49 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/args_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: args_get stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_args_get; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/args_sizes_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: args_sizes_get stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_args_sizes_get; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/clock_time_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: clock_time_get via std::time::SystemTime 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_clock_time_get_via_systemtime; 19 | } 20 | --- error_code: 200 21 | --- response_body eval 22 | qr/seconds since Unix epoch: [1-9][0-9]{9}\n/ 23 | --- no_error_log 24 | [error] 25 | 26 | 27 | 28 | === TEST 2: clock_time_get via std::time::Instant 29 | --- wasm_modules: wasi_host_tests 30 | --- config 31 | location /t { 32 | wasm_call rewrite wasi_host_tests test_wasi_clock_time_get_via_instant; 33 | } 34 | --- response_body 35 | test passed 36 | --- no_error_log 37 | [error] 38 | 39 | 40 | 41 | === TEST 3: clock_time_get 42 | --- wasm_modules: wasi_host_tests 43 | --- config 44 | location /t { 45 | wasm_call rewrite wasi_host_tests test_wasi_clock_time_get; 46 | } 47 | --- response_body eval 48 | qr/test passed with timestamp: [0-9]+\n/ 49 | --- no_error_log 50 | [error] 51 | 52 | 53 | 54 | === TEST 4: clock_time_get using an unsupported clock 55 | --- wasm_modules: wasi_host_tests 56 | --- config 57 | location /t { 58 | wasm_call rewrite wasi_host_tests test_wasi_clock_time_get_unsupported; 59 | } 60 | --- response_body 61 | test passed 62 | --- no_error_log 63 | [error] 64 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/environ_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: environ_get 15 | --- main_config eval 16 | qq{ 17 | env FOO=bar; 18 | env NGX_WASI_ENV=1; 19 | 20 | wasm { 21 | module wasi_host_tests $t::TestWasmX::crates/wasi_host_tests.wasm; 22 | } 23 | } 24 | --- config 25 | location /t { 26 | wasm_call rewrite wasi_host_tests test_wasi_environ_get; 27 | } 28 | --- response_body_like 29 | FOO=bar 30 | NGX_WASI_ENV=1.* 31 | 32 | .*?FOO=bar\0NGX_WASI_ENV=1.* 33 | --- no_error_log 34 | [error] 35 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/environ_sizes_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: environ_sizes_get 15 | --- main_config eval 16 | qq{ 17 | env FOO=bar; 18 | env NGX_WASI_ENV=1; 19 | 20 | wasm { 21 | module wasi_host_tests $t::TestWasmX::crates/wasi_host_tests.wasm; 22 | } 23 | } 24 | --- config 25 | location /t { 26 | wasm_call rewrite wasi_host_tests test_wasi_environ_sizes_get; 27 | } 28 | --- response_body_like 29 | envs: [1-9]\d*, size: [1-9]\d* 30 | --- no_error_log 31 | [error] 32 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_close.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_close stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_close; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_fdstat_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_fdstat_get stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_fdstat_get; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_fdstat_set_flags.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_fdstat_set_flags stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_fdstat_set_flags; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_prestat_dir_name.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_prestat_dir_name stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_prestat_dir_name; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_prestat_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_prestat_get stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_prestat_get; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_read.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_read stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_read; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_seek.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_seek stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_seek; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/fd_write.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_write stdout 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_fd_write_stdout; 19 | } 20 | --- response_body 21 | test passed, wrote 15 bytes 22 | --- error_log eval 23 | qr/\[info\] .*? hello, fd_write/ 24 | 25 | 26 | 27 | === TEST 2: fd_write stderr 28 | --- wasm_modules: wasi_host_tests 29 | --- config 30 | location /t { 31 | wasm_call rewrite wasi_host_tests test_wasi_fd_write_stderr; 32 | } 33 | --- response_body 34 | test passed, wrote 15 bytes 35 | --- error_log eval 36 | qr/\[error\] .*? hello, fd_write/ 37 | 38 | 39 | 40 | === TEST 3: fd_write via println 41 | --- wasm_modules: wasi_host_tests 42 | --- config 43 | location /t { 44 | wasm_call rewrite wasi_host_tests test_wasi_fd_write_via_println; 45 | } 46 | --- response_body 47 | test passed 48 | --- error_log eval 49 | qr/\[info\] .*? Hello, println/ 50 | 51 | 52 | 53 | === TEST 4: fd_write to an unsupported fd 54 | --- wasm_modules: wasi_host_tests 55 | --- config 56 | location /t { 57 | wasm_call rewrite wasi_host_tests test_wasi_fd_write_unsupported_fd; 58 | } 59 | --- response_body 60 | test passed 61 | --- no_error_log 62 | hello, fd_write 63 | 64 | 65 | 66 | === TEST 5: fd_write an empty string 67 | --- wasm_modules: wasi_host_tests 68 | --- config 69 | location /t { 70 | wasm_call rewrite wasi_host_tests test_wasi_fd_write_empty_string; 71 | } 72 | --- response_body 73 | test passed 74 | --- no_error_log 75 | hello, fd_write 76 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/path_open.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: path_open stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_path_open; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/poll_oneoff.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_fdstat_set_flags stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_poll_oneoff; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/random_get.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: random_get 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_random_get; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/05-wasi/wasi-p1/sched_yield.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_wasi(); 8 | 9 | plan_tests(3); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: fd_fdstat_set_flags stub 15 | --- wasm_modules: wasi_host_tests 16 | --- config 17 | location /t { 18 | wasm_call rewrite wasi_host_tests test_wasi_sched_yield; 19 | } 20 | --- response_body 21 | test passed 22 | --- no_error_log 23 | [error] 24 | -------------------------------------------------------------------------------- /t/06-others/002-resolver_add_sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: resolver_add directive - IPv4 sanity 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: hostcalls 15 | --- config 16 | server_name hostname; 17 | resolver 1.1.1.1 ipv6=off; 18 | resolver_add 127.0.0.1 hostname; 19 | 20 | location /t { 21 | proxy_wasm hostcalls 'test=/t/dispatch_http_call \ 22 | host=hostname:$TEST_NGINX_SERVER_PORT \ 23 | path=/dispatch \ 24 | on_http_call_response=echo_response_body'; 25 | echo fail; 26 | } 27 | 28 | location /dispatch { 29 | echo ok; 30 | } 31 | --- response_body 32 | ok 33 | --- no_error_log 34 | [error] 35 | [crit] 36 | 37 | 38 | 39 | === TEST 2: resolver_add directive - IPv6 sanity 40 | --- load_nginx_modules: ngx_http_echo_module 41 | --- wasm_modules: hostcalls 42 | --- config 43 | listen [::]:$TEST_NGINX_SERVER_PORT; 44 | server_name hostname; 45 | resolver 1.1.1.1 ipv6=on; 46 | resolver_add 0:0:0:0:0:0:0:1 hostname; 47 | 48 | location /t { 49 | proxy_wasm hostcalls 'test=/t/dispatch_http_call \ 50 | host=[0:0:0:0:0:0:0:1]:$TEST_NGINX_SERVER_PORT \ 51 | path=/dispatch \ 52 | on_http_call_response=echo_response_body'; 53 | echo fail; 54 | } 55 | 56 | location /dispatch { 57 | echo ok; 58 | } 59 | --- response_body 60 | ok 61 | --- no_error_log 62 | [error] 63 | [crit] 64 | -------------------------------------------------------------------------------- /t/06-others/011-upstream_connection_abort.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_hup(); 8 | 9 | plan_tests(4); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: upstream connection abort - wasm_call 15 | Calls on aborted upstream connections execute response phases on the produced 16 | --- skip_no_debug 17 | --- wasm_modules: ngx_rust_tests 18 | --- tcp_listen: $TEST_NGINX_UNIX_SOCKET 19 | --- tcp_shutdown: 2 20 | --- tcp_reply eval 21 | sub { 22 | return ["HTTP/1.1 100 OK\r\n", 23 | "Connection: close\r\n", 24 | "Content-Length: 0\r\n", 25 | "\r\n"]; 26 | } 27 | --- config 28 | location /t { 29 | wasm_call header_filter ngx_rust_tests log_notice_hello; 30 | wasm_call body_filter ngx_rust_tests log_notice_hello; 31 | proxy_pass http://unix:$TEST_NGINX_UNIX_SOCKET:/; 32 | } 33 | --- error_code: 502 34 | --- ignore_response 35 | --- grep_error_log eval: qr/(upstream prematurely closed|(wasm ops calling .*? in .*? phase))/ 36 | --- grep_error_log_out eval 37 | qr/\Aupstream prematurely closed 38 | wasm ops calling "ngx_rust_tests\.log_notice_hello" in "header_filter" phase 39 | wasm ops calling "ngx_rust_tests\.log_notice_hello" in "body_filter" phase\Z/ 40 | --- no_error_log 41 | [crit] 42 | [emerg] 43 | [alert] 44 | 45 | 46 | 47 | === TEST 2: upstream connection abort - chained filters 48 | Filters on aborted upstream connections execute response phases on the produced 49 | HTTP 502 response. 50 | --- wasm_modules: on_phases 51 | --- tcp_listen: $TEST_NGINX_UNIX_SOCKET 52 | --- tcp_shutdown: 2 53 | --- tcp_reply eval 54 | sub { 55 | return ["HTTP/1.1 100 OK\r\n", 56 | "Connection: close\r\n", 57 | "Content-Length: 0\r\n", 58 | "\r\n"]; 59 | } 60 | --- config 61 | location /t { 62 | proxy_wasm on_phases; 63 | proxy_wasm on_phases; 64 | proxy_pass http://unix:$TEST_NGINX_UNIX_SOCKET:/; 65 | } 66 | --- error_code: 502 67 | --- ignore_response 68 | --- grep_error_log eval: qr/\[(error|info)\] .*? ((upstream prematurely closed)|on_request_headers|on_response_headers|on_log|on_done|on_http_call_response.*)/ 69 | --- grep_error_log_out eval 70 | qr/\A\[info\] .*? on_request_headers 71 | \[info\] .*? on_request_headers 72 | \[error\] .*? upstream prematurely closed 73 | \[info\] .*? on_response_headers 74 | \[info\] .*? on_response_headers 75 | \[info\] .*? on_done 76 | \[info\] .*? on_log 77 | \[info\] .*? on_done 78 | \[info\] .*? on_log\Z/ 79 | --- no_error_log 80 | [crit] 81 | [emerg] 82 | [alert] 83 | -------------------------------------------------------------------------------- /t/07-ipc/001-ipc_block.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | skip_no_ipc(); 8 | 9 | plan_tests(6); 10 | run_tests(); 11 | 12 | __DATA__ 13 | 14 | === TEST 1: ipc{} - empty block 15 | --- skip_no_debug 16 | --- valgrind 17 | --- main_config 18 | ipc {} 19 | --- error_log 20 | ipc core module initializing 21 | --- no_error_log 22 | wasm core module initializing 23 | [error] 24 | [crit] 25 | [emerg] 26 | 27 | 28 | 29 | === TEST 2: ipc{} - with wasm{} block 30 | --- skip_no_debug 31 | --- valgrind 32 | --- main_config 33 | ipc {} 34 | wasm {} 35 | --- error_log 36 | ipc core module initializing 37 | wasm core module initializing 38 | --- no_error_log 39 | [error] 40 | [crit] 41 | [emerg] 42 | 43 | 44 | 45 | === TEST 3: ipc{} - duplicated block 46 | --- main_config 47 | ipc {} 48 | ipc {} 49 | --- error_log 50 | "ipc" directive is duplicate 51 | --- no_error_log 52 | ipc core module initializing 53 | [error] 54 | [crit] 55 | [alert] 56 | --- must_die 57 | -------------------------------------------------------------------------------- /t/11-bench/001-bench_hash.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: bench - mandelbrot 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: benchmarks 15 | --- config 16 | location /t { 17 | proxy_wasm benchmarks; 18 | echo fail; 19 | } 20 | --- request 21 | GET /t/hash 22 | --- more_headers 23 | X-Prefix: test-prefix-3 24 | --- response_body 25 | test-prefix-3-1873 26 | --- no_error_log 27 | [error] 28 | [crit] 29 | -------------------------------------------------------------------------------- /t/11-bench/002-bench_fannkuch_redux.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: bench - fannkuch_redux 13 | --- load_nginx_modules: ngx_http_echo_module 14 | --- wasm_modules: benchmarks 15 | --- config 16 | location /t { 17 | proxy_wasm benchmarks; 18 | echo fail; 19 | } 20 | --- request 21 | GET /t/fannkuch_redux 22 | --- more_headers 23 | X-N: 8 24 | --- response_body 25 | 1616 26 | Pfannkuchen(8) = 22 27 | --- no_error_log 28 | [error] 29 | [crit] 30 | -------------------------------------------------------------------------------- /t/11-bench/003-bench_proxy_wasm.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sts=4 sw=4 et fdm=marker: 2 | 3 | use strict; 4 | use lib '.'; 5 | use t::TestWasmX; 6 | 7 | plan_tests(4); 8 | run_tests(); 9 | 10 | __DATA__ 11 | 12 | === TEST 1: bench - proxy_wasm on_phases filter 13 | --- wasm_modules: on_phases 14 | --- config 15 | location /t { 16 | proxy_wasm on_phases; 17 | return 200; 18 | } 19 | --- response_body 20 | --- no_error_log 21 | [error] 22 | [crit] 23 | -------------------------------------------------------------------------------- /t/TestWasmX/Lua.pm: -------------------------------------------------------------------------------- 1 | package t::TestWasmX::Lua; 2 | 3 | use strict; 4 | use t::TestWasmX -Base; 5 | 6 | our $lua_package_path = "${buildroot}/prefix/?.lua;${buildroot}/prefix/?/init.lua;./lib/?.lua;;"; 7 | 8 | our @EXPORT = qw( 9 | $lua_package_path 10 | skip_no_openresty 11 | ); 12 | 13 | sub skip_no_openresty { 14 | my $build_name = (split /\n/, $nginxV)[0]; 15 | 16 | if ($build_name !~ m/nginx version: openresty/) { 17 | plan skip_all => "not an OpenResty binary"; 18 | } 19 | } 20 | 21 | add_block_preprocessor(sub { 22 | my $block = shift; 23 | my $http_config = $block->http_config || ''; 24 | 25 | $http_config .= <<_EOC_; 26 | lua_package_path '$lua_package_path'; 27 | _EOC_ 28 | 29 | $block->set_value("http_config", $http_config); 30 | }); 31 | 32 | 1; 33 | -------------------------------------------------------------------------------- /t/data/badssl_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFKTCCBBGgAwIBAgISA72GeoqMzBVu8cWy+pmPRE8ZMA0GCSqGSIb3DQEBCwUA 3 | MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD 4 | EwJSMzAeFw0yMjA4MTIxNDU3NDZaFw0yMjExMTAxNDU3NDVaMBcxFTATBgNVBAMM 5 | DCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKW7 6 | HVuI3+OFYi9Tz1gU+5GGHsp2W7bDW/DAyNtI0zCUDnPb53J/YU3gUpbp+kxtmQIY 7 | gXwV4lRwJ/6J6SpuEEgej8ZwI5fXMoVECL53FqCAKQEMVOtVmsFbj4p+4qeiXQ9Y 8 | D783s3BiPKeRmyfGXpXm/nRCMco3Cg+HsmXkRYy75g0yXtqLg9x1SJKPF8136Qdj 9 | kSqYdA+SclNtn4z6yEx9aheixsYwy/M6xo4/1hqUnUWh3Cs/ujCJD0yUx3Y3YKCf 10 | xXoxZPkwQND/rhr6Qf2h4h8W/BOxt8yZ6AJdSYHa945pMRly6FOM53/Mv1xhDNZS 11 | dN4hP7p2NrMWa7B7SGcCAwEAAaOCAlIwggJOMA4GA1UdDwEB/wQEAwIFoDAdBgNV 12 | HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E 13 | FgQUUqHvF2qvpN783rvRKXLGaT9yf2UwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA 14 | 5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMu 15 | by5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8w 16 | IwYDVR0RBBwwGoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29tMEwGA1UdIARFMEMw 17 | CAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9j 18 | cHMubGV0c2VuY3J5cHQub3JnMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHUAQcjK 19 | sd8iRkoQxqE6CUKHXk4xixsD6+tLx2jwkGKWBvYAAAGCksaeKQAABAMARjBEAiBW 20 | 1iLbri7Vt+WRi4LQkSOsB0BLvE2QmxO0FshSLBm+UgIgSdsuOrzyQa0EdyJJs6tC 21 | U05eto6fyCAplMfVWE0oP2UAdgApeb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZc 22 | JV3HhAAAAYKSxp4aAAAEAwBHMEUCIQC/2FVuRQtT2J1lLhFqcValPdlVW+ALLsPV 23 | EZL6UqlYRwIgdd1uCPqTuMGxHg8zsPv86LEjC8cVF/eM8Ayi6VMZlowwDQYJKoZI 24 | hvcNAQELBQADggEBAB7jnMkT4FfcthfJvO5c5CUgwzIyUxXmURXrOlEYmfSuFojL 25 | PW5qfLB18J1hMyC0S4sZc7iIHk504b6MN/tgTnZEhH2pWltT/RBbVlbobEUOs8Kb 26 | 7hLIxZbPS10K0GqDrVJptizsP4jCW69hq71b3cMHwOcJhhqZyY6tBLicqLO4O7bI 27 | 5Wcp79WBB7SVgiE7GFcc/manUs0xKTpj2sCkvg5761VBFM5VDKnqLSMeXQHl7C3D 28 | 0R1hweoSh/NNcSoo0ZOXwT68jxdkuPaIkTkjaktqPt/toOwYWONewyz1q9CL1KOO 29 | AsEK3KNMoHmtkduv4NSbadJT6uSPrP0Bx/zLt5s= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /t/data/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDjzCCAnegAwIBAgIUCtIGSi1CdhLhymtVESn8xVaeUawwDQYJKoZIhvcNAQEL 3 | BQAwVjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE 4 | CgwTRGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJMTI3LjAuMC4xMCAXDTIy 5 | MDgxNjEwMDE1NloYDzQ3NjAwNzEyMTAwMTU2WjBWMQswCQYDVQQGEwJYWDEVMBMG 6 | A1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRk 7 | MRIwEAYDVQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK 8 | AoIBAQCzatUQY8k40dzkh5Da0RVEWPsl6o8dseNjIJwMyzBMbC6sffiZsQnB9XCk 9 | NoDJACDC4HaauB/FapMATF6CPCl9UxkLZ/Z0zhg81xJrJLukHZh2acokBAFULsTz 10 | FYB7V8X7EcLEbkbAxqmFjHZRJ+KF8wEB7RPAoMT1T6cvmFFrHb5qJ6uCOwpMnN9s 11 | wPyY4DrdiaV9+vzhq/p0lZoIj4oiPjYs1XjEQJWJDVGk3w3SYA0/ahlzKXw0llTC 12 | sx17ltwQDHGVwl2xVyHtFEREE2YLUjBZjiiPGu2NdGUcA0zLJ6cyc5WqZ41xEYm6 13 | C4I+i5HXldGbOhIV2zjto8rYFbbBAgMBAAGjUzBRMB0GA1UdDgQWBBTslN+U8iO9 14 | wgs3xkibH6Zlm3y+cTAfBgNVHSMEGDAWgBTslN+U8iO9wgs3xkibH6Zlm3y+cTAP 15 | BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB4lOp5DgjnAdMIPpcZ 16 | 6tnlcR1kSSx2tFxIKuTU4yhhEaO2bKy/PCGpnWWFVKwAd9qz/v+bL07kCFwV/YRu 17 | gKcWWxMhoublyAEGED+R1SZGD/uErDFdMHZ/pnDnoj2iTP0LGMiiNmwiRST89RgV 18 | QAPZ23XQ4hz91EP3KALBvyRlt4gfXjzhX2yd1uSouYIkh6+0Jxj1A3pTmbMGZRzp 19 | nfbCYiOkcGWgtlHHCm0ZpFB8p3i7an68r3SJp5RZFP9O2nJhR6RSkPYtf/AKW/rA 20 | 6J8urAQApFz4FtVsJu3qsBCSmThvPIobWeEAG1esl9BKb0XiPOglQ7R5FevtaJJp 21 | euLL 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /t/data/hostname_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDjTCCAnWgAwIBAgIUCU/L35ArdINqXVXjaiqvh5FwpPkwDQYJKoZIhvcNAQEL 3 | BQAwVTELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE 4 | CgwTRGVmYXVsdCBDb21wYW55IEx0ZDERMA8GA1UEAwwIaG9zdG5hbWUwIBcNMjIw 5 | ODE4MjEyMzQxWhgPNDc2MDA3MTQyMTIzNDFaMFUxCzAJBgNVBAYTAlhYMRUwEwYD 6 | VQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQx 7 | ETAPBgNVBAMMCGhvc3RuYW1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 8 | AQEA2S8RcOzIJ91UnkYFLSFjCfUmsnHWIHkiPGjTYwMsxSPEnDc9dRpt8xNx5Njf 9 | jm2090OLn6FLySLRxVSoSen1Xm62lz5aEGPUS7ie9bZYHkIi8zeEfE4P+zMxIwvm 10 | ERfFNTrdMrf8GPM8WV5op5AsEKiBU+VBQwOBCVsuQLmABW5zwzXx6QpY8jak+Epl 11 | nWD39LHnlouHeuJUWGc/kGcui4EGUL73YsTbvG/etDfqjVwJSUxL1RZzFftpCzYK 12 | pHbUFOaW5xCryp/KzIL+ussIGnIYEebIwy3hyu8LdJuWLzhl194j4228BLnJm/zd 13 | WQl2eGEEYyBMen7gjKKAE96pTQIDAQABo1MwUTAdBgNVHQ4EFgQUYhbb+pEfP1SE 14 | DtI+qcXZiW2KgwAwHwYDVR0jBBgwFoAUYhbb+pEfP1SEDtI+qcXZiW2KgwAwDwYD 15 | VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAqfeYsEmn1/yWtEYltlJe 16 | auc4A3KNdI7jk2/IewN59SZG71VJCPmRYpfx6u//0AVTNm2S8fIt2+/XND+7dhQX 17 | VLOxbis30E1Li4vTU0l5MvXgNJLyWadIQJaUxjgXO/1dD7im2ruxRMuJ4SNJwDjb 18 | PLaweUDfP5sxOa57IEGteGWfXgxggCw9D9fc5f++R0qiJhye4RjMEXXeymHqmxGb 19 | eXiZAyjdtI+ViDlWSn+KDRxefhokAnMsojp4slu98BCUki5b2SrEhWc7Qt0T8xxT 20 | b7vlDb3gz9hx97gSpgYG5DajL3b+uXuXQCmaLaAHuIk4wodL7I1N/SNJxDkcrNAW 21 | Eg== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /t/data/hostname_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDZLxFw7Mgn3VSe 3 | RgUtIWMJ9SaycdYgeSI8aNNjAyzFI8ScNz11Gm3zE3Hk2N+ObbT3Q4ufoUvJItHF 4 | VKhJ6fVebraXPloQY9RLuJ71tlgeQiLzN4R8Tg/7MzEjC+YRF8U1Ot0yt/wY8zxZ 5 | XminkCwQqIFT5UFDA4EJWy5AuYAFbnPDNfHpCljyNqT4SmWdYPf0seeWi4d64lRY 6 | Zz+QZy6LgQZQvvdixNu8b960N+qNXAlJTEvVFnMV+2kLNgqkdtQU5pbnEKvKn8rM 7 | gv66ywgachgR5sjDLeHK7wt0m5YvOGXX3iPjbbwEucmb/N1ZCXZ4YQRjIEx6fuCM 8 | ooAT3qlNAgMBAAECggEAd8m5MfK3dx1hlaaDJmA60vwvKs8UznZhhrY+mWbf46AV 9 | yh/Buvwn1qFL+XAQ5ermnFbaBOKe/UJCNze5VoM/PaWM+iB+5nlZV6ZtrpKzSYUq 10 | 58EgRrt7nw6eNHlUnOrib7iW1mmaF1zZVWV4Dau8UjfOlSpmc4LUQgfTnAl0bgl4 11 | nYMI1XXC3Zgwffmc+4OTqHZOJ49m294OH/0X3ksWGtD0/kahhBuqyyrhiswQpncW 12 | nM4QkEJw8dYMPvW0yyvhTeuUhtK9G8wLC9h3anUTM89SWs0y/4gdhYtTK92w6WBR 13 | xYVY3aksB2SjneUxq+Mg9UXPdPcTr+1+WH/mBOLOdQKBgQDsyS0YLxtTQoFkHWG8 14 | kAnivnH+cYIjddflslw72S4f2R7ZdZVfxZtOR85PoTpZ8nxzt7ImS5qzqauBDB93 15 | KWB75l6EpkGCivvEC+DU3q7VcaZBQao+y/amTpo23drxYqdu8PzH/3zqK09W289z 16 | SBbqkSzIdLUYbrdtMV0lP2O26wKBgQDqzrGsYCJk5ZbFXmyk9vwcYsoxeA6p+cYK 17 | H6gpi8nCCGOisB6b9tfC0jI8Z/G0w0zlt/uaIP4hJCbX1bbgTV3xKmV27HVcAox1 18 | PEcevcYNcXk5Y7u+XJUVz5HIIxR9zAbBIo+kUeYHVkqXrGe/DxuEoHuf4HaLWvFM 19 | Hwj/Jw2CpwKBgCa6VLzS35ZDl2QnhhfQOz2xxnVGXXGtUY2JGZrUT733xhrtJ2xN 20 | prQr/Gt7xE534bEPh3zJ+tiN1LY7pF3aD6TULftmMerHDpynELPgZBoXB4k+0ziI 21 | JaRX0NNOgAPhDd+QXNfdSrIGOWjMdOa3EMB21CtJI2GGokuiukhgUM/XAoGAVeFX 22 | draKneCjLnkEv6leOHuhfEpvAphKaLV/agKovoEXAA/ughjcfXMn0JQsAXNVEsgi 23 | DBN5H2H7mwGdq5hgfa6GAeMmYYrFGLP9Ry8d2xjfv6/MoSl3lcyfg1XhTslqxwT/ 24 | CJizy4cyLRtvrp+17uJLlQQiF4Ihsze+sKP1+w0CgYEAjZhq76zuuxOMNWgDo9dX 25 | puEMszCip683qzRX38tuBAilJxJyk8ZCf9Otpf9joxbMSLWhASWO2UZesAz57XdF 26 | h/ps/jj+xxteCXKEMEQUl3Yb9EmiJWFO3QpvyyZYKdDH8RZOxqzo4EKhTawac9LB 27 | H8jNsQojMJteM2aPABBRn+o= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /t/data/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzatUQY8k40dzk 3 | h5Da0RVEWPsl6o8dseNjIJwMyzBMbC6sffiZsQnB9XCkNoDJACDC4HaauB/FapMA 4 | TF6CPCl9UxkLZ/Z0zhg81xJrJLukHZh2acokBAFULsTzFYB7V8X7EcLEbkbAxqmF 5 | jHZRJ+KF8wEB7RPAoMT1T6cvmFFrHb5qJ6uCOwpMnN9swPyY4DrdiaV9+vzhq/p0 6 | lZoIj4oiPjYs1XjEQJWJDVGk3w3SYA0/ahlzKXw0llTCsx17ltwQDHGVwl2xVyHt 7 | FEREE2YLUjBZjiiPGu2NdGUcA0zLJ6cyc5WqZ41xEYm6C4I+i5HXldGbOhIV2zjt 8 | o8rYFbbBAgMBAAECggEAT4G+HV864nUNgDAbHvycggc0dF73QN99toXS4VCBfLxM 9 | CqBgNCth+ZO8cOi+NVRbMECsDnAdlCxgLDergecLM8BJTuapLqXN09gzD0vd4yJC 10 | V+cVbtRfimCXYmla4E3LLDF4r/d2XyMqKEZQgDI+jcFb5vCaWjhkT5kWq17CZcaw 11 | Nh6cuUZhIEXloMfUoHAafy/4rpPw4BT7R1DX6DQJlR1sui9A+FvZWtqCSbfmE/OK 12 | yndj1yNoLQVrS4B/KunyDQZ8uDB502poHt6wwlb/syMvdgt30YvCDzx8SD/7Y6Jg 13 | gIfFE/+yIFbzPD8mO0u6OMJfVa1jr7A+7nyC+DkdaQKBgQDj+P04v8f294uPbp6I 14 | hqqa6b/MscsrS60UajqEVOPLFEVDWjM8hIs9cZuCPjoWBrVudPSsC0F3JiIsqPgg 15 | e2VUIkbnGjvqW2LEv2YC4Y7TAUzimkSvCNFJLrC76ATOaXmkVC3wIyhf7kUz8uD+ 16 | +ZC1/9c5U7f9IBRdbGNXrsIekwKBgQDJeafyPZCwlTsB57JjEuP9yJL3ifJd2N2+ 17 | LV4AIa4p2EOBczRke61cQ3wPgBUTndCtFqKA71ODgpVwSSfu/YoKd7yI0cJEjDLr 18 | A+iu7SRQ8cWsTUAUTcnUpiRUGS1WvGLj3gpcj68/kDj0fLHwf6/d1KLu4CynfPYi 19 | ebGMfR6V2wKBgDEyZ3sasA2U6FJAvgeagDDEJvcGm2CxiR1xu0UZiLsnmbbqPUpf 20 | FCljXfricOiV9AttQ+vo1ezfltpqcHmaB4j7iK+Q0sNFi3AIGfyfLpJMoon4XsAj 21 | N/8CC3PRo0/kJTMYU32SKMFjCx4l2PZNZzRPjOO7NGZ0yNBMdrfSZ+PvAoGAUBFu 22 | AiIfZ13XFnm69g6i1s+oQIHs9Qjjjtm+urSn329X3JEpKCnSipEzM4HGXoZgUPlm 23 | 2XDDMsdpljcsjJjsDB7rqUAbQVyqO6XRCfuqbBS5ZzFIHwmPBViFpXpf/1Fcx4wN 24 | eB2OGue5Csinepl0DeecXOxwMpvBwY+1VMzAo/MCgYEA0ntBXkA4vyuhC4oFb49Q 25 | T+b9gwIcbWKfwW8z5VPKGE7E7AsGHBLK0F0PeWymnvGSza2B4Sp9pXdKoH7WJ0mw 26 | uXg/rqrI4I5TA2p3bTVsbbnnpKU/Iad7ZXlhB/EIrpD1MioGD6PK7HvIHJGcNmjU 27 | 2is8Oid70HzUT5BYnu+Do60= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /t/lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "ngx-rust-tests", 4 | "ngx-lua-tests", 5 | "wasi-vm-tests", 6 | "wasi-host-tests", 7 | "proxy-wasm-tests/on-tick", 8 | "proxy-wasm-tests/on-phases", 9 | "proxy-wasm-tests/hostcalls", 10 | "proxy-wasm-tests/rust-sdk-ver-zero-one", 11 | "proxy-wasm-tests/benchmarks", 12 | "proxy-wasm-tests/instance-lifecycle", 13 | "proxy-wasm-tests/context-checks", 14 | ] 15 | -------------------------------------------------------------------------------- /t/lib/ngx-lua-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-lua-tests" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | ngx = { path = "../../../lib/ngx-rust" } 12 | -------------------------------------------------------------------------------- /t/lib/ngx-lua-tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod lua_bridge; 2 | pub use lua_bridge::*; 3 | -------------------------------------------------------------------------------- /t/lib/ngx-lua-tests/src/lua_bridge.rs: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | fn ngx_wasm_lua_test_argsrets(); 3 | fn ngx_wasm_lua_test_bad_chunk(); 4 | fn ngx_wasm_lua_test_error(); 5 | fn ngx_wasm_lua_test_sleep(); 6 | fn ngx_wasm_lua_test_cancel(); 7 | } 8 | 9 | #[no_mangle] 10 | pub fn test_lua_argsrets() { 11 | unsafe { ngx_wasm_lua_test_argsrets() } 12 | } 13 | 14 | #[no_mangle] 15 | pub fn test_bad_lua_chunk() { 16 | unsafe { ngx_wasm_lua_test_bad_chunk() } 17 | } 18 | 19 | #[no_mangle] 20 | pub fn test_lua_error() { 21 | unsafe { ngx_wasm_lua_test_error() } 22 | } 23 | 24 | #[no_mangle] 25 | pub fn test_lua_sleep() { 26 | unsafe { ngx_wasm_lua_test_sleep() } 27 | } 28 | 29 | #[no_mangle] 30 | pub fn test_lua_cancel() { 31 | unsafe { ngx_wasm_lua_test_cancel() } 32 | } 33 | -------------------------------------------------------------------------------- /t/lib/ngx-rust-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ngx-rust-tests" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | ngx = { path = "../../../lib/ngx-rust" } 12 | -------------------------------------------------------------------------------- /t/lib/ngx-rust-tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | use ngx::*; 2 | 3 | #[no_mangle] 4 | pub fn nop() {} 5 | 6 | #[no_mangle] 7 | pub fn log_notice_hello() { 8 | ngx_log!(Notice, "hello world"); 9 | } 10 | 11 | #[no_mangle] 12 | pub fn log_resp_status() { 13 | ngx_log!(Notice, "resp status: {}", ngx_resp_get_status()); 14 | } 15 | 16 | #[no_mangle] 17 | pub fn set_resp_status() { 18 | ngx_resp_set_status(201); 19 | } 20 | 21 | #[no_mangle] 22 | pub fn say_hello() { 23 | ngx_resp_say(Some("hello say")); 24 | } 25 | 26 | #[no_mangle] 27 | pub fn say_nothing() { 28 | ngx_resp_say(Some("")); 29 | } 30 | 31 | #[no_mangle] 32 | pub fn local_reason() { 33 | ngx_resp_local(201, Some("REASON"), None); 34 | } 35 | 36 | #[no_mangle] 37 | pub fn local_response() { 38 | ngx_resp_local(200, Some("OK"), Some("hello world")); 39 | } 40 | 41 | #[no_mangle] 42 | pub fn discard_local_response() { 43 | ngx_resp_discard_local(); 44 | } 45 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/benchmarks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "benchmarks" 3 | version = "0.1.0" 4 | authors = ["Heyang Zhou "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/filter.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | proxy-wasm = "0.2" 13 | log = "0.4" 14 | enum-utils = "0.1.2" 15 | blake3 = "1.3.1" 16 | hex = "0.4.3" 17 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/benchmarks/src/filter.rs: -------------------------------------------------------------------------------- 1 | mod fannkuch_redux; 2 | 3 | use log::info; 4 | use proxy_wasm::traits::*; 5 | use proxy_wasm::types::*; 6 | 7 | struct BenchmarksRoot {} 8 | 9 | impl Context for BenchmarksRoot {} 10 | impl RootContext for BenchmarksRoot { 11 | fn get_type(&self) -> Option { 12 | Some(ContextType::HttpContext) 13 | } 14 | 15 | fn create_http_context(&self, _context_id: u32) -> Option> { 16 | Some(Box::new(Benchmarks {})) 17 | } 18 | } 19 | 20 | struct Benchmarks {} 21 | 22 | impl Context for Benchmarks {} 23 | impl HttpContext for Benchmarks { 24 | fn on_http_request_headers(&mut self, _nheaders: usize, _eof: bool) -> Action { 25 | let path = self.get_http_request_header(":path").unwrap(); 26 | info!("on_http_request_headers {}", path); 27 | match path.as_str() { 28 | "/t/hash" => { 29 | let prefix = self 30 | .get_http_request_header("x-prefix") 31 | .expect("missing x-prefix"); 32 | for i in 0u64.. { 33 | let s = format!("{prefix}-{i}"); 34 | let hash = blake3::hash(s.as_bytes()); 35 | let bytes = hash.as_bytes(); 36 | if bytes[0] == 0 && bytes[1] == 0 { 37 | self.send_http_response(200, vec![], Some(s.as_bytes())); 38 | break; 39 | } 40 | } 41 | } 42 | "/t/fannkuch_redux" => { 43 | let n = self 44 | .get_http_request_header("x-n") 45 | .expect("missing x-n") 46 | .parse::() 47 | .unwrap(); 48 | let output = fannkuch_redux::run(n); 49 | self.send_http_response(200, vec![], Some(output.as_bytes())); 50 | } 51 | _ => {} 52 | } 53 | Action::Continue 54 | } 55 | } 56 | 57 | #[no_mangle] 58 | pub fn _start() { 59 | proxy_wasm::set_log_level(LogLevel::Warn); 60 | proxy_wasm::set_root_context(|_| -> Box { Box::new(BenchmarksRoot {}) }); 61 | } 62 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/context-checks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "context-checks" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | proxy-wasm = { git = "https://github.com/kong/proxy-wasm-rust-sdk.git", branch = "main" } 12 | log = "0.4" 13 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/hostcalls/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hostcalls" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | proxy-wasm = { git = "https://github.com/kong/proxy-wasm-rust-sdk.git", branch = "main" } 12 | log = "0.4" 13 | http = "1.2" 14 | enum-utils = "0.1.2" 15 | urlencoding = "2.1.2" 16 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/hostcalls/src/foreign_callbacks/mod.rs: -------------------------------------------------------------------------------- 1 | use log::*; 2 | 3 | pub fn resolve_lua_callback(args: Option>) { 4 | match args { 5 | Some(args) => { 6 | let address_size = args[0] as usize; 7 | let name = std::str::from_utf8(&args[(address_size + 1)..]).unwrap(); 8 | 9 | if address_size > 0 { 10 | let address = &args[1..address_size + 1]; 11 | info!("resolved (yielding) {} to {:?}", name, address); 12 | } else { 13 | info!("could not resolve {}", name) 14 | } 15 | } 16 | _ => info!("empty args"), 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/hostcalls/src/tests/echo.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use http::StatusCode; 3 | use std::str; 4 | 5 | pub(crate) fn echo_headers(ctx: &mut TestHttp) { 6 | let headers = ctx 7 | .get_http_request_headers() 8 | .iter() 9 | .filter_map(|(name, value)| { 10 | // Do not include ':path' and such special headers 11 | // Do not include 'pwm-*' test headers 12 | if name.to_lowercase().starts_with("pwm-") || name.to_lowercase().starts_with(':') { 13 | return None; 14 | } 15 | 16 | Some((name, value)) 17 | }) 18 | .map(|(name, value)| format!("{name}: {value}")) 19 | .collect::>() 20 | .join("\n"); 21 | 22 | ctx.send_plain_response(StatusCode::OK, Some(headers.as_str())); 23 | } 24 | 25 | pub(crate) fn echo_all_headers(ctx: &mut TestHttp) { 26 | let headers = ctx 27 | .get_http_request_headers() 28 | .iter() 29 | .map(|(name, value)| format!("{name}: {value}")) 30 | .collect::>() 31 | .join("\n"); 32 | 33 | ctx.send_plain_response(StatusCode::OK, Some(headers.as_str())); 34 | } 35 | 36 | pub(crate) fn echo_header(ctx: &mut TestHttp, name: &str) { 37 | let _ = ctx.get_http_request_header(name); 38 | let value = ctx.get_http_request_header(name); // twice for host cache hit 39 | if value.is_none() { 40 | ctx.send_plain_response(StatusCode::OK, Some(format!("{name}:").as_str())); 41 | return; 42 | } 43 | 44 | let body = format!("{name}: {}", value.unwrap()); 45 | ctx.send_plain_response(StatusCode::OK, Some(body.as_str())); 46 | } 47 | 48 | pub(crate) fn echo_body(ctx: &mut TestHttp) { 49 | let req_body = ctx.get_http_request_body(0, usize::MAX); 50 | info!("/echo/body buffer: {:?}", req_body); 51 | 52 | if let Some(body) = req_body { 53 | ctx.send_plain_response( 54 | StatusCode::OK, 55 | Some(str::from_utf8(&body).expect("Invalid UTF-8 sequence")), 56 | ); 57 | } else { 58 | ctx.send_plain_response(StatusCode::OK, None); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/hostcalls/src/types/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod test_http; 2 | pub mod test_root; 3 | 4 | use crate::*; 5 | 6 | #[derive(Debug, Eq, PartialEq, enum_utils::FromStr)] 7 | #[enumeration(rename_all = "snake_case")] 8 | pub enum TestPhase { 9 | Configure, 10 | Tick, 11 | RequestHeaders, 12 | RequestBody, 13 | ResponseHeaders, 14 | ResponseBody, 15 | ResponseTrailers, 16 | Log, 17 | } 18 | 19 | #[repr(u32)] 20 | #[allow(dead_code)] // ignore erroneous dead code warning 21 | pub enum WasmxForeignFunction { 22 | ResolveLua = 0, 23 | } 24 | 25 | pub trait TestContext { 26 | fn get_config(&self, name: &str) -> Option<&str>; 27 | fn get_metrics_mapping(&self) -> &BTreeMap; 28 | fn save_metric_mapping(&mut self, name: &str, metric_id: u32) -> Option; 29 | } 30 | 31 | impl Context for dyn TestContext {} 32 | 33 | impl TestContext for TestRoot { 34 | fn get_config(&self, name: &str) -> Option<&str> { 35 | self.config.get(name).map(|s| s.as_str()) 36 | } 37 | 38 | fn get_metrics_mapping(&self) -> &BTreeMap { 39 | &self.metrics 40 | } 41 | 42 | fn save_metric_mapping(&mut self, name: &str, metric_id: u32) -> Option { 43 | self.metrics.insert(name.to_string(), metric_id) 44 | } 45 | } 46 | 47 | impl TestContext for TestHttp { 48 | fn get_config(&self, name: &str) -> Option<&str> { 49 | self.config.get(name).map(|s| s.as_str()) 50 | } 51 | 52 | fn get_metrics_mapping(&self) -> &BTreeMap { 53 | &self.metrics 54 | } 55 | 56 | fn save_metric_mapping(&mut self, name: &str, metric_id: u32) -> Option { 57 | self.metrics.insert(name.to_string(), metric_id) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/hostcalls/src/types/test_root.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | pub struct TestRoot { 4 | pub config: HashMap, 5 | pub metrics: BTreeMap, 6 | pub n_sync_calls: usize, 7 | } 8 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/instance-lifecycle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "instance-lifecycle" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/filter.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | proxy-wasm = "0.2" 13 | log = "0.4" 14 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/instance-lifecycle/src/filter.rs: -------------------------------------------------------------------------------- 1 | use log::info; 2 | use proxy_wasm::{traits::*, types::*}; 3 | 4 | static mut MY_STATIC_VARIABLE: i32 = 123000; 5 | 6 | proxy_wasm::main! {{ 7 | proxy_wasm::set_log_level(LogLevel::Debug); 8 | proxy_wasm::set_root_context(|_| -> Box { 9 | Box::new(InstanceLifecycleRoot) 10 | }); 11 | }} 12 | 13 | struct InstanceLifecycleRoot; 14 | impl Context for InstanceLifecycleRoot {} 15 | impl RootContext for InstanceLifecycleRoot { 16 | fn get_type(&self) -> Option { 17 | Some(ContextType::HttpContext) 18 | } 19 | 20 | fn create_http_context(&self, context_id: u32) -> Option> { 21 | Some(Box::new(InstanceLifecycleHttp { context_id })) 22 | } 23 | } 24 | 25 | struct InstanceLifecycleHttp { 26 | context_id: u32, 27 | } 28 | impl Context for InstanceLifecycleHttp {} 29 | impl HttpContext for InstanceLifecycleHttp { 30 | fn on_http_request_headers(&mut self, _nheaders: usize, _eof: bool) -> Action { 31 | unsafe { 32 | MY_STATIC_VARIABLE += 1; 33 | } 34 | 35 | Action::Continue 36 | } 37 | 38 | fn on_log(&mut self) { 39 | let value = unsafe { MY_STATIC_VARIABLE }; 40 | info!("#{} on_log: MY_STATIC_VARIABLE: {}", self.context_id, value); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/on-phases/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "on-phases" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/filter.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | proxy-wasm = "0.2" 13 | log = "0.4" 14 | enum-utils = "0.1.2" 15 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/on-tick/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "on-tick" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/filter.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | proxy-wasm = "0.2" 13 | log = "0.4" 14 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/on-tick/src/filter.rs: -------------------------------------------------------------------------------- 1 | use log::info; 2 | use proxy_wasm::{traits::*, types::*}; 3 | use std::collections::HashMap; 4 | use std::time::Duration; 5 | 6 | proxy_wasm::main! {{ 7 | proxy_wasm::set_log_level(LogLevel::Debug); 8 | proxy_wasm::set_root_context(|_| -> Box { Box::new(OnTick {}) }); 9 | }} 10 | 11 | struct OnTick {} 12 | 13 | impl Context for OnTick {} 14 | impl RootContext for OnTick { 15 | fn get_type(&self) -> Option { 16 | Some(ContextType::HttpContext) 17 | } 18 | 19 | fn create_http_context(&self, _context_id: u32) -> Option> { 20 | Some(Box::new(OnTickHttp {})) 21 | } 22 | 23 | fn on_vm_start(&mut self, _: usize) -> bool { 24 | self.set_tick_period(Duration::from_millis(400)); 25 | true 26 | } 27 | 28 | fn on_configure(&mut self, _: usize) -> bool { 29 | if let Some(config_bytes) = self.get_plugin_configuration() { 30 | let config_str = String::from_utf8(config_bytes).unwrap(); 31 | let config: HashMap = config_str 32 | .split_whitespace() 33 | .map(|k| (k.to_string(), "".to_string())) 34 | .collect(); 35 | 36 | if config.contains_key("double_tick") { 37 | self.set_tick_period(Duration::from_millis(400)); 38 | } 39 | } 40 | 41 | true 42 | } 43 | 44 | fn on_tick(&mut self) { 45 | info!("ticking"); 46 | } 47 | } 48 | 49 | struct OnTickHttp; 50 | impl Context for OnTickHttp {} 51 | impl HttpContext for OnTickHttp { 52 | fn on_http_request_headers(&mut self, _: usize, _eof: bool) -> Action { 53 | info!("from request_headers"); 54 | Action::Continue 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /t/lib/proxy-wasm-tests/rust-sdk-ver-zero-one/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-sdk-ver-zero-one" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | path = "src/filter.rs" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | proxy-wasm = "0.1" 13 | http = "1.2" 14 | log = "0.4" 15 | -------------------------------------------------------------------------------- /t/lib/wasi-host-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasi-host-tests" 3 | version = "0.1.0" 4 | authors = ["Thibault Charbonnier "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | ngx = { path = "../../../lib/ngx-rust" } 12 | wasi = "0.11" 13 | -------------------------------------------------------------------------------- /t/lib/wasi-vm-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasi-vm-tests" 3 | version = "0.1.0" 4 | authors = ["Hisham Muhammad "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | ngx = { path = "../../../lib/ngx-rust" } 12 | wasi = "0.11" 13 | -------------------------------------------------------------------------------- /t/lib/wasi-vm-tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | use ngx::*; 2 | 3 | #[no_mangle] 4 | pub fn test_wasi_non_host() { 5 | // test a WASI function provided by the VM, not the host 6 | if unsafe { wasi::fd_filestat_get(1).is_ok() } { 7 | resp::ngx_resp_local(200, None, Some("test passed")); 8 | } else { 9 | resp::ngx_resp_local(500, None, Some("test failed")); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /util/changelog.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | SCRIPT_NAME=$(basename $0) 5 | NGX_WASM_DIR=${NGX_WASM_DIR:-"$( 6 | cd $(dirname $(dirname ${0})) 7 | pwd -P 8 | )"} 9 | if [[ ! -f "${NGX_WASM_DIR}/util/_lib.sh" ]]; then 10 | echo "Unable to source util/_lib.sh" >&2 11 | exit 1 12 | fi 13 | 14 | source $NGX_WASM_DIR/util/_lib.sh 15 | 16 | ############################################################################### 17 | 18 | cd $NGX_WASM_DIR 19 | 20 | # TODO: be smarter about grabbing the proper tag once we have more than just 21 | # prerelease tags 22 | LATEST_TAG=$(git describe --tags --abbrev=0) 23 | OUT="$(git --no-pager log --format=oneline $LATEST_TAG..)" 24 | 25 | if [[ -n $OUT ]]; then 26 | # Only show user-facing commits. Include refactor(), misc() and use best 27 | # judgement whether or not to include them in the final release 28 | # description. 29 | echo "$OUT" \ 30 | | sed "s/^[^ ]* //" \ 31 | | $(which grep) -v -E '^(chore|tests|style|hotfix|docs)' 32 | fi 33 | -------------------------------------------------------------------------------- /util/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | SCRIPT_NAME=$(basename $0) 5 | NGX_WASM_DIR=${NGX_WASM_DIR:-"$( 6 | cd $(dirname $(dirname ${0})) 7 | pwd -P 8 | )"} 9 | if [[ ! -f "${NGX_WASM_DIR}/util/_lib.sh" ]]; then 10 | echo "Unable to source util/_lib.sh" >&2 11 | exit 1 12 | fi 13 | 14 | source $NGX_WASM_DIR/util/_lib.sh 15 | 16 | ############################################################################### 17 | set +e 18 | 19 | if [[ -f "$DIR_PATCHED_ROOT/Makefile" ]]; then 20 | pushd $DIR_PATCHED_ROOT 21 | make clean 22 | rm -f Makefile 23 | popd 24 | fi 25 | 26 | if [[ "$1" == "--all" || "$1" == "--more" ]]; then 27 | rm -rf t/servroot* \ 28 | $DIR_SRC_ROOT \ 29 | $DIR_PATCHED_ROOT \ 30 | $DIR_BUILDROOT \ 31 | $DIR_PREFIX \ 32 | $DIR_SCANS \ 33 | $DIR_DIST_OUT \ 34 | $DIR_DIST_WORK \ 35 | $DIR_TESTS_LIB_WASM 36 | remove_luarocks 37 | cargo clean --manifest-path lib/Cargo.toml 38 | cargo clean --manifest-path t/lib/Cargo.toml 39 | fi 40 | 41 | if [[ "$1" == "--all" ]]; then 42 | rm -rf $DIR_WORK 43 | fi 44 | 45 | # vim: ft=sh ts=4 sts=4 sw=4: 46 | -------------------------------------------------------------------------------- /util/parse-valgrind.awk: -------------------------------------------------------------------------------- 1 | #!/bin/awk -f 2 | 3 | BEGIN { 4 | sep 5 | while (getline) { 6 | if ($0 ~ /^==[[:digit:]]+==\s*$/) { 7 | sep = "\n\n\n" 8 | } else if ($0 ~ /^==[[:digit:]]+==/) { 9 | printf "%s%s\n", sep, $0 10 | sep = "" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /util/reindex.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | SCRIPT_NAME=$(basename $0) 5 | NGX_WASM_DIR=${NGX_WASM_DIR:-"$( 6 | cd $(dirname $(dirname ${0})) 7 | pwd -P 8 | )"} 9 | if [[ ! -f "${NGX_WASM_DIR}/util/_lib.sh" ]]; then 10 | echo "Unable to source util/_lib.sh" >&2 11 | exit 1 12 | fi 13 | 14 | source $NGX_WASM_DIR/util/_lib.sh 15 | 16 | ############################################################################### 17 | 18 | if [[ ! -x "$DIR_BIN/reindex" ]]; then 19 | fatal "missing 'reindex' script, run 'make setup' first" 20 | fi 21 | 22 | exec $DIR_BIN/reindex "$@" 23 | 24 | # vim: ft=sh ts=4 sts=4 sw=4: 25 | -------------------------------------------------------------------------------- /util/style.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_NAME=$(basename $0) 4 | NGX_WASM_DIR=${NGX_WASM_DIR:-"$( 5 | cd $(dirname $(dirname ${0})) 6 | pwd -P 7 | )"} 8 | if [[ ! -f "${NGX_WASM_DIR}/util/_lib.sh" ]]; then 9 | echo "Unable to source util/_lib.sh" >&2 10 | exit 1 11 | fi 12 | 13 | source $NGX_WASM_DIR/util/_lib.sh 14 | 15 | ############################################################################### 16 | 17 | if [[ ! -x "$DIR_BIN/style" ]]; then 18 | fatal "missing 'style' script, run 'make setup' first" 19 | fi 20 | 21 | FILE_OUT=$DIR_WORK/style.out 22 | rc=0 23 | 24 | $DIR_BIN/style "$@" >$FILE_OUT & 25 | wait 26 | 27 | $NGX_WASM_DIR/util/morestyle.pl "$@" >>$FILE_OUT & 28 | wait 29 | 30 | if [[ -s "$FILE_OUT" ]]; then 31 | cat $FILE_OUT 32 | rc=1 33 | fi 34 | 35 | rm -f $FILE_OUT 36 | 37 | exit $rc 38 | -------------------------------------------------------------------------------- /valgrind.suppress: -------------------------------------------------------------------------------- 1 | { 2 | 3 | Memcheck:Leak 4 | match-leak-kinds: definite 5 | fun:malloc 6 | fun:ngx_alloc 7 | fun:ngx_set_environment 8 | } 9 | { 10 | 11 | Memcheck:Leak 12 | fun:malloc 13 | fun:ngx_alloc 14 | fun:ngx_event_process_init 15 | } 16 | { 17 | 18 | Memcheck:Leak 19 | match-leak-kinds: possible 20 | fun:malloc 21 | ... 22 | fun:ngx_crc32_table_init 23 | } 24 | { 25 | 26 | Memcheck:Cond 27 | fun:ngx_http_set_header_helper 28 | ... 29 | fun:ngx_http_headers_more_exec_cmd 30 | fun:ngx_http_headers_more_filter 31 | } 32 | { 33 | 34 | Memcheck:Cond 35 | fun:_ZN10wasmparser6parser6Parser12parse_reader17h* 36 | } 37 | { 38 | 39 | Memcheck:Cond 40 | fun:_ZN10wasmparser6parser6Parser5parse17h* 41 | } 42 | { 43 | 44 | Memcheck:Leak 45 | match-leak-kinds: definite 46 | fun:malloc 47 | ... 48 | fun:_ZN6wasmer3sys8instance8Instance12new_by_index17h9b11b6b5fcb57319E 49 | fun:wasm_instance_new 50 | } 51 | { 52 | 53 | Memcheck:Leak 54 | match-leak-kinds: possible 55 | fun:calloc 56 | ... 57 | fun:_ZN6wasmer3sys6module6Module11from_binary17h0e63bedfc82f5d11E 58 | fun:wasm_module_new 59 | } 60 | --------------------------------------------------------------------------------