diff --git a/.gitignore b/.gitignore
index 7caf82f..b4501df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,8 @@
 *.crt
 *.key
 settings.test
+__pycache__/*
+*.pyc
 
 # User-specific stuff
 .idea/**/workspace.xml
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..874e82f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "common/awssig"]
+	path = common/awssig
+	url = git@github.com:nginx-serverless/nginx-aws-signature.git
diff --git a/Dockerfile.buildkit.plus b/Dockerfile.buildkit.plus
deleted file mode 100644
index 8e95af1..0000000
--- a/Dockerfile.buildkit.plus
+++ /dev/null
@@ -1,77 +0,0 @@
-FROM debian:bullseye-slim
-
-ENV NGINX_PLUS_VERSION   28-1
-ENV NGINX_VERSION        1.23.2
-ENV NJS_VERSION          28+0.7.10-1
-ENV XSLT_VERSION         28-1
-
-ENV PROXY_CACHE_VALID_OK "1h"
-ENV PROXY_CACHE_VALID_NOTFOUND "1m"
-ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
-
-ENV PROXY_CACHE_VALID_OK "1h"
-ENV PROXY_CACHE_VALID_NOTFOUND "1m"
-ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
-ENV CORS_ENABLED 0
-
-COPY plus/usr /usr
-
-# Copy files from the OSS NGINX Docker container such that the container
-# startup is the same.
-# Source: https://github.com/nginxinc/docker-nginx/tree/1.19.2/stable/buster
-COPY common/docker-entrypoint.sh /docker-entrypoint.sh
-COPY common/docker-entrypoint.d /docker-entrypoint.d/
-COPY plus/docker-entrypoint.d /docker-entrypoint.d/
-# Add NGINX Plus package repository keyring
-COPY plus/usr/share/keyrings/nginx-archive-keyring.gpg /usr/share/keyrings/nginx-archive-keyring.gpg
-
-RUN --mount=type=secret,id=nginx-crt --mount=type=secret,id=nginx-key \
-    set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    mkdir -p /etc/ssl/nginx; \
-    cp /run/secrets/nginx-crt /etc/ssl/nginx/nginx-repo.crt; \
-    chmod 0664 /etc/ssl/nginx/nginx-repo.crt; \
-    cp /run/secrets/nginx-key /etc/ssl/nginx/nginx-repo.key; \
-    chmod 0664 /etc/ssl/nginx/nginx-repo.key; \
-    # create nginx user/group first, to be consistent throughout docker variants
-    addgroup --system --gid 101 nginx; \
-    adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx; \
-    apt-get -qq update; \
-    apt-get -qq upgrade --yes; \
-    apt-get -qq install --yes ca-certificates; \
-    sh -a /usr/local/bin/add_nginx_plus_repo.sh; \
-    rm /usr/local/bin/add_nginx_plus_repo.sh; \
-    apt-get -qq update; \
-    export DISTRO_VERSION="$(grep '^VERSION_CODENAME=' /etc/os-release | awk -v FS='=' '{print $2}')" && \
-    apt-get -qq install --no-install-recommends --no-install-suggests -y \
-        nginx-plus=${NGINX_PLUS_VERSION}~${DISTRO_VERSION} \
-        nginx-plus-module-njs=${NJS_VERSION}~${DISTRO_VERSION} \
-        nginx-plus-module-xslt=${XSLT_VERSION}~${DISTRO_VERSION} \
-        gettext-base; \
-    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
-    rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/* /etc/ssl/nginx; \
-    # forward request and error logs to docker log collector
-    ln -sf /dev/stdout /var/log/nginx/access.log; \
-    ln -sf /dev/stderr /var/log/nginx/error.log; \
-    chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh
-
-ENTRYPOINT ["/docker-entrypoint.sh"]
-
-EXPOSE 80
-
-STOPSIGNAL SIGTERM
-
-CMD ["nginx", "-g", "daemon off;"]
-
-# NGINX Docker image setup complete, everything below is specific for
-# the S3 Gateway use case.
-
-COPY plus/etc/nginx /etc/nginx
-COPY common/etc /etc
-COPY common/docker-entrypoint.d/00-check-for-required-env.sh /docker-entrypoint.d/00-check-for-required-env.sh
-
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    mkdir -p /var/cache/nginx/s3_proxy; \
-    chown nginx:nginx /var/cache/nginx/s3_proxy; \
-    chmod -R +x /docker-entrypoint.d/*
diff --git a/Dockerfile.latest-njs b/Dockerfile.latest-njs
deleted file mode 100644
index cfb802f..0000000
--- a/Dockerfile.latest-njs
+++ /dev/null
@@ -1,49 +0,0 @@
-# This container image removes the existing njs package from the inherited image
-# (which could be OSS NGINX or NGINX Plus), builds njs from the latest
-# source, and installs it.
-FROM nginx-s3-gateway
-
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive;  \
-    apt-get update -qq; \
-    apt-get install --no-install-recommends --no-install-suggests --yes make gcc libc6-dev curl expect libpcre2-dev libpcre3-dev libedit-dev libreadline-dev libssl-dev libpcre2-posix2 libxml2-dev libxslt1-dev; \
-    mkdir -p /tmp/nginx /tmp/njs-latest; \
-    curl --retry 6 --location "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" \
-        | gunzip | tar --extract --strip-components=1 --directory /tmp/nginx; \
-    curl --retry 6 --location 'https://hg.nginx.org/njs/archive/tip.tar.gz' \
-        | gunzip | tar --extract --strip-components=1 --directory /tmp/njs-latest; \
-    cd /tmp/njs-latest; \
-    ./configure; \
-    make -j "$(nproc)"; \
-    cp build/njs /usr/bin/njs; \
-    cd /tmp/nginx; \
-    ./configure \
-        --add-dynamic-module=/tmp/njs-latest/nginx \
-        --without-http_gzip_module \
-        --without-http_rewrite_module \
-        --prefix=/etc/nginx \
-        --sbin-path=/usr/sbin/nginx \
-        --modules-path=/usr/lib/nginx/modules \
-        --conf-path=/etc/nginx/nginx.conf \
-        --error-log-path=/var/log/nginx/error.log \
-        --http-log-path=/var/log/nginx/access.log \
-        --pid-path=/var/run/nginx.pid \
-        --lock-path=/var/run/nginx.lock \
-        --http-client-body-temp-path=/var/cache/nginx/client_temp \
-        --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
-        --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
-        --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
-        --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
-        --user=nginx --group=nginx --with-compat --with-file-aio \
-        --with-stream \
-        --with-mail \
-        --with-threads \
-        --with-compat \
-        --with-cc-opt="-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-${NGINX_VERSION}/debian/debuild-base/nginx-${NGINX_VERSION}=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC"; \
-    make -j "$(nproc)"; \
-    cp objs/ngx_stream_js_module.so /usr/lib/nginx/modules; \
-    cp objs/ngx_http_js_module.so /usr/lib/nginx/modules; \
-    apt-get purge --yes --auto-remove make gcc libc6-dev expect libpcre2-dev libpcre3-dev libedit-dev libreadline-dev libssl-dev; \
-    rm -rf \
-      /var/lib/apt/lists/* \
-      /tmp/*
diff --git a/Dockerfile.oss b/Dockerfile.oss
deleted file mode 100644
index 393a713..0000000
--- a/Dockerfile.oss
+++ /dev/null
@@ -1,35 +0,0 @@
-FROM nginx:1.23.3
-
-ENV NGINX_VERSION "1.23.3"
-ENV NJS_VERSION   0.7.10
-
-ENV PROXY_CACHE_VALID_OK "1h"
-ENV PROXY_CACHE_VALID_NOTFOUND "1m"
-ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
-ENV CORS_ENABLED 0
-
-# We modify the nginx base image by:
-# 1. Adding configuration files needed for proxying private S3 buckets
-# 2. Adding a directory for proxied objects to be stored
-# 3. Replacing the entrypoint script with a modified version that explicitly
-#    sets resolvers.
-# 4. Explicitly install the version of njs coded in the environment variable
-#    above.
-
-COPY common/etc /etc
-COPY common/docker-entrypoint.sh /docker-entrypoint.sh
-COPY common/docker-entrypoint.d /docker-entrypoint.d/
-COPY oss/etc /etc
-
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    mkdir -p /var/cache/nginx/s3_proxy; \
-    chown nginx:nginx /var/cache/nginx/s3_proxy; \
-    chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh; \
-    echo "deb https://nginx.org/packages/mainline/debian/ $(echo $PKG_RELEASE | cut -f2 -d~) nginx" >> /etc/apt/sources.list.d/nginx.list; \
-    apt-get update; \
-    apt-get install --no-install-recommends --no-install-suggests --yes \
-      curl nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE}; \
-    apt-get remove --purge --auto-remove --yes; \
-    rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list
-
diff --git a/Dockerfile.plus b/Dockerfile.plus
deleted file mode 100644
index 230f52b..0000000
--- a/Dockerfile.plus
+++ /dev/null
@@ -1,67 +0,0 @@
-FROM debian:bullseye-slim
-
-ENV NGINX_PLUS_VERSION   28-1
-ENV NGINX_VERSION        1.23.2
-ENV NJS_VERSION          28+0.7.10-1
-ENV XSLT_VERSION         28-1
-
-ENV PROXY_CACHE_VALID_OK "1h"
-ENV PROXY_CACHE_VALID_NOTFOUND "1m"
-ENV PROXY_CACHE_VALID_FORBIDDEN "30s"
-ENV CORS_ENABLED 0
-
-COPY plus/etc/ssl /etc/ssl
-COPY plus/usr /usr
-
-# Copy files from the OSS NGINX Docker container such that the container
-# startup is the same.
-COPY common/docker-entrypoint.sh /docker-entrypoint.sh
-COPY common/docker-entrypoint.d /docker-entrypoint.d/
-COPY plus/docker-entrypoint.d /docker-entrypoint.d/
-# Add NGINX Plus package repository keyring
-COPY plus/usr/share/keyrings/nginx-archive-keyring.gpg /usr/share/keyrings/nginx-archive-keyring.gpg
-
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    # create nginx user/group first, to be consistent throughout docker variants
-    addgroup --system --gid 101 nginx; \
-    adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx; \
-    apt-get -qq update; \
-    apt-get -qq upgrade --yes; \
-    apt-get -qq install --yes ca-certificates curl; \
-    sh -a /usr/local/bin/add_nginx_plus_repo.sh; \
-    rm /usr/local/bin/add_nginx_plus_repo.sh; \
-    apt-get -qq update; \
-    export DISTRO_VERSION="$(grep '^VERSION_CODENAME=' /etc/os-release | awk -v FS='=' '{print $2}')" && \
-    apt-get -qq install --yes --no-install-recommends --no-install-suggests \
-        nginx-plus=${NGINX_PLUS_VERSION}~${DISTRO_VERSION} \
-        nginx-plus-module-njs=${NJS_VERSION}~${DISTRO_VERSION} \
-        nginx-plus-module-xslt=${XSLT_VERSION}~${DISTRO_VERSION} \
-        gettext-base; \
-    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
-    rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*; \
-    # forward request and error logs to docker log collector
-    ln -sf /dev/stdout /var/log/nginx/access.log; \
-    ln -sf /dev/stderr /var/log/nginx/error.log; \
-    chmod -R -v +x /docker-entrypoint.sh /docker-entrypoint.d/*.sh
-
-ENTRYPOINT ["/docker-entrypoint.sh"]
-
-EXPOSE 80
-
-STOPSIGNAL SIGTERM
-
-CMD ["nginx", "-g", "daemon off;"]
-
-# NGINX Docker image setup complete, everything below is specific for
-# the S3 Gateway use case.
-
-COPY plus/etc/nginx /etc/nginx
-COPY common/etc /etc
-COPY common/docker-entrypoint.d/00-check-for-required-env.sh /docker-entrypoint.d/00-check-for-required-env.sh
-
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    mkdir -p /var/cache/nginx/s3_proxy; \
-    chown nginx:nginx /var/cache/nginx/s3_proxy; \
-    chmod -R +x /docker-entrypoint.d/*
diff --git a/Dockerfile.unprivileged b/Dockerfile.unprivileged
deleted file mode 100644
index 5ec85db..0000000
--- a/Dockerfile.unprivileged
+++ /dev/null
@@ -1,21 +0,0 @@
-# This container images makes the necessary modifications in the
-# inherited image (which could be OSS NGINX or NGINX Plus) in order
-# to allow running NGINX S3 Gateway as a non root user.
-# Steps are based on the official unprivileged container:
-# https://github.com/nginxinc/docker-nginx-unprivileged/blob/main/Dockerfile-debian.template
-FROM nginx-s3-gateway
-
-# Implement changes required to run NGINX as an unprivileged user
-RUN sed -i "/^server {/a \    listen       8080;" /etc/nginx/templates/default.conf.template \
-    && sed -i '/user  nginx;/d' /etc/nginx/nginx.conf \
-    && sed -i 's,/var/run/nginx.pid,/tmp/nginx.pid,' /etc/nginx/nginx.conf \
-    && sed -i "/^http {/a \    proxy_temp_path /tmp/proxy_temp;\n    client_body_temp_path /tmp/client_temp;\n    fastcgi_temp_path /tmp/fastcgi_temp;\n    uwsgi_temp_path /tmp/uwsgi_temp;\n    scgi_temp_path /tmp/scgi_temp;\n" /etc/nginx/nginx.conf \
-# Nginx user must own the cache and etc directory to write cache and tweak the nginx config
-    && chown -R nginx:0 /var/cache/nginx \
-    && chmod -R g+w /var/cache/nginx \
-    && chown -R nginx:0 /etc/nginx \
-    && chmod -R g+w /etc/nginx
-
-EXPOSE 8080
-
-USER nginx
diff --git a/GNUmakefile.old b/GNUmakefile.old
deleted file mode 100644
index 8efeb48..0000000
--- a/GNUmakefile.old
+++ /dev/null
@@ -1,24 +0,0 @@
-MAKE_MAJOR_VER    := $(shell echo $(MAKE_VERSION) | cut -d'.' -f1)
-
-ifneq ($(shell test $(MAKE_MAJOR_VER) -gt 3; echo $$?),0)
-$(error Make version $(MAKE_VERSION) is not supported, please install GNU Make 4.x)
-endif
-
-AWK               ?= $(shell command -v gawk 2> /dev/null || command -v awk 2> /dev/null)
-
-Q = $(if $(filter 1,$V),,@)
-M = $(shell printf "\033[34;1m▶\033[0m")
-
-# Use docker based commitsar if it isn't in the path
-ifeq ($(COMMITSAR),)
-	COMMITSAR = $(COMMITSAR_DOCKER)
-endif
-
-.PHONY: help
-help:
-	@grep --no-filename -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
-		$(AWK) 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-28s\033[0m %s\n", $$1, $$2}' | sort
-
-.PHONY: test
-test: ## Run all tests
-	$Q $(CURDIR)/test.sh --type oss --unprivileged false --latest-njs false
diff --git a/Makefile b/Makefile
index eb74059..14f2b8e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,24 @@
-.PHONY: submodule start-plus start watch down clean clean-cache unit-test functional-test test
-.DEFAULT_GOAL := help
-
-PYTHONPATH=$(PWD)/services/nginx-quota-limiter
-export PYTHONPATH
+submodule:
+	git submodule update --init common/awssig
+	git submodule absorbgitdirs
+	git -C common/awssig config core.sparseCheckout true
+	echo 'core/*' >>.git/modules/common/awssig/info/sparse-checkout
+	git submodule update --force --checkout common/awssig
 
-UNIT_TEST_PATH=$(PYTHONPATH)/test/unit
-export UNIT_TEST_PATH
+start:
+	docker-compose up -d
 
-FUNCTIONAL_TEST_PATH=$(PYTHONPATH)/test/functional
-export FUNCTIONAL_TEST_PATH
+start-01:
+	docker-compose -f examples/01-all-lambda-function-arns/docker-compose.yml up -d
 
-INTEGRATION_TEST_PATH=$(PYTHONPATH)/test/integration
-export INTEGRATION_TEST_PATH
+start-02:
+	docker-compose -f examples/02-one-lambda-function-arn/docker-compose.yml up -d
 
-submodule:
-	git submodule update --init --recursive
-	git submodule foreach 'git fetch origin; git checkout $$(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
+start-03:
+	docker-compose -f examples/03-one-lambda-function-url/docker-compose.yml up -d
 
-start-plus:
-	# docker build --file Dockerfile.plus --tag nginx-plus-s3-test --tag nginx-plus-s3-test:plus .
-	# docker run --env-file ./settings.test --publish 81:80 --name nginx-plus-s3-test nginx-plus-s3-test:plus
-
-start:
-	docker-compose up -d
+start-04:
+	docker-compose -f examples/04-lambda-function-arn-url/docker-compose.yml up -d
 
 ps:
 	docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Names}}"
@@ -33,29 +29,19 @@ watch:
 down:
 	docker-compose down
 
-clean: 
-	docker kill $$(docker ps -q) 2> /dev/null || true
-	docker system prune -a
-	docker volume rm $(docker volume ls -qf dangling=true)
-
-clean-cache:
-	find . -type d -name __pycache__ -exec rm -r {} \+
-	find . -type d -name .cache -exec rm -r {} \+
-	find . -type d -name .pytest_cache -exec rm -r {} \+
-
-lint:
-	@flake8
+down-01:
+	docker-compose -f examples/01-all-lambda-function-arns/docker-compose.yml down
 
-unit-test:
-	pytest $(UNIT_TEST_PATH)
+down-02:
+	docker-compose -f examples/02-one-lambda-function-arn/docker-compose.yml down
 
-functional-test:
-	bash $(FUNCTIONAL_TEST_PATH)/run_test.sh
+down-03:
+	docker-compose -f examples/03-one-lambda-function-url/docker-compose.yml down
 
-integration-test:
-	bash $(INTEGRATION_TEST_PATH)/run_test.sh
+down-04:
+	docker-compose -f examples/04-lambda-function-arn-url/docker-compose.yml down
 
-test:
-	pytest $(UNIT_TEST_PATH)
-	bash $(FUNCTIONAL_TEST_PATH)/run_test.sh
-	bash $(INTEGRATION_TEST_PATH)/run_test.sh
+clean: 
+	docker kill $$(docker ps -q) 2> /dev/null || true
+	docker system prune -a
+	docker volume rm $(docker volume ls -qf dangling=true)
diff --git a/README.md b/README.md
index d3e33db..b7ed681 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,78 @@
-<!-- [![CI](https://github.com/nginxinc/nginx-s3-gateway/actions/workflows/main.yml/badge.svg)](https://github.com/nginxinc/nginx-s3-gateway/actions/workflows/main.yml) ![Docker Pulls](https://img.shields.io/docker/pulls/nginxinc/nginx-s3-gateway?style=plastic) -->
-
 # NGINX Lambda Gateway
 
 ## Introduction
 
+This project provides a working configuration of NGINX configured to act as an authenticating gateway for the AWS Lambda service. This allows you to proxy a private Lambda function without requiring users to authenticate to it via AWS signature. 
+
+![](./docs/img/nginx-lambda-gateway-intro.png)
+
+Within the proxy layer of `nginx-lambda-gateway`, additional functionality can be configured such as:
+
+- Providing an AWS signature based authentication gateway using an alternative authentication
+   system to AWS Lambda functions
+- For internal/micro services that can't authenticate against the AWS Lambda functions
+   (e.g. don't have libraries available) the gateway can provide a means
+   to accessing Lambda functions without authentication
+- Protecting Lambda functions from arbitrary public access
+- For internal/micro services that can't authenticate against the AWS Lambda functions
+- [Rate limiting](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html) AWS Lambda functions
+- Authenticating users to authorize AWS Lambda functions with a [OIDC](https://github.com/nginx-openid-connect)
+- Protecting AWS Lambda functions with a [WAF](https://docs.nginx.com/nginx-waf/)
+
+
 ## Getting Started
 
-Refer to the [Getting Started Guide](docs/getting_started.md) for how to build
-and run the gateway.
+Refer to the [Getting Started Guide](docs/getting_started.md) for how to build and run the gateway.
 
 ## Directory Structure and File Descriptions
 
+```
+nginx-lambda-gateway
+│
+├── common
+│   ├── etc
+│   │   ├── nginx                   default nginx-lambda-gateway configuration
+│   │   └── ssl                     contains certificates and NGINX Plus license
+│   ├── lambda-core
+│   │   ├── awscredentials.js       common lib to read and write AWS credentials
+│   │   ├── awssig2.js              common lib to build AWS signature v2
+│   │   ├── awssig4.js              common lib to build AWS signature v4
+│   │   ├── lambdagateway.js        common lib to integrate the Lambda from NGINX
+│   │   ├── lambda_ngx_apis.conf    API endpoints config for nginx-lambda-gateway
+│   │   ├── lambda_ngx_http.conf    common config under NGINX http directive
+│   │   ├── lambda_ngx_proxy.conf   common config to be set before proxy_pass
+│   │   └── utils.js                common lib to be reused by all NJS codebase
+│   └── lambda-emulator             proxy for Lambda Runtime API to locally test
+│
+├── docker
+│   ├── Dockerfile.oss              for NGINX OSS  to act as a Lambda gateway
+│   └── Dockerfile.plus             for NGINX Plus to act as a Lambda gateway
+│
+├── docker-compose.yml              Docker config to build and run nginx-lambda-gateway
+├── settings.env                    Docker env file
+│
+├── docs                            contains documentation about the project
+│
+├── examples
+│   ├── 01-all-lambda-function-arns NGINX proxy to all Lambda function ARNs
+│   ├── 02-one-lambda-function-arn  NGINX proxy to one Lambda function ARN
+│   ├── 03-one-lambda-function-url  NGINX proxy to one Lambda function URL
+│   └── 04-lambda-function-arn-url  NGINX proxy to both of Lambda function ARN and URL
+│
+├── tests                           test launcher and unit/integration test codebase
+│
+└── Makefile                        automate to build/start/stop nginx-lambda-gateway
+```
 
 ## Development
 
-Refer to the [Development Guide](docs/development.md) for more information about
-extending or testing the gateway.
+Refer to the [Development Guide](docs/development.md) for more information about extending or testing the gateway.
 
 ## License
 
 All code include is licensed under the [Apache 2.0 license](LICENSE.txt).
+
+## Inspired Projects
+- [NGINX S3 Gateway](https://github.com/nginxinc/nginx-s3-gateway)
+- [NGINX AWS Signature](https://github.com/nginxinc/nginx-aws-signature)
+- [NGINX OIDC Core and IAM Integration Examples](https://github.com/nginx-openid-connect)
diff --git a/common/awssig b/common/awssig
new file mode 160000
index 0000000..9e9ff39
--- /dev/null
+++ b/common/awssig
@@ -0,0 +1 @@
+Subproject commit 9e9ff393e29adf3bf4615dfeec9811eb4ed6b683
diff --git a/common/docker-entrypoint.d/00-check-for-required-env.sh b/common/docker-entrypoint.d/00-check-for-required-env.sh
deleted file mode 100755
index 0492051..0000000
--- a/common/docker-entrypoint.d/00-check-for-required-env.sh
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env bash
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-# This script checks to see that required environment variables were correctly
-# passed into the Docker container.
-
-set -e
-
-failed=0
-
-required=("S3_BUCKET_NAME" "S3_SERVER" "S3_SERVER_PORT" "S3_SERVER_PROTO"
-"S3_REGION" "S3_STYLE" "ALLOW_DIRECTORY_LIST" "AWS_SIGS_VERSION"
-"CORS_ENABLED")
-
-# Require some form of authentication to be configured.
-
-# a) Using container credentials. This is indicated by AWS_CONTAINER_CREDENTIALS_RELATIVE_URI being set.
-#    See https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html
-#    Example: We are running inside an ECS task.
-if [[ -v AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ]]; then
-  echo "Running inside an ECS task, using container credentials"
-
-# b) Using Instance Metadata Service (IMDS) credentials, if IMDS is present at http://169.254.169.254.
-#    See https://docs.aws.amazon.com/sdkref/latest/guide/feature-imds-credentials.html.
-#    Example: We are running inside an EC2 instance.
-elif curl --output /dev/null --silent --head --fail --connect-timeout 2 --max-time 5 "http://169.254.169.254"; then
-  echo "Running inside an EC2 instance, using IMDS for credentials"
-
-# c) Using assume role credentials. This is indicated by AWS_WEB_IDENTITY_TOKEN_FILE being set.
-#    See https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html.
-#    Example: We are running inside an EKS cluster with IAM roles for service accounts enabled.
-elif [[ -v AWS_WEB_IDENTITY_TOKEN_FILE ]]; then
-  echo "Running inside EKS with IAM roles for service accounts"
-
-# If none of the options above is used, require static credentials.
-# See https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html.
-else
-  required+=("AWS_ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY")
-fi
-
-if [[ -v AWS_SESSION_TOKEN ]]; then
-  echo "S3 Session token present"
-fi
-
-for name in ${required[@]}; do
-  if [[ ! -v name ]]; then
-      >&2 echo "Required ${name} environment variable missing"
-      failed=1
-  fi
-done
-
-if [ "${S3_SERVER_PROTO}" != "http" ] && [ "${S3_SERVER_PROTO}" != "https" ]; then
-    >&2 echo "S3_SERVER_PROTO contains an invalid value (${S3_SERVER_PROTO}). Valid values: http, https"
-    failed=1
-fi
-
-if [ "${AWS_SIGS_VERSION}" != "2" ] && [ "${AWS_SIGS_VERSION}" != "4" ]; then
-  >&2 echo "AWS_SIGS_VERSION contains an invalid value (${AWS_SIGS_VERSION}). Valid values: 2, 4"
-  failed=1
-fi
-
-parseBoolean() {
-  case "$1" in
-    TRUE | true | True | YES | Yes | 1)
-      echo 1
-      ;;
-    *)
-      echo 0
-      ;;
-  esac
-}
-
-if [ "$(parseBoolean ${ALLOW_DIRECTORY_LIST})" == "1" ] && [ "$(parseBoolean ${PROVIDE_INDEX_PAGE})" == "1" ]; then
-  >&2 echo "ALLOW_DIRECTORY_LIST and PROVIDE_INDEX_PAGE cannot be both set"
-  failed=1
-fi
-
-if [ -n "${HEADER_PREFIXES_TO_STRIP+x}" ]; then
-  if [[ "${HEADER_PREFIXES_TO_STRIP}" =~ [A-Z] ]]; then
-    >&2 echo "HEADER_PREFIXES_TO_STRIP must not contain uppercase characters"
-    failed=1
-  fi
-fi
-
-
-if [ $failed -gt 0 ]; then
-  exit 1
-fi
-
-echo "S3 Backend Environment"
-echo "Access Key ID: ${AWS_ACCESS_KEY_ID}"
-echo "Origin: ${S3_SERVER_PROTO}://${S3_BUCKET_NAME}.${S3_SERVER}:${S3_SERVER_PORT}"
-echo "Region: ${S3_REGION}"
-echo "Addressing Style: ${S3_STYLE}"
-echo "AWS Signatures Version: v${AWS_SIGS_VERSION}"
-echo "DNS Resolvers: ${DNS_RESOLVERS}"
-echo "Directory Listing Enabled: ${ALLOW_DIRECTORY_LIST}"
-echo "Provide Index Pages Enabled: ${PROVIDE_INDEX_PAGE}"
-echo "Append slash for directory enabled: ${APPEND_SLASH_FOR_POSSIBLE_DIRECTORY}"
-echo "Stripping the following headers from responses: x-amz-;${HEADER_PREFIXES_TO_STRIP}"
-echo "CORS Enabled: ${CORS_ENABLED}"
diff --git a/common/docker-entrypoint.d/22-enable_js_fetch_trusted_certificate.sh b/common/docker-entrypoint.d/22-enable_js_fetch_trusted_certificate.sh
deleted file mode 100755
index 9535abb..0000000
--- a/common/docker-entrypoint.d/22-enable_js_fetch_trusted_certificate.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-#  Copyright 2022 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-set -e
-
-if [ -f /etc/nginx/conf.d/gateway/js_fetch_trusted_certificate.conf ] && [ -n "${JS_TRUSTED_CERT_PATH+x}" ]; then
-  if [ ! -f "${JS_TRUSTED_CERT_PATH}" ]; then
-    >&2 echo "JS_TRUSTED_CERT_PATH environment variable error: no file found at the path: ${JS_TRUSTED_CERT_PATH}"
-    exit 1
-  fi
-
-  echo "js_fetch_trusted_certificate ${JS_TRUSTED_CERT_PATH};" >> /etc/nginx/conf.d/gateway/js_fetch_trusted_certificate.conf
-  echo "Enabling js_fetch_trusted_certificate ${JS_TRUSTED_CERT_PATH}"
-fi
diff --git a/common/docker-entrypoint.sh b/common/docker-entrypoint.sh
deleted file mode 100644
index 024d0aa..0000000
--- a/common/docker-entrypoint.sh
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env bash
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-# vim:sw=4:ts=4:et
-
-set -e
-
-parseBoolean() {
-  case "$1" in
-    TRUE | true | True | YES | Yes | 1)
-      echo 1
-      ;;
-    *)
-      echo 0
-      ;;
-  esac
-}
-
-# This line is an addition to the NGINX Docker image's entrypoint script.
-if [ -z ${DNS_RESOLVERS+x} ]; then
-  resolvers=""
-  for ip in $(grep nameserver /etc/resolv.conf | cut -d' ' -f2 | xargs)
-  do
-    if echo "${ip}" | grep -q ':'; then
-      resolvers="$resolvers [${ip}]"
-    else
-      resolvers="$resolvers $ip"
-    fi
-  done
-  export DNS_RESOLVERS="${resolvers}"
-fi
-
-# Normalize the CORS_ENABLED environment variable to a numeric value
-# so that it can be easily parsed in the nginx configuration.
-export CORS_ENABLED="$(parseBoolean "${CORS_ENABLED}")"
-
-# By enabling CORS, we also need to enable the OPTIONS method which
-# is not normally used as part of the gateway. The following variable
-# defines the set of acceptable headers.
-if [ "${CORS_ENABLED}" == "1" ]; then
-  export LIMIT_METHODS_TO="GET HEAD OPTIONS"
-  export LIMIT_METHODS_TO_CSV="GET, HEAD, OPTIONS"
-else
-  export LIMIT_METHODS_TO="GET HEAD"
-  export LIMIT_METHODS_TO_CSV="GET, HEAD"
-fi
-
-if [ -z "${CORS_ALLOWED_ORIGIN+x}" ]; then
-  export CORS_ALLOWED_ORIGIN="*"
-fi
-
-# Nothing is modified under this line
-
-if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
-    exec 3>&1
-else
-    exec 3>/dev/null
-fi
-
-if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
-    if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
-        echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"
-
-        echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
-        find "/docker-entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do
-            case "$f" in
-                *.sh)
-                    if [ -x "$f" ]; then
-                        echo >&3 "$0: Launching $f";
-                        "$f"
-                    else
-                        # warn on shell scripts without exec bit
-                        echo >&3 "$0: Ignoring $f, not executable";
-                    fi
-                    ;;
-                *) echo >&3 "$0: Ignoring $f";;
-            esac
-        done
-
-        echo >&3 "$0: Configuration complete; ready for start up"
-    else
-        echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
-    fi
-fi
-
-exec "$@"
diff --git a/common/etc/nginx/conf.d/nginx_lambda_gateway.conf b/common/etc/nginx/conf.d/nginx_lambda_gateway.conf
new file mode 100644
index 0000000..aa2ec69
--- /dev/null
+++ b/common/etc/nginx/conf.d/nginx_lambda_gateway.conf
@@ -0,0 +1,52 @@
+include "serverless/lambda_ngx_http.conf";
+
+map $request_uri $lambda_host {
+    # Use default host ($lambdaFunctionARNHost) when using one region for
+    # multiple Lambda Function ARNs per NGINX Lambda Gateway.
+    default $lambdaFunctionARNHost;
+
+    # Add default host per endpoint when using multiple regions for
+    # multiple Lambda Function ARNs per NGINX Lambda Gateway.
+    # '/2015-03-31/functions/foo/invocations' $lambdaFunctionARNHost;
+
+    # Add the following host with ediging {url_id} and {aws-region} per endpoint
+    # when using AWS Lambda Function URL
+    # '/bar' {url-id}.lambda-url.{aws-region}.on.aws;
+}
+
+map $request_uri $lambda_url {
+    # Use default Lambda server URL when using AWS Lambda Function ARN.
+    default  $lambdaProto://$lambda_host:$lambdaPort;
+
+    # Add Lambda server URL per endpoint when using AWS Lambda Function URL.
+    # '/bar' $lambdaProto://$lambda_host/;
+}
+
+server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Example of a proxy to all of the AWS Lambda Function ARNs.
+    location / {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Add this config per endpoint when using a proxy to a Lambda Function ARN.
+    # - arn:aws:lambda:{aws-region}:{account-id}:function:foo
+    # location /2015-03-31/functions/foo/invocations {
+    #     auth_request /aws/credentials/retrieval;
+    #     js_content lambdagateway.redirectToLambdaFunctionARN;
+    # }
+
+    # Add this config per endpoint when using a proxy to a Lambda Function URL.
+    # - https://{url-id}.lambda-url.{aws-region}.on.aws/
+    # location /bar {
+    #     auth_request /aws/credentials/retrieval;
+    #     js_content lambdagateway.redirectToLambdaFunctionURL;
+    # }
+
+    # Enable when debugging is needed
+    error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    access_log /var/log/nginx/access.log main;
+}
diff --git a/common/etc/nginx/include/awscredentials.js b/common/etc/nginx/include/awscredentials.js
deleted file mode 100644
index 2a708fa..0000000
--- a/common/etc/nginx/include/awscredentials.js
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import utils from "./utils.js";
-
-const fs = require('fs');
-
-/**
- * The current moment as a timestamp. This timestamp will be used across
- * functions in order for there to be no variations in signatures.
- * @type {Date}
- */
-const NOW = new Date();
-
-/**
- * Constant base URI to fetch credentials together with the credentials relative URI, see
- * https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html for more details.
- * @type {string}
- */
-const ECS_CREDENTIAL_BASE_URI = 'http://169.254.170.2';
-
-/**
- * @type {string}
- */
-const EC2_IMDS_TOKEN_ENDPOINT = 'http://169.254.169.254/latest/api/token';
-
-const EC2_IMDS_SECURITY_CREDENTIALS_ENDPOINT = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/';
-
-/**
- * Offset to the expiration of credentials, when they should be considered expired and refreshed. The maximum
- * time here can be 5 minutes, the IMDS and ECS credentials endpoint will make sure that each returned set of credentials
- * is valid for at least another 5 minutes.
- *
- * To make sure we always refresh the credentials instead of retrieving the same again, keep credentials until 4:30 minutes
- * before they really expire.
- *
- * @type {number}
- */
-const maxValidityOffsetMs = 4.5 * 60 * 1000;
-
-
-/**
- * Get the current session token from either the instance profile credential 
- * cache or environment variables.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} current session token or empty string
- */
-function sessionToken(r) {
-    const credentials = readCredentials(r);
-    if (credentials.sessionToken) {
-        return credentials.sessionToken;
-    }
-    return '';
-}
-
-/**
- * Get the instance profile credentials needed to authenticated against S3 from
- * a backend cache. If the credentials cannot be found, then return undefined.
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {undefined|{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string|null), expiration: (string|null)}} AWS instance profile credentials or undefined
- */
-function readCredentials(r) {
-    // TODO: Change the generic constants naming for multiple AWS services.
-    if ('AWS_ACCESS_KEY_ID' in process.env && 'AWS_SECRET_ACCESS_KEY' in process.env) {
-        const sessionToken = 'AWS_SESSION_TOKEN' in process.env ?
-                              process.env['AWS_SESSION_TOKEN'] : null;
-        return {
-            accessKeyId: process.env['AWS_ACCESS_KEY_ID'],
-            secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],
-            sessionToken: sessionToken,
-            expiration: null
-        };
-    }
-
-    if ("variables" in r && r.variables.cache_instance_credentials_enabled == 1) {
-        return _readCredentialsFromKeyValStore(r);
-    } else {
-        return _readCredentialsFromFile();
-    }
-}
-
-/**
- * Read credentials from the NGINX Keyval store. If it is not found, then
- * return undefined.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {undefined|{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}} AWS instance profile credentials or undefined
- * @private
- */
-function _readCredentialsFromKeyValStore(r) {
-    const cached = r.variables.instance_credential_json;
-
-    if (!cached) {
-        return undefined;
-    }
-
-    try {
-        return JSON.parse(cached);
-    } catch (e) {
-        utils.debug_log(r, `Error parsing JSON value from r.variables.instance_credential_json: ${e}`);
-        return undefined;
-    }
-}
-
-/**
- * Read the contents of the credentials file into memory. If it is not
- * found, then return undefined.
- *
- * @returns {undefined|{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}} AWS instance profile credentials or undefined
- * @private
- */
-function _readCredentialsFromFile() {
-    const credsFilePath = _credentialsTempFile();
-
-    try {
-        const creds = fs.readFileSync(credsFilePath);
-        return JSON.parse(creds);
-    } catch (e) {
-        /* Do not throw an exception in the case of when the
-           credentials file path is invalid in order to signal to
-           the caller that such a file has not been created yet. */
-        if (e.code === 'ENOENT') {
-            return undefined;
-        }
-        throw e;
-    }
-}
-
-/**
- * Returns the path to the credentials temporary cache file.
- *
- * @returns {string} path on the file system to credentials cache file
- * @private
- */
-function _credentialsTempFile() {
-    if (process.env['AWS_CREDENTIALS_TEMP_FILE']) {
-        return process.env['AWS_CREDENTIALS_TEMP_FILE'];
-    }
-    if (process.env['TMPDIR']) {
-        return `${process.env['TMPDIR']}/credentials.json`
-    }
-
-    return '/tmp/credentials.json';
-}
-
-/**
- * Write the instance profile credentials to a caching backend.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @param credentials {{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}} AWS instance profile credentials
- */
-function writeCredentials(r, credentials) {
-    /* Do not bother writing credentials if we are running in a mode where we
-       do not need instance credentials. */
-    if (process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY']) {
-        return;
-    }
-
-    if (!credentials) {
-        throw `Cannot write invalid credentials: ${JSON.stringify(credentials)}`;
-    }
-
-    if ("variables" in r && r.variables.cache_instance_credentials_enabled == 1) {
-        _writeCredentialsToKeyValStore(r, credentials);
-    } else {
-        _writeCredentialsToFile(credentials);
-    }
-}
-
-/**
- * Write the instance profile credentials to the NGINX Keyval store.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @param credentials {{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}} AWS instance profile credentials
- * @private
- */
-function _writeCredentialsToKeyValStore(r, credentials) {
-    r.variables.instance_credential_json = JSON.stringify(credentials);
-}
-
-/**
- * Write the instance profile credentials to a file on the file system. This
- * file will be quite small and should end up in the file cache relatively
- * quickly if it is repeatedly read.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @param credentials {{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}} AWS instance profile credentials
- * @private
- */
-function _writeCredentialsToFile(credentials) {
-    fs.writeFileSync(_credentialsTempFile(), JSON.stringify(credentials));
-}
-
-/**
- * Get the credentials needed to create AWS signatures in order to authenticate
- * to S3. If the gateway is being provided credentials via a instance profile
- * credential as provided over the metadata endpoint, this function will:
- * 1. Try to read the credentials from cache
- * 2. Determine if the credentials are stale
- * 3. If the cached credentials are missing or stale, it gets new credentials
- *    from the metadata endpoint.
- * 4. If new credentials were pulled, it writes the credentials back to the
- *    cache.
- *
- * If the gateway is not using instance profile credentials, then this function
- * quickly exits.
- *
- * @param r {Request} HTTP request object
- * @returns {Promise<void>}
- */
-async function fetchCredentials(r) {
-    /* If we are not using an AWS instance profile to set our credentials we
-       exit quickly and don't write a credentials file. */
-    if (process.env['AWS_ACCESS_KEY_ID'] && process.env['AWS_SECRET_ACCESS_KEY']) {
-        r.return(200);
-        return;
-    }
-
-    let current;
-
-    try {
-        current = readCredentials(r);
-    } catch (e) {
-        utils.debug_log(r, `Could not read credentials: ${e}`);
-        r.return(500);
-        return;
-    }
-
-    if (current) {
-        // If AWS returns a Unix timestamp it will be in seconds, but in Date constructor we should provide timestamp in milliseconds
-        // In some situations (including EC2 and Fargate) current.expiration will be an RFC 3339 string - see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#instance-metadata-security-credentials
-        const expireAt = typeof current.expiration == 'number' ? current.expiration * 1000 : current.expiration
-        const exp = new Date(expireAt).getTime() - maxValidityOffsetMs;
-        if (NOW.getTime() < exp) {
-            r.return(200);
-            return;
-        }
-    }
-
-    let credentials;
-
-    utils.debug_log(r, 'Cached credentials are expired or not present, requesting new ones');
-
-    if (process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']) {
-        const uri = ECS_CREDENTIAL_BASE_URI + process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'];
-        try {
-            credentials = await _fetchEcsRoleCredentials(uri);
-        } catch (e) {
-            utils.debug_log(r, 'Could not load ECS task role credentials: ' + JSON.stringify(e));
-            r.return(500);
-            return;
-        }
-    }
-    else if(process.env['AWS_WEB_IDENTITY_TOKEN_FILE']) {
-        try {
-            credentials = await _fetchWebIdentityCredentials(r)
-        } catch(e) {
-            utils.debug_log(r, 'Could not assume role using web identity: ' + JSON.stringify(e));
-            r.return(500);
-            return;
-        }
-    } else {
-        try {
-            credentials = await _fetchEC2RoleCredentials();
-        } catch (e) {
-            utils.debug_log(r, 'Could not load EC2 task role credentials: ' + JSON.stringify(e));
-            r.return(500);
-            return;
-        }
-    }
-    try {
-        writeCredentials(r, credentials);
-    } catch (e) {
-        utils.debug_log(r, `Could not write credentials: ${e}`);
-        r.return(500);
-        return;
-    }
-    r.return(200);
-}
-
-/**
- * Get the credentials needed to generate AWS signatures from the ECS
- * (Elastic Container Service) metadata endpoint.
- *
- * @param credentialsUri {string} endpoint to get credentials from
- * @returns {Promise<{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}>}
- * @private
- */
-async function _fetchEcsRoleCredentials(credentialsUri) {
-    const resp = await ngx.fetch(credentialsUri);
-    if (!resp.ok) {
-        throw 'Credentials endpoint response was not ok.';
-    }
-    const creds = await resp.json();
-
-    return {
-        accessKeyId: creds.AccessKeyId,
-        secretAccessKey: creds.SecretAccessKey,
-        sessionToken: creds.Token,
-        expiration: creds.Expiration,
-    };
-}
-
-/**
- * Get the credentials needed to generate AWS signatures from the EC2
- * metadata endpoint.
- *
- * @returns {Promise<{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}>}
- * @private
- */
-async function _fetchEC2RoleCredentials() {
-    const tokenResp = await ngx.fetch(EC2_IMDS_TOKEN_ENDPOINT, {
-        headers: {
-            'x-aws-ec2-metadata-token-ttl-seconds': '21600',
-        },
-        method: 'PUT',
-    });
-    const token = await tokenResp.text();
-    let resp = await ngx.fetch(EC2_IMDS_SECURITY_CREDENTIALS_ENDPOINT, {
-        headers: {
-            'x-aws-ec2-metadata-token': token,
-        },
-    });
-    /* This _might_ get multiple possible roles in other scenarios, however,
-       EC2 supports attaching one role only.It should therefore be safe to take
-       the whole output, even given IMDS _might_ (?) be able to return multiple
-       roles. */
-    const credName = await resp.text();
-    if (credName === "") {
-        throw 'No credentials available for EC2 instance';
-    }
-    resp = await ngx.fetch(EC2_IMDS_SECURITY_CREDENTIALS_ENDPOINT + credName, {
-        headers: {
-            'x-aws-ec2-metadata-token': token,
-        },
-    });
-    const creds = await resp.json();
-
-    return {
-        accessKeyId: creds.AccessKeyId,
-        secretAccessKey: creds.SecretAccessKey,
-        sessionToken: creds.Token,
-        expiration: creds.Expiration,
-    };
-}
-
-/**
- * Get the credentials by assuming calling AssumeRoleWithWebIdentity with the environment variable
- * values ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE and HOSTNAME
- *
- * @returns {Promise<{accessKeyId: (string), secretAccessKey: (string), sessionToken: (string), expiration: (string)}>}
- * @private
- */
-async function _fetchWebIdentityCredentials(r) {
-    const arn = process.env['AWS_ROLE_ARN'];
-    const name = process.env['HOSTNAME'] || 'nginx-s3-gateway';
-
-    let sts_endpoint = process.env['STS_ENDPOINT'];
-    if (!sts_endpoint) {
-        /* On EKS, the ServiceAccount can be annotated with
-           'eks.amazonaws.com/sts-regional-endpoints' to control
-           the usage of regional endpoints. We are using the same standard
-           environment variable here as the AWS SDK. This is with the exception
-           of replacing the value `legacy` with `global` to match what EKS sets
-           the variable to.
-           See: https://docs.aws.amazon.com/sdkref/latest/guide/feature-sts-regionalized-endpoints.html
-           See: https://docs.aws.amazon.com/eks/latest/userguide/configure-sts-endpoint.html */
-        const sts_regional = process.env['AWS_STS_REGIONAL_ENDPOINTS'] || 'global';
-        if (sts_regional === 'regional') {
-            /* STS regional endpoints can be derived from the region's name.
-               See: https://docs.aws.amazon.com/general/latest/gr/sts.html */
-            const region = process.env['AWS_REGION'];
-            if (region) {
-                sts_endpoint = `https://sts.${region}.amazonaws.com`;
-            } else {
-                throw 'Missing required AWS_REGION env variable';
-            }
-        } else {
-            // This is the default global endpoint
-            sts_endpoint = 'https://sts.amazonaws.com';
-        }
-    }
-
-    const token = fs.readFileSync(process.env['AWS_WEB_IDENTITY_TOKEN_FILE']);
-
-    const params = `Version=2011-06-15&Action=AssumeRoleWithWebIdentity&RoleArn=${arn}&RoleSessionName=${name}&WebIdentityToken=${token}`;
-
-    const response = await ngx.fetch(sts_endpoint + "?" + params, {
-        headers: {
-            "Accept": "application/json"
-        },
-        method: 'GET',
-    });
-
-    const resp = await response.json();
-    const creds = resp.AssumeRoleWithWebIdentityResponse.AssumeRoleWithWebIdentityResult.Credentials;
-
-    return {
-        accessKeyId: creds.AccessKeyId,
-        secretAccessKey: creds.SecretAccessKey,
-        sessionToken: creds.SessionToken,
-        expiration: creds.Expiration,
-    };
-}
-
-/**
- * Get the current timestamp. This timestamp will be used across functions in 
- * order for there to be no variations in signatures.
- *
- * @returns {Date} The current moment as a timestamp
- */
-function getNow() {
-    return NOW;
-}
-
-export default {
-    getNow,
-    fetchCredentials,
-    readCredentials,
-    sessionToken,
-    writeCredentials
-}
diff --git a/common/etc/nginx/include/awssig2.js b/common/etc/nginx/include/awssig2.js
deleted file mode 100644
index 5630b21..0000000
--- a/common/etc/nginx/include/awssig2.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import utils from "./utils.js";
-
-const mod_hmac = require('crypto');
-
-/**
- * Create HTTP Authorization header for authenticating with an AWS compatible
- * v2 API.
- *
- * @param r {Request} HTTP request object
- * @param uri {string} The URI-encoded version of the absolute path component URL to create a request
- * @param httpDate {string} RFC2616 timestamp used to sign the request
- * @param credentials {object} Credential object with AWS credentials in it (AccessKeyId, SecretAccessKey, SessionToken)
- * @returns {string} HTTP Authorization header value
- */
-function signatureV2(r, uri, httpDate, credentials) {
-    const method = r.method;
-    const hmac = mod_hmac.createHmac('sha1', credentials.secretAccessKey);
-    const stringToSign = method + '\n\n\n' + httpDate + '\n' + uri;
-
-    utils.debug_log(r, 'AWS v2 Auth Signing String: [' + stringToSign + ']');
-
-    const signature = hmac.update(stringToSign).digest('base64');
-
-    return `AWS ${credentials.accessKeyId}:${signature}`;
-}
-
-
-export default {
-    signatureV2
-}
diff --git a/common/etc/nginx/include/awssig4.js b/common/etc/nginx/include/awssig4.js
deleted file mode 100644
index 2b1d2e0..0000000
--- a/common/etc/nginx/include/awssig4.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import utils from "./utils.js";
-
-const mod_hmac = require('crypto');
-
-/**
- * Constant checksum for an empty HTTP body.
- * @type {string}
- */
-const EMPTY_PAYLOAD_HASH = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
-
-/**
- * Constant defining the headers being signed.
- * @type {string}
- */
-const DEFAULT_SIGNED_HEADERS = 'host;x-amz-content-sha256;x-amz-date';
-
-
-/**
- * Create HTTP Authorization header for authenticating with an AWS compatible
- * v4 API.
- *
- * @param r {Request} HTTP request object
- * @param timestamp {Date} timestamp associated with request (must fall within a skew)
- * @param region {string} API region associated with request
- * @param service {string} service code (for example, s3, lambda)
- * @param uri {string} The URI-encoded version of the absolute path component URL to create a canonical request
- * @param queryParams {string} The URL-encoded query string parameters to create a canonical request
- * @param host {string} HTTP host header value
- * @param credentials {object} Credential object with AWS credentials in it (AccessKeyId, SecretAccessKey, SessionToken)
- * @returns {string} HTTP Authorization header value
- */
-function signatureV4(r, timestamp, region, service, uri, queryParams, host, credentials) {
-    const eightDigitDate = utils.getEightDigitDate(timestamp);
-    const amzDatetime = utils.getAmzDatetime(timestamp, eightDigitDate);
-    const canonicalRequest = _buildCanonicalRequest(r,
-        r.method, uri, queryParams, host, amzDatetime, credentials.sessionToken);
-    const signature = _buildSignatureV4(r, amzDatetime, eightDigitDate,
-        credentials, region, service, canonicalRequest);
-    const authHeader = 'AWS4-HMAC-SHA256 Credential='
-        .concat(credentials.accessKeyId, '/', eightDigitDate, '/', region, '/', service, '/aws4_request,',
-            'SignedHeaders=', _signedHeaders(r, credentials.sessionToken), ',Signature=', signature);
-
-    utils.debug_log(r, 'AWS v4 Auth header: [' + authHeader + ']');
-
-    return authHeader;
-}
-
-/**
- * Creates a canonical request that will later be signed
- *
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html | Creating a Canonical Request}
- * @param method {string} HTTP method
- * @param uri {string} URI associated with request
- * @param queryParams {string} query parameters associated with request
- * @param host {string} HTTP Host header value
- * @param amzDatetime {string} ISO8601 timestamp string to sign request with
- * @returns {string} string with concatenated request parameters
- * @private
- */
-function _buildCanonicalRequest(r,
-    method, uri, queryParams, host, amzDatetime, sessionToken) {
-    r.log('##### ---------------------------- #####')
-    r.log('     _buildCanonicalRequest(): ')
-    r.log('       - uri         : ' + uri)
-    r.log('       - method      : ' + method)
-    r.log('       - queryParams : ' + queryParams)
-    r.log('       - host        : ' + host)
-    r.log('       - amzDatetime : ' + amzDatetime)
-    r.log('       - request body: ' + r.variables.request_body)
-    r.log('       - content_type: ' + r.variables.content_type)
-    const payloadHash = awsHeaderPayloadHash(r);
-    let canonicalHeaders = '';
-    if (r.variables.content_type) {
-        canonicalHeaders += 'content-type:' + r.variables.content_type + '\n'
-    }
-    canonicalHeaders += 'host:' + host + '\n' +
-                        'x-amz-content-sha256:' + payloadHash + '\n' +
-                        'x-amz-date:' + amzDatetime + '\n';
-
-    if (sessionToken) {
-        canonicalHeaders += 'x-amz-security-token:' + sessionToken + '\n'
-    }
-
-    let canonicalRequest = method + '\n';
-    canonicalRequest += uri + '\n';
-    canonicalRequest += queryParams + '\n';
-    canonicalRequest += canonicalHeaders + '\n';
-    canonicalRequest += _signedHeaders(r, sessionToken) + '\n';
-    canonicalRequest += payloadHash;
-
-    return canonicalRequest;
-}
-
-/**
- * Creates a signature for use authenticating against an AWS compatible API.
- *
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html | AWS V4 Signing Process}
- * @param r {Request} HTTP request object
- * @param amzDatetime {string} ISO8601 timestamp string to sign request with
- * @param eightDigitDate {string} date in the form of 'YYYYMMDD'
- * @param creds {object} AWS credentials
- * @param region {string} API region associated with request
- * @param service {string} service code (for example, s3, lambda)
- * @param canonicalRequest {string} string with concatenated request parameters
- * @returns {string} hex encoded hash of signature HMAC value
- * @private
- */
-function _buildSignatureV4(
-    r, amzDatetime, eightDigitDate, creds, region, service, canonicalRequest) {
-    utils.debug_log(r, 'AWS v4 Auth Canonical Request: [' + canonicalRequest + ']');
-
-    const canonicalRequestHash = mod_hmac.createHash('sha256')
-        .update(canonicalRequest)
-        .digest('hex');
-
-    utils.debug_log(r, 'AWS v4 Auth Canonical Request Hash: [' + canonicalRequestHash + ']');
-
-    const stringToSign = _buildStringToSign(
-        amzDatetime, eightDigitDate, region, service, canonicalRequestHash);
-
-        utils.debug_log(r, 'AWS v4 Auth Signing String: [' + stringToSign + ']');
-
-    let kSigningHash;
-
-    /* If we have a keyval zone and key defined for caching the signing key hash,
-     * then signing key caching will be enabled. By caching signing keys we can
-     * accelerate the signing process because we will have four less HMAC
-     * operations that have to be performed per incoming request. The signing
-     * key expires every day, so our cache key can persist for 24 hours safely.
-     */
-    if ("variables" in r && r.variables.cache_signing_key_enabled == 1) {
-        // cached value is in the format: [eightDigitDate]:[signingKeyHash]
-        const cached = "signing_key_hash" in r.variables ? r.variables.signing_key_hash : "";
-        const fields = _splitCachedValues(cached);
-        const cachedEightDigitDate = fields[0];
-        const cacheIsValid = fields.length === 2 && eightDigitDate === cachedEightDigitDate;
-
-        // If true, use cached value
-        if (cacheIsValid) {
-            utils.debug_log(r, 'AWS v4 Using cached Signing Key Hash');
-            /* We are forced to JSON encode the string returned from the HMAC
-             * operation because it is in a very specific format that include
-             * binary data and in order to preserve that data when persisting
-             * we encode it as JSON. By doing so we can gracefully decode it
-             * when reading from the cache. */
-            kSigningHash = Buffer.from(JSON.parse(fields[1]));
-        // Otherwise, generate a new signing key hash and store it in the cache
-        } else {
-            kSigningHash = _buildSigningKeyHash(creds.secretAccessKey, eightDigitDate, region, service);
-            utils.debug_log(r, 'Writing key: ' + eightDigitDate + ':' + kSigningHash.toString('hex'));
-            r.variables.signing_key_hash = eightDigitDate + ':' + JSON.stringify(kSigningHash);
-        }
-    // Otherwise, don't use caching at all (like when we are using NGINX OSS)
-    } else {
-        kSigningHash = _buildSigningKeyHash(creds.secretAccessKey, eightDigitDate, region, service);
-    }
-
-    utils.debug_log(r, 'AWS v4 Signing Key Hash: [' + kSigningHash.toString('hex') + ']');
-
-    const signature = mod_hmac.createHmac('sha256', kSigningHash)
-        .update(stringToSign).digest('hex');
-
-    utils.debug_log(r, 'AWS v4 Authorization Header: [' + signature + ']');
-
-    return signature;
-}
-
-/**
- * Creates a string to sign by concatenating together multiple parameters required
- * by the signatures algorithm.
- *
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html | String to Sign}
- * @param amzDatetime {string} ISO8601 timestamp string to sign request with
- * @param eightDigitDate {string} date in the form of 'YYYYMMDD'
- * @param region {string} region associated with server API
- * @param service {string} service code (for example, s3, lambda)
- * @param canonicalRequestHash {string} hex encoded hash of canonical request string
- * @returns {string} a concatenated string of the passed parameters formatted for signatures
- * @private
- */
-function _buildStringToSign(amzDatetime, eightDigitDate, region, service, canonicalRequestHash) {
-    return 'AWS4-HMAC-SHA256\n' +
-        amzDatetime + '\n' +
-        eightDigitDate + '/' + region + '/' + service + '/aws4_request\n' +
-        canonicalRequestHash;
-}
-
-/**
- * Creates a string containing the headers that need to be signed as part of v4
- * signature authentication.
- *
- * @param r {Request} HTTP request object
- * @param sessionToken {string|undefined} AWS session token if present
- * @returns {string} semicolon delimited string of the headers needed for signing
- * @private
- */
-function _signedHeaders(r, sessionToken) {
-    let headers = '';
-    if (r.variables.content_type) {
-        headers += 'content-type;';
-    }
-    headers += DEFAULT_SIGNED_HEADERS;
-    if (sessionToken) {
-        headers += ';x-amz-security-token';
-    }
-    return headers;
-}
-
-/**
- * Creates a signing key HMAC. This value is used to sign the request made to
- * the API.
- *
- * @param kSecret {string} secret access key
- * @param eightDigitDate {string} date in the form of 'YYYYMMDD'
- * @param region {string} region associated with server API
- * @param service {string} name of service that request is for e.g. s3, lambda
- * @returns {ArrayBuffer} signing HMAC
- * @private
- */
-function _buildSigningKeyHash(kSecret, eightDigitDate, region, service) {
-    const kDate = mod_hmac.createHmac('sha256', 'AWS4'.concat(kSecret))
-        .update(eightDigitDate).digest();
-    const kRegion = mod_hmac.createHmac('sha256', kDate)
-        .update(region).digest();
-    const kService = mod_hmac.createHmac('sha256', kRegion)
-        .update(service).digest();
-    const kSigning = mod_hmac.createHmac('sha256', kService)
-        .update('aws4_request').digest();
-
-    return kSigning;
-}
-
-/**
- * Splits the cached values into an array with two elements or returns an
- * empty array if the input string is invalid. The first element contains
- * the eight digit date string and the second element contains a JSON string
- * of the kSigningHash.
- *
- * @param cached input string to parse
- * @returns {string[]|*[]} array containing eight digit date and kSigningHash or empty
- * @private
- */
-function _splitCachedValues(cached) {
-    const matchedPos = cached.indexOf(':', 0);
-    // Do a sanity check on the position returned, if it isn't sane, return
-    // an empty array and let the caller logic process it.
-    if (matchedPos < 0 || matchedPos + 1 > cached.length) {
-        return []
-    }
-
-    const eightDigitDate = cached.substring(0, matchedPos);
-    const kSigningHash = cached.substring(matchedPos + 1);
-
-    return [eightDigitDate, kSigningHash]
-}
-
-/**
- * Return a payload hash in the header
- *
- * @param r {Request} HTTP request object
- * @returns {string} payload hash
- */
-function awsHeaderPayloadHash(r) {
-    // Empty payload only works with this crypt library.
-    // TODO: Need to either find the right library or implement the crypto lib.
-    // const reqBodyStr = JSON.stringify(r.variables.request_body);
-    const reqBodyStr = r.variables.request_body;
-    r.log('       - req body str: ' + reqBodyStr)
-    const payloadHash = mod_hmac.createHash('sha256', 'utf8')
-                                .update(reqBodyStr)
-                                .digest('hex');
-    r.log('       - payload Hash: ' + payloadHash)
-    return payloadHash;
-}
-
-export default {
-    awsHeaderPayloadHash,
-    signatureV4,
-    // These functions do not need to be exposed, but they are exposed so that
-    // unit tests can run against them.
-    _buildCanonicalRequest,
-    _buildSignatureV4,
-    _buildSigningKeyHash,
-    _splitCachedValues
-}
diff --git a/common/etc/nginx/include/listing.xsl b/common/etc/nginx/include/listing.xsl
deleted file mode 100644
index 62056ad..0000000
--- a/common/etc/nginx/include/listing.xsl
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0"?>
-<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
-    <xsl:output method="html" encoding="utf-8" indent="yes"/>
-    <xsl:strip-space elements="*" />
-
-    <xsl:template match="/">
-        <xsl:choose>
-            <xsl:when test="//*[local-name()='Contents'] or //*[local-name()='CommonPrefixes']">
-                <xsl:apply-templates select="*[local-name()='ListBucketResult']" />
-            </xsl:when>
-            <xsl:otherwise>
-                <xsl:call-template name="no_contents"/>
-            </xsl:otherwise>
-        </xsl:choose>
-
-    </xsl:template>
-
-    <!-- When FOUR_O_FOUR_ON_EMPTY_BUCKET is disabled (the default setting),
-         the following template will be executed when the bucket is empty. -->
-    <xsl:template name="no_contents">
-        <html>
-            <head><title>No Files Available for Listing</title></head>
-            <body>
-                <h1>No Files Available for Listing</h1>
-            </body>
-        </html>
-    </xsl:template>
-
-    <xsl:template match="*[local-name()='ListBucketResult']">
-        <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
-        <xsl:variable name="globalPrefix"
-                      select="*[local-name()='Prefix']/text()"/>
-        <html>
-            <head>
-                <title><xsl:value-of select="$globalPrefix"/>
-                </title>
-            </head>
-            <body>
-                <h1>Index of /<xsl:value-of select="$globalPrefix"/></h1>
-                <hr/>
-                <table id="list">
-                    <thead>
-                        <tr>
-                            <th style="text-align: left; width:55%">Filename
-                            </th>
-                            <th style="text-align: left; width:20%">File Size
-                            </th>
-                            <th style="text-align: left; width:25%">Date</th>
-                        </tr>
-                    </thead>
-                    <tbody>
-                        <xsl:if test="string-length($globalPrefix) > 0">
-                            <tr>
-                                <td>
-                                    <a href="../">..</a>
-                                </td>
-                            </tr>
-                        </xsl:if>
-                        <xsl:apply-templates
-                                select="*[local-name()='CommonPrefixes']">
-                            <xsl:with-param name="globalPrefix"
-                                            select="$globalPrefix"/>
-                        </xsl:apply-templates>
-                        <xsl:apply-templates
-                                select="*[local-name()='Contents']">
-                            <xsl:with-param name="globalPrefix"
-                                            select="$globalPrefix"/>
-                        </xsl:apply-templates>
-                    </tbody>
-                </table>
-            </body>
-        </html>
-    </xsl:template>
-    <xsl:template match="*[local-name()='CommonPrefixes']">
-        <xsl:param name="globalPrefix"/>
-        <xsl:apply-templates select=".//*[local-name()='Prefix']">
-            <xsl:with-param name="globalPrefix" select="$globalPrefix"/>
-        </xsl:apply-templates>
-    </xsl:template>
-    <xsl:template match="*[local-name()='Prefix']">
-        <xsl:param name="globalPrefix"/>
-        <xsl:if test="not(text()=$globalPrefix)">
-            <xsl:variable name="dirName"
-                          select="substring-after(text(), $globalPrefix)"/>
-            <tr>
-                <td>
-                    <a><xsl:attribute name="href">/<xsl:call-template name="encode-uri"><xsl:with-param name="uri" select="text()"/></xsl:call-template>/</xsl:attribute>
-                        <xsl:value-of select="$dirName"/>
-                    </a>
-                </td>
-                <td/>
-                <td/>
-            </tr>
-        </xsl:if>
-    </xsl:template>
-
-    <xsl:template match="*[local-name()='Contents']">
-        <xsl:param name="globalPrefix"/>
-        <xsl:variable name="key" select="*[local-name()='Key']/text()"/>
-
-        <xsl:if test="not($key=$globalPrefix)">
-            <xsl:variable name="fileName"
-                          select="substring-after($key, $globalPrefix)"/>
-            <xsl:variable name="date"
-                          select="*[local-name()='LastModified']/text()"/>
-            <xsl:variable name="size" select="*[local-name()='Size']/text()"/>
-            <tr>
-                <td>
-                    <a>
-                        <xsl:attribute name="href">/<xsl:call-template name="encode-uri"><xsl:with-param name="uri" select="$key"/></xsl:call-template></xsl:attribute>
-                        <xsl:value-of select="$fileName"/>
-                    </a>
-                </td>
-                <td>
-                    <xsl:value-of select="$size"/>
-                </td>
-                <td>
-                    <xsl:value-of select="$date"/>
-                </td>
-            </tr>
-        </xsl:if>
-    </xsl:template>
-    <!-- This template escapes the URI such that symbols or unicode characters are
-         encoded so that they form a valid link that NGINX can parse -->
-    <xsl:template name="encode-uri">
-        <xsl:param name="uri"/>
-        <xsl:for-each select="str:split($uri, '/')">
-            <xsl:variable name="encoded" select="str:encode-uri(., 'true', 'UTF-8')" />
-            <xsl:variable name="more-encoded" select="
-                str:replace(
-                    str:replace(
-                        str:replace(
-                            str:replace(
-                                str:replace($encoded, '@', '%40'), '(', '%28'),
-                        ')', '%29'),
-                    '!', '%21'),
-                '*', '%2A')" />
-            <xsl:value-of select="$more-encoded" /><xsl:if test="position() != last()">/</xsl:if></xsl:for-each>
-    </xsl:template>
-</xsl:stylesheet>
diff --git a/common/etc/nginx/include/s3gateway.js b/common/etc/nginx/include/s3gateway.js
deleted file mode 100644
index 09e9d72..0000000
--- a/common/etc/nginx/include/s3gateway.js
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- *  Copyright 2020 F5 Networks
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import awscred from "./awscredentials.js";
-import awssig2 from "./awssig2.js";
-import awssig4 from "./awssig4.js";
-import utils from "./utils.js";
-
-_require_env_var('S3_BUCKET_NAME');
-_require_env_var('S3_SERVER');
-_require_env_var('S3_SERVER_PROTO');
-_require_env_var('S3_SERVER_PORT');
-_require_env_var('S3_REGION');
-_require_env_var('AWS_SIGS_VERSION');
-_require_env_var('S3_STYLE');
-
-
-/**
- * Flag indicating debug mode operation. If true, additional information
- * about signature generation will be logged.
- * @type {boolean}
- */
-const ALLOW_LISTING = utils.parseBoolean(process.env['ALLOW_DIRECTORY_LIST']);
-const PROVIDE_INDEX_PAGE = utils.parseBoolean(process.env['PROVIDE_INDEX_PAGE']);
-const APPEND_SLASH = utils.parseBoolean(process.env['APPEND_SLASH_FOR_POSSIBLE_DIRECTORY']);
-const FOUR_O_FOUR_ON_EMPTY_BUCKET = utils.parseBoolean(process.env['FOUR_O_FOUR_ON_EMPTY_BUCKET']);
-const S3_STYLE = process.env['S3_STYLE'];
-
-const ADDITIONAL_HEADER_PREFIXES_TO_STRIP = utils.parseArray(process.env['HEADER_PREFIXES_TO_STRIP']);
-
-/**
- * Default filename for index pages to be read off of the backing object store.
- * @type {string}
- */
-const INDEX_PAGE = "index.html";
-
-/**
- * Constant defining the service requests are being signed for.
- * @type {string}
- */
-const SERVICE = 's3';
-
-/**
- * Transform the headers returned from S3 such that there isn't information
- * leakage about S3 and do other tasks needed for appropriate gateway output.
- * @param r HTTP request
- */
-function editHeaders(r) {
-    const isDirectoryHeadRequest =
-        ALLOW_LISTING &&
-        r.method === 'HEAD' &&
-        _isDirectory(decodeURIComponent(r.variables.uri_path));
-
-    /* Strips all x-amz- headers from the output HTTP headers so that the
-     * requesters to the gateway will not know you are proxying S3. */
-    if ('headersOut' in r) {
-        for (const key in r.headersOut) {
-            /* We delete all headers when it is a directory head request because
-             * none of the information is relevant for passing on via a gateway. */
-            if (isDirectoryHeadRequest) {
-                delete r.headersOut[key];
-            } else if (_isHeaderToBeStripped(key.toLowerCase(), ADDITIONAL_HEADER_PREFIXES_TO_STRIP)) {
-                delete r.headersOut[key];
-            }
-        }
-
-        /* Transform content type returned on HEAD requests for directories
-         * if directory listing is enabled. If you change the output format
-         * for the XSL stylesheet from HTML to something else, you will
-         * want to change the content type below. */
-        if (isDirectoryHeadRequest) {
-            r.headersOut['Content-Type'] = 'text/html; charset=utf-8'
-        }
-    }
-}
-
-/**
- * Determines if a given HTTP header should be removed before being
- * sent on to the requesting client.
- * @param headerName {string} Lowercase HTTP header name
- * @param additionalHeadersToStrip {Array[string]} array of additional headers to remove
- * @returns {boolean} true if header should be removed
- */
-function _isHeaderToBeStripped(headerName, additionalHeadersToStrip) {
-    if (headerName.indexOf('x-amz-', 0) >= 0) {
-        return true;
-    }
-
-    for (let i = 0; i < additionalHeadersToStrip.length; i++) {
-        const headerToStrip = additionalHeadersToStrip[i];
-        if (headerName.indexOf(headerToStrip, 0) >= 0) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/**
- * Outputs the timestamp used to sign the request, so that it can be added to
- * the 'Date' header and sent by NGINX.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} RFC2616 timestamp
- */
-function s3date(r) {
-    return awscred.getNow().toUTCString();
-}
-
-/**
- * Outputs the timestamp used to sign the request, so that it can be added to
- * the 'x-amz-date' header and sent by NGINX. The output format is
- * ISO 8601: YYYYMMDD'T'HHMMSS'Z'.
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html | Handling dates in Signature Version 4}
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} ISO 8601 timestamp
- */
-function awsHeaderDate(r) {
-    return utils.getAmzDatetime(
-        awscred.getNow(), 
-        utils.getEightDigitDate(awscred.getNow())
-    );
-}
-
-/**
- * Creates an AWS authentication signature based on the global settings and
- * the passed request parameter.
- *
- * @param r {Request} HTTP request object
- * @returns {string} AWS authentication signature
- */
-function s3auth(r) {
-    const bucket = process.env['S3_BUCKET_NAME'];
-    const region = process.env['S3_REGION'];
-    let server;
-    if (S3_STYLE === 'path') {
-        server = process.env['S3_SERVER'] + ':' + process.env['S3_SERVER_PORT'];
-    } else {
-        server = process.env['S3_SERVER'];
-    }
-    const sigver = process.env['AWS_SIGS_VERSION'];
-
-    let signature;
-
-    const credentials = awscred.readCredentials(r);
-    if (sigver == '2') {
-        let req = _s3ReqParamsForSigV2(r, bucket);
-        signature = awssig2.signatureV2(r, req.uri, req.httpDate, credentials);
-    } else {
-        let req = _s3ReqParamsForSigV4(r, bucket, server);
-        signature = awssig4.signatureV4(r, awscred.getNow(), region, SERVICE,
-            req.uri, req.queryParams, req.host, credentials);
-    }
-
-    return signature;
-}
-
-/**
- * Generate some of request parameters for AWS signature version 2
- *
- * @see {@link https://docs.aws.amazon.com/AmazonS3/latest/userguide/auth-request-sig-v2.html | AWS signature version 2}
- * @param r {Request} HTTP request object
- * @param bucket {string} S3 bucket associated with request
- * @returns s3ReqParams {object} s3ReqParams object (host, method, uri, queryParams)
- * @private
- */
-function _s3ReqParamsForSigV2(r, bucket) {
-    /* If the source URI is a directory, we are sending to S3 a query string
-     * local to the root URI, so this is what we need to encode within the
-     * string to sign. For example, if we are requesting /bucket/dir1/ from
-     * nginx, then in S3 we need to request /?delimiter=/&prefix=dir1/
-     * Thus, we can't put the path /dir1/ in the string to sign. */
-    let uri = _isDirectory(r.variables.uri_path) ? '/' : r.variables.uri_path;
-    // To return index pages + index.html
-    if (PROVIDE_INDEX_PAGE && _isDirectory(r.variables.uri_path)){
-        uri = r.variables.uri_path + INDEX_PAGE
-    }
- 
-    return {
-        uri: '/' + bucket + uri,
-        httpDate: s3date(r)
-    };
-}
-
-/**
- * Generate some of request parameters for AWS signature version 4
- *
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html | AWS V4 Signing Process}
- * @param r {Request} HTTP request object
- * @param bucket {string} S3 bucket associated with request
- * @param server {string} S3 host associated with request
- * @returns s3ReqParams {object} s3ReqParams object (host, uri, queryParams)
- * @private
- */
-function _s3ReqParamsForSigV4(r, bucket, server) {
-    let host = server;
-    if (S3_STYLE === 'virtual' || S3_STYLE === 'default' || S3_STYLE === undefined) {
-        host = bucket + '.' + host;
-    }
-    const baseUri = s3BaseUri(r);
-    const queryParams = _s3DirQueryParams(r.variables.uri_path, r.method);
-    let uri;
-    if (queryParams.length > 0) {
-        if (baseUri.length > 0) {
-            uri = baseUri;
-        } else {
-            uri = '/';
-        }
-    } else {
-        uri = s3uri(r);
-    }
-    return {
-        host: host,
-        uri: uri,
-        queryParams: queryParams
-    };
-}
-
-/**
- * Build the base file path for a S3 request URI. This function allows for
- * path style S3 URIs to be created that do not use a subdomain to specify
- * the bucket name.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} start of the file path for the S3 object URI
- */
-function s3BaseUri(r) {
-    const bucket = process.env['S3_BUCKET_NAME'];
-    let basePath;
-
-    if (S3_STYLE === 'path') {
-        utils.debug_log(r, 'Using path style uri : ' + '/' + bucket);
-        basePath = '/' + bucket;
-    } else {
-        basePath = '';
-    }
-
-    return basePath;
-}
-
-/**
- * Returns the s3 path given the incoming request
- *
- * @param r HTTP request
- * @returns {string} uri for s3 request
- */
-function s3uri(r) {
-    let uriPath = r.variables.uri_path;
-    const basePath = s3BaseUri(r);
-    let path;
-
-    // Create query parameters only if directory listing is enabled.
-    if (ALLOW_LISTING) {
-        const queryParams = _s3DirQueryParams(uriPath, r.method);
-        if (queryParams.length > 0) {
-            path = basePath + '?' + queryParams;
-        } else {
-            path = _escapeURIPath(basePath + uriPath);
-        }
-    } else {
-        // This is a path that will resolve to an index page
-        if (PROVIDE_INDEX_PAGE  && _isDirectory(uriPath) ) {
-            uriPath += INDEX_PAGE;
-        }
-        path = _escapeURIPath(basePath + uriPath);
-    }
-
-    utils.debug_log(r, 'S3 Request URI: ' + r.method + ' ' + path);
-    return path;
-}
-
-/**
- * Create and encode the query parameters needed to query S3 for an object
- * listing.
- *
- * @param uriPath request URI path
- * @param method request HTTP method
- * @returns {string} query parameters to use with S3 request
- * @private
- */
-function _s3DirQueryParams(uriPath, method) {
-    if (!_isDirectory(uriPath) || method !== 'GET') {
-        return '';
-    }
-
-    /* Return if static website. We don't want to list the files in the
-       directory, we want to append the index page and get the fil. */
-    if (PROVIDE_INDEX_PAGE){
-        return '';
-    }
-
-    let path = 'delimiter=%2F'
-
-    if (uriPath !== '/') {
-        let decodedUriPath = decodeURIComponent(uriPath);
-        let without_leading_slash = decodedUriPath.charAt(0) === '/' ?
-            decodedUriPath.substring(1, decodedUriPath.length) : decodedUriPath;
-        path += '&prefix=' + _encodeURIComponent(without_leading_slash);
-    }
-
-    return path;
-}
-
-/**
- * Redirects the request to the appropriate location. If the request is not
- * a read (GET/HEAD) request, then we reject the request outright by returning
- * a HTTP 405 error with a list of allowed methods.
- *
- * @param r {Request} HTTP request object
- */
-function redirectToS3(r) {
-    // This is a read-only S3 gateway, so we do not support any other methods
-    if (!(r.method === 'GET' || r.method === 'HEAD')) {
-        utils.debug_log(r, 'Invalid method requested: ' + r.method);
-        r.internalRedirect("@error405");
-        return;
-    }
-
-    const uriPath = r.variables.uri_path;
-    const isDirectoryListing = ALLOW_LISTING && _isDirectory(uriPath);
-
-    if (isDirectoryListing && r.method === 'GET') {
-        r.internalRedirect("@s3Listing");
-    } else if ( PROVIDE_INDEX_PAGE == true ) {
-        r.internalRedirect("@s3");
-    } else if ( !ALLOW_LISTING && !PROVIDE_INDEX_PAGE && uriPath == "/" ) {
-       r.internalRedirect("@error404");
-    } else {
-        r.internalRedirect("@s3");
-    }
-}
-
-function trailslashControl(r) {
-    if (APPEND_SLASH) {
-        const hasExtension = /\/[^.\/]+\.[^.]+$/;
-        if (!hasExtension.test(r.variables.uri_path)  && !_isDirectory(r.variables.uri_path)){
-            return r.internalRedirect("@trailslash");
-        }
-    }
-        r.internalRedirect("@error404");
-}
-
-/**
- * Processes the directory listing output as returned from S3. If
- * FOUR_O_FOUR_ON_EMPTY_BUCKET is enabled, this function will corrupt the
- * XML output by inserting the string 'junk' into the output thereby causing
- * nginx to return a 404 for empty directory listings.
- *
- * If anyone finds a better way to do this, please submit a PR.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @param data chunked data buffer
- * @param flags contains field that indicates that a chunk is last
- */
-function filterListResponse(r, data, flags) {
-    if (FOUR_O_FOUR_ON_EMPTY_BUCKET) {
-        let indexIsEmpty = utils.parseBoolean(r.variables.indexIsEmpty);
-
-        if (indexIsEmpty && data.indexOf('<Contents') >= 0) {
-            r.variables.indexIsEmpty = false;
-            indexIsEmpty = false;
-        }
-
-        if (indexIsEmpty && data.indexOf('<CommonPrefixes') >= 0) {
-            r.variables.indexIsEmpty = false;
-            indexIsEmpty = false;
-        }
-
-        if (flags.last && indexIsEmpty) {
-            r.sendBuffer('junk', flags);
-        } else {
-            r.sendBuffer(data, flags);
-        }
-    } else {
-        r.sendBuffer(data, flags);
-    }
-}
-
-/**
- * Adds additional encoding to a URI component
- *
- * @param string {string} string to encode
- * @returns {string} an encoded string
- * @private
- */
-function _encodeURIComponent(string) {
-    return encodeURIComponent(string)
-        .replace(/[!*'()]/g, (c) =>
-            `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
-}
-
-/**
- * Escapes the path portion of a URI without escaping the path separator
- * characters (/).
- *
- * @param uri {string} unescaped URI
- * @returns {string} URI with each path component separately escaped
- * @private
- */
-function _escapeURIPath(uri) {
-    // Check to see if the URI path was already encoded. If so, we decode it.
-    let decodedUri = (uri.indexOf('%') >= 0) ? decodeURIComponent(uri) : uri;
-    let components = [];
-
-    decodedUri.split('/').forEach(function (item, i) {
-        components[i] = _encodeURIComponent(item);
-    });
-
-    return components.join('/');
-}
-
-/**
- * Determines if a given path is a directory based on whether or not the last
- * character in the path is a forward slash (/).
- *
- * @param path {string} path to parse
- * @returns {boolean} true if path is a directory
- * @private
- */
-function _isDirectory(path) {
-    if (path === undefined) {
-        return false;
-    }
-    const len = path.length;
-
-    if (len < 1) {
-        return false;
-    }
-
-    return path.charAt(len - 1) === '/';
-}
-
-/**
- * Checks to see if the given environment variable is present. If not, an error
- * is thrown.
- * @param envVarName {string} environment variable to check for
- * @private
- */
-function _require_env_var(envVarName) {
-    const isSet = envVarName in process.env;
-
-    if (!isSet) {
-        throw('Required environment variable ' + envVarName + ' is missing');
-    }
-}
-
-
-export default {
-    awsHeaderDate,
-    s3date,
-    s3auth,
-    s3uri,
-    trailslashControl,
-    redirectToS3,
-    editHeaders,
-    filterListResponse,
-    // These functions do not need to be exposed, but they are exposed so that
-    // unit tests can run against them.
-    _s3ReqParamsForSigV2,
-    _s3ReqParamsForSigV4,
-    _encodeURIComponent,
-    _escapeURIPath,
-    _isHeaderToBeStripped
-};
diff --git a/common/etc/nginx/include/utils.js b/common/etc/nginx/include/utils.js
deleted file mode 100644
index 0228d0f..0000000
--- a/common/etc/nginx/include/utils.js
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-/**
- * Flag indicating debug mode operation. If true, additional information
- * about signature generation will be logged.
- * @type {boolean}
- */
-const DEBUG = parseBoolean(process.env['S3_DEBUG']);
-
-
-/**
- * Parses a string delimited by semicolons into an array of values
- * @param string {string|null} value representing a array of strings
- * @returns {Array} a list of values
- */
-function parseArray(string) {
-    if (string == null || !string || string === ';') {
-        return [];
-    }
-
-    // Exclude trailing delimiter
-    if (string.endsWith(';')) {
-        return string.substr(0, string.length - 1).split(';');
-    }
-
-    return string.split(';')
-}
-
-/**
- * Parses a string to and returns a boolean value based on its value. If the
- * string can't be parsed, this method returns false.
- *
- * @param string {*} value representing a boolean
- * @returns {boolean} boolean value of string
- */
-function parseBoolean(string) {
-    switch(string) {
-        case "TRUE":
-        case "true":
-        case "True":
-        case "YES":
-        case "yes":
-        case "Yes":
-        case "1":
-            return true;
-        default:
-            return false;
-    }
-}
-
-/**
- * Outputs a log message to the request logger if debug messages are enabled.
- *
- * @param r {Request} HTTP request object
- * @param msg {string} message to log
- */
-function debug_log(r, msg) {
-    if (DEBUG && "log" in r) {
-        r.log(msg);
-    }
-}
-
-/**
- * Pads the supplied number with leading zeros.
- *
- * @param num {number|string} number to pad
- * @param size number of leading zeros to pad
- * @returns {string} a string with leading zeros
- * @private
- */
-function padWithLeadingZeros(num, size) {
-    const s = "0" + num;
-    return s.substr(s.length-size);
-}
-
-/**
- * Creates a string in the ISO601 date format (YYYYMMDD'T'HHMMSS'Z') based on
- * the supplied timestamp and date. The date is not extracted from the timestamp
- * because that operation is already done once during the signing process.
- *
- * @param timestamp {Date} timestamp to extract date from
- * @param eightDigitDate {string} 'YYYYMMDD' format date string that was already extracted from timestamp
- * @returns {string} string in the format of YYYYMMDD'T'HHMMSS'Z'
- * @private
- */
-function getAmzDatetime(timestamp, eightDigitDate) {
-    const hours = timestamp.getUTCHours();
-    const minutes = timestamp.getUTCMinutes();
-    const seconds = timestamp.getUTCSeconds();
-
-    return ''.concat(
-        eightDigitDate,
-        'T', padWithLeadingZeros(hours, 2),
-        padWithLeadingZeros(minutes, 2),
-        padWithLeadingZeros(seconds, 2),
-        'Z');
-}
-
-/**
- * Formats a timestamp into a date string in the format 'YYYYMMDD'.
- *
- * @param timestamp {Date} timestamp
- * @returns {string} a formatted date string based on the input timestamp
- * @private
- */
-function getEightDigitDate(timestamp) {
-    const year = timestamp.getUTCFullYear();
-    const month = timestamp.getUTCMonth() + 1;
-    const day = timestamp.getUTCDate();
-
-    return ''.concat(padWithLeadingZeros(year, 4),
-        padWithLeadingZeros(month,2),
-        padWithLeadingZeros(day,2));
-}
-
-
-/**
- * Checks to see if the given environment variable is present. If not, an error
- * is thrown.
- * @param envVarName {string} environment variable to check for
- * @private
- */
-function requireEnvVar(envVarName) {
-    const isSet = envVarName in process.env;
-
-    if (!isSet) {
-        throw('Required environment variable ' + envVarName + ' is missing');
-    }
-}
-
-export default {
-    debug_log,
-    getAmzDatetime,
-    getEightDigitDate,
-    padWithLeadingZeros,
-    parseArray,
-    parseBoolean,
-    requireEnvVar
-}
diff --git a/common/etc/nginx/nginx.conf b/common/etc/nginx/nginx.conf
index 035f909..f7bc8cb 100644
--- a/common/etc/nginx/nginx.conf
+++ b/common/etc/nginx/nginx.conf
@@ -4,30 +4,19 @@ worker_processes  1;
 error_log  /dev/stdout info;
 pid        /var/run/nginx.pid;
 
-# NJS module used for implementing S3 authentication
+# NJS module used for implementing Lambda authentication
 load_module modules/ngx_http_js_module.so;
-load_module modules/ngx_http_xslt_filter_module.so;
 
-# Preserve S3 environment variables for worker threads
+# Preserve Lambda environment variables for worker threads
 env AWS_ACCESS_KEY_ID;
 env AWS_SECRET_ACCESS_KEY;
 env AWS_SESSION_TOKEN;
-env S3_BUCKET_NAME;
-env S3_SERVER;
-env S3_SERVER_PORT;
-env S3_SERVER_PROTO;
-env S3_REGION;
-env AWS_SIGS_VERSION;
-env S3_DEBUG;
-env S3_STYLE;
-env ALLOW_DIRECTORY_LIST;
-env PROVIDE_INDEX_PAGE;
-env APPEND_SLASH_FOR_POSSIBLE_DIRECTORY;
-env PROXY_CACHE_VALID_OK;
-env PROXY_CACHE_VALID_NOTFOUND;
-env PROXY_CACHE_VALID_FORBIDDEN;
+env DEBUG;
 env HEADER_PREFIXES_TO_STRIP;
-env FOUR_O_FOUR_ON_EMPTY_BUCKET;
+env LAMBDA_REGION;
+env LAMBDA_SERVER_PROTO;
+env LAMBDA_SERVER;
+env LAMBDA_SERVER_PORT;
 
 events {
     worker_connections  1024;
@@ -49,14 +38,5 @@ http {
     keepalive_timeout  65;
 
     #gzip  on;
-
-    # Settings for S3 cache
-    proxy_cache_path /var/cache/nginx/s3_proxy
-        levels=1:2
-        keys_zone=s3_cache:10m
-        max_size=10g
-        inactive=60m
-        use_temp_path=off;
-
     include /etc/nginx/conf.d/*.conf;
 }
diff --git a/common/etc/nginx/templates/default.conf.template b/common/etc/nginx/templates/default.conf.template
deleted file mode 100644
index b473d0c..0000000
--- a/common/etc/nginx/templates/default.conf.template
+++ /dev/null
@@ -1,285 +0,0 @@
-js_import /etc/nginx/include/awscredentials.js;
-js_import /etc/nginx/include/awssig4.js;
-js_import /etc/nginx/include/s3gateway.js;
-js_import /etc/nginx/include/lambdagateway.js;
-
-# We include only the variables needed for the authentication signatures that
-# we plan to use.
-include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_js_vars.conf;
-
-# Extracts only the path from the requested URI. This strips out all query
-# parameters and anchors in order to prevent extraneous data from being sent
-# to S3.
-map $request_uri $uri_path {
-    "~^(?P<path>.*?)(\?.*)*$"  $path;
-}
-
-map $S3_STYLE $s3_host_hdr {
-    virtual "${S3_BUCKET_NAME}.${S3_SERVER}";
-    path    "${S3_SERVER}:${S3_SERVER_PORT}";
-    default "${S3_BUCKET_NAME}.${S3_SERVER}";
-}
-
-map $host $lambda_host {
-    default "https://lambda.us-east-2.amazonaws.com";
-}
-
-js_var $indexIsEmpty true;
-
-# This creates the HTTP authentication header to be sent to S3
-js_set $s3auth s3gateway.s3auth;
-js_set $awsSessionToken awscredentials.sessionToken;
-js_set $s3uri s3gateway.s3uri;
-
-js_set $lambdaAuth lambdagateway.lambdaAuth;
-js_set $lambdaURI  lambdagateway.lambdaURI;
-
-server {
-    include /etc/nginx/conf.d/gateway/server_variables.conf;
-
-    # Don't display the NGINX version number because we don't want to reveal
-    # information that could be used to find an exploit.
-    server_tokens off;
-
-    # Uncomment this for a HTTP header that will let you know the cache status
-    # of an object.
-    # add_header X-Cache-Status $upstream_cache_status;
-
-    # Proxy caching configuration. Customize this for your needs.
-    proxy_cache s3_cache;
-    proxy_cache_valid 200 302 ${PROXY_CACHE_VALID_OK};
-    proxy_cache_valid 404 ${PROXY_CACHE_VALID_NOTFOUND};
-    proxy_cache_valid 403 ${PROXY_CACHE_VALID_FORBIDDEN};
-    proxy_cache_methods GET HEAD;
-    # When this is enabled a HEAD request to NGINX will result in a GET
-    # request upstream. Unfortunately, proxy_cache_convert_head has to be
-    # disabled because there is no way for the signatures generation code to
-    # get access to the metadata in the GET request that is sent upstream.
-    proxy_cache_convert_head off;
-    proxy_cache_revalidate on;
-    proxy_cache_background_update on;
-    proxy_cache_lock on;
-    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
-    proxy_cache_key "$request_method$host$uri";
-
-    # If you need to support proxying range request, refer to this article:
-    # https://www.nginx.com/blog/smart-efficient-byte-range-caching-nginx/
-
-    # Do not proxy the S3 SOAP API. The S3 API has a less-documented feature
-    # where the object name "soap" is used for the SOAP API. We don't allow
-    # access to it.
-    location /soap {
-        return 404;
-    }
-
-    location /health {
-        return 200;
-    }
-
-    location / {
-        # This value is templated in based on the value of $CORS_ENABLED. When
-        # CORS is enabled, acceptable methods are GET, HEAD, and OPTIONS.
-        # Otherwise, they are GET and HEAD.
-        # limit_except ${LIMIT_METHODS_TO} {}
-
-        # CORS is implemented by returning the appropriate headers as part of
-        # the response to an OPTIONS request. If you want to customize the
-        # CORS response, the cors.conf.template file can be overwritten and
-        # extended to meet one's needs.
-        include /etc/nginx/conf.d/gateway/cors.conf;
-
-        auth_request /aws/credentials/retrieve;
-
-        # Redirect to the proper location based on the client request - either
-        # @s3, @s3Listing or @error405.
-
-        #js_content s3gateway.redirectToS3;
-        js_content lambdagateway.redirectToLambda;
-    }
-
-    location /aws/credentials/retrieve {
-        internal;
-        js_content awscredentials.fetchCredentials;
-
-        include /etc/nginx/conf.d/gateway/js_fetch_trusted_certificate.conf;
-    }
-
-    location @lambda {
-        # We include only the headers needed for the authentication signatures that
-        # we plan to use.
-        include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_headers.conf;
-
-        # The CORS configuration needs to be imported in several places in order for
-        # it to be applied within different contexts.
-        # include /etc/nginx/conf.d/gateway/cors.conf;
-
-        # Don't allow any headers from the client - we don't want them messing
-        # with Lambda at all.
-        proxy_pass_request_headers off;
-
-        # Enable passing of the server name through TLS Server Name Indication extension.
-        proxy_ssl_server_name on;
-        #proxy_ssl_name ${LAMBDA_SERVER};
-
-        # Set the Authorization header to the AWS Signatures credentials
-        proxy_set_header Authorization $lambdaAuth;
-        proxy_set_header X-Amz-Security-Token $awsSessionToken;
-
-        # We set the host as the bucket name to inform the S3 API of the bucket
-        #proxy_set_header Host $s3_host_hdr;
-
-        # Use keep alive connections in order to improve performance
-        proxy_http_version 1.1;
-        proxy_set_header Connection '';
-        proxy_method POST;
-
-        # We strip off all of the AWS specific headers from the server so that
-        # there is nothing identifying the object as having originated in an
-        # object store.
-        #js_header_filter s3gateway.editHeaders;
-
-        # Catch all errors from S3 and sanitize them so that the user can't
-        # gain intelligence about the S3 bucket being proxied.
-        proxy_intercept_errors on;
-
-        # Comment out this line to receive the error messages returned by Lambda
-        #error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 =404 @error404;
-
-        #error_page 404 @trailslashControl;
-
-        #proxy_pass ${S3_SERVER_PROTO}://storage_urls$s3uri;
-        #proxy_pass ${LAMBDA_SERVER_PROTO}://lambda_urls$lambdaURI;
-        proxy_pass $lambda_host$lambdaURI;
-        #proxy_pass https://lambda.us-east-2.amazonaws.com/2015-03-31/functions/nginx-serverless/invocations;
-
-        #include /etc/nginx/conf.d/gateway/s3_location.conf;
-    }
-
-    location @s3 {
-        # We include only the headers needed for the authentication signatures that
-        # we plan to use.
-        include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_headers.conf;
-
-        # The CORS configuration needs to be imported in several places in order for
-        # it to be applied within different contexts.
-        include /etc/nginx/conf.d/gateway/cors.conf;
-
-        # Don't allow any headers from the client - we don't want them messing
-        # with S3 at all.
-        proxy_pass_request_headers off;
-
-        # Enable passing of the server name through TLS Server Name Indication extension.
-        proxy_ssl_server_name on;
-        proxy_ssl_name ${S3_SERVER};
-
-        # Set the Authorization header to the AWS Signatures credentials
-        proxy_set_header Authorization $s3auth;
-        proxy_set_header X-Amz-Security-Token $awsSessionToken;
-
-        # We set the host as the bucket name to inform the S3 API of the bucket
-        proxy_set_header Host $s3_host_hdr;
-
-        # Use keep alive connections in order to improve performance
-        proxy_http_version 1.1;
-        proxy_set_header Connection '';
-
-        # We strip off all of the AWS specific headers from the server so that
-        # there is nothing identifying the object as having originated in an
-        # object store.
-        js_header_filter s3gateway.editHeaders;
-
-        # Catch all errors from S3 and sanitize them so that the user can't
-        # gain intelligence about the S3 bucket being proxied.
-        proxy_intercept_errors on;
-
-        # Comment out this line to receive the error messages returned by S3
-        error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 =404 @error404;
-
-        error_page 404 @trailslashControl;
-
-        proxy_pass ${S3_SERVER_PROTO}://storage_urls$s3uri;
-
-        include /etc/nginx/conf.d/gateway/s3_location.conf;
-    }
-
-    location @s3Listing {
-        # We include only the headers needed for the authentication signatures that
-        # we plan to use.
-        include /etc/nginx/conf.d/gateway/v${AWS_SIGS_VERSION}_headers.conf;
-
-        # The CORS configuration needs to be imported in several places in order for
-        # it to be applied within different contexts.
-        include /etc/nginx/conf.d/gateway/cors.conf;
-
-        # Don't allow any headers from the client - we don't want them messing
-        # with S3 at all.
-        proxy_pass_request_headers off;
-
-        # Enable passing of the server name through TLS Server Name Indication extension.
-        proxy_ssl_server_name on;
-        proxy_ssl_name ${S3_SERVER};
-
-        # Set the Authorization header to the AWS Signatures credentials
-        proxy_set_header Authorization $s3auth;
-        proxy_set_header X-Amz-Security-Token $awsSessionToken;
-
-        # We set the host as the bucket name to inform the S3 API of the bucket
-        proxy_set_header Host $s3_host_hdr;
-
-        # Use keep alive connections in order to improve performance
-        proxy_http_version 1.1;
-        proxy_set_header Connection '';
-
-        # We strip off all of the AWS specific headers from the server so that
-        # there is nothing identifying the object as having originated in an
-        # object store.
-        js_header_filter s3gateway.editHeaders;
-
-        # Apply XSL transformation to the XML returned from S3 directory listing
-        # results such that we can output an HTML directory contents list.
-        xslt_stylesheet /etc/nginx/include/listing.xsl;
-        xslt_types application/xml;
-
-        # We apply an output filter to the XML input received from S3 before it
-        # is passed to XSLT in order to determine if the resource is not a valid
-        # S3 directory. If it isn't a valid directory, we do a dirty hack to
-        # corrupt the contents of the XML causing the XSLT to fail and thus
-        # nginx to return a 404 to the client. If you don't care about empty
-        # directory listings for invalid directories, remove this.
-        js_body_filter s3gateway.filterListResponse;
-
-        # Catch all errors from S3 and sanitize them so that the user can't
-        # gain intelligence about the S3 bucket being proxied.
-        proxy_intercept_errors on;
-
-        # Comment out this line to receive the error messages returned by S3
-        error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 =404 @error404;
-
-        proxy_pass ${S3_SERVER_PROTO}://storage_urls$s3Uri;
-        include /etc/nginx/conf.d/gateway/s3listing_location.conf;
-    }
-
-    location @error404 {
-        return 404;
-    }
-
-    location @trailslashControl {
-        # Checks if requesting a folder without trailing slash, and return 302
-        # appending a slash to it when using for static site hosting.
-        js_content s3gateway.trailslashControl;
-    }
-
-    location @trailslash {
-        # 302 to request without slashes
-        rewrite ^ $scheme://$http_host$request_uri/ redirect;
-    }
-
-    # Provide a hint to the client on 405 errors of the acceptable request methods
-    error_page 405 @error405;
-    location @error405 {
-        add_header Allow "${LIMIT_METHODS_TO_CSV}" always;
-        return 405;
-    }
-
-    include /etc/nginx/conf.d/gateway/s3_server.conf;
-}
diff --git a/common/etc/nginx/templates/gateway/cors.conf.template b/common/etc/nginx/templates/gateway/cors.conf.template
deleted file mode 100644
index e92a1c9..0000000
--- a/common/etc/nginx/templates/gateway/cors.conf.template
+++ /dev/null
@@ -1,31 +0,0 @@
-set $request_cors "${request_method}_${CORS_ENABLED}";
-
-if ($request_cors = "OPTIONS_1") {
-    add_header 'Access-Control-Allow-Origin' '${CORS_ALLOWED_ORIGIN}';
-    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
-    #
-    # Custom headers and headers various browsers *should* be OK with but aren't
-    #
-    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
-    #
-    # Tell client that this pre-flight info is valid for 20 days
-    #
-    add_header 'Access-Control-Max-Age' 1728000;
-    add_header 'Content-Type' 'text/plain; charset=utf-8';
-    add_header 'Content-Length' 0;
-    return 204;
-}
-
-if ($request_cors = "GET_1") {
-    add_header 'Access-Control-Allow-Origin' '${CORS_ALLOWED_ORIGIN}' always;
-    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
-    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
-    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
-}
-
-if ($request_cors = "HEAD_1") {
-    add_header 'Access-Control-Allow-Origin' '${CORS_ALLOWED_ORIGIN}' always;
-    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
-    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
-    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
-}
diff --git a/common/etc/nginx/templates/gateway/js_fetch_trusted_certificate.conf.template b/common/etc/nginx/templates/gateway/js_fetch_trusted_certificate.conf.template
deleted file mode 100644
index 475e980..0000000
--- a/common/etc/nginx/templates/gateway/js_fetch_trusted_certificate.conf.template
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable js_fetch_trusted_certificate if you are seeing SSL Handshake error when connecing to S3
-# The following often works for connecting to AWS services:
-# js_fetch_trusted_certificate /etc/ssl/certs/Amazon_Root_CA_1.pem;
diff --git a/common/etc/nginx/templates/gateway/s3_location.conf.template b/common/etc/nginx/templates/gateway/s3_location.conf.template
deleted file mode 100644
index 60d8726..0000000
--- a/common/etc/nginx/templates/gateway/s3_location.conf.template
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file is intentional left as blank.
-# Use this file to add additional configuration to the "location @s3"
-# block with default.conf.template
diff --git a/common/etc/nginx/templates/gateway/s3_server.conf.template b/common/etc/nginx/templates/gateway/s3_server.conf.template
deleted file mode 100644
index 9f6b0d2..0000000
--- a/common/etc/nginx/templates/gateway/s3_server.conf.template
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file is intentional left as blank.
-# Use this file to add additional configuration to the "server"
-# block with default.conf.template
diff --git a/common/etc/nginx/templates/gateway/s3listing_location.conf.template b/common/etc/nginx/templates/gateway/s3listing_location.conf.template
deleted file mode 100644
index 4157c6e..0000000
--- a/common/etc/nginx/templates/gateway/s3listing_location.conf.template
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file is intentional left as blank.
-# Use this file to add additional configuration to the "location @s3Listing"
-# block with default.conf.template
diff --git a/common/etc/nginx/templates/gateway/v2_headers.conf.template b/common/etc/nginx/templates/gateway/v2_headers.conf.template
deleted file mode 100644
index 5798b25..0000000
--- a/common/etc/nginx/templates/gateway/v2_headers.conf.template
+++ /dev/null
@@ -1,3 +0,0 @@
-# This header is needed when doing v2 signature authentication. It
-# specifies the timestamp in which the signature was generated.
-proxy_set_header Date $httpDate;
diff --git a/common/etc/nginx/templates/gateway/v2_js_vars.conf.template b/common/etc/nginx/templates/gateway/v2_js_vars.conf.template
deleted file mode 100644
index 04e9eda..0000000
--- a/common/etc/nginx/templates/gateway/v2_js_vars.conf.template
+++ /dev/null
@@ -1,4 +0,0 @@
-# This header is needed when doing v2 signature authentication. It
-# specifies the timestamp in which the signature was generated and is used with
-# the HTTP Date header.
-js_set $httpDate s3gateway.s3date;
diff --git a/common/etc/nginx/templates/gateway/v4_headers.conf.template b/common/etc/nginx/templates/gateway/v4_headers.conf.template
deleted file mode 100644
index c7d37bc..0000000
--- a/common/etc/nginx/templates/gateway/v4_headers.conf.template
+++ /dev/null
@@ -1,4 +0,0 @@
-# This header is needed when doing v4 signature authentication. It
-# specifies the timestamp in which the signature was generated.
-proxy_set_header x-amz-date $awsDate;
-proxy_set_header x-amz-content-sha256 $awsPayloadHash;
diff --git a/common/etc/nginx/templates/gateway/v4_js_vars.conf.template b/common/etc/nginx/templates/gateway/v4_js_vars.conf.template
deleted file mode 100644
index 631876e..0000000
--- a/common/etc/nginx/templates/gateway/v4_js_vars.conf.template
+++ /dev/null
@@ -1,5 +0,0 @@
-# This header is needed when doing v4 signature authentication. It
-# specifies the timestamp in which the signature was generated and is used with
-# the x-amz-date header.
-js_set $awsDate        lambdagateway.awsHeaderDate;
-js_set $awsPayloadHash awssig4.awsHeaderPayloadHash;
diff --git a/test/data/bucket-1/b/c/@ b/common/etc/ssl/.gitkeep
similarity index 100%
rename from test/data/bucket-1/b/c/@
rename to common/etc/ssl/.gitkeep
diff --git a/common/lambda-core/lambda_ngx_apis.conf b/common/lambda-core/lambda_ngx_apis.conf
new file mode 100644
index 0000000..1ab76dc
--- /dev/null
+++ b/common/lambda-core/lambda_ngx_apis.conf
@@ -0,0 +1,21 @@
+location /aws/credentials/retrieval {
+    internal;
+    js_content awscredentials.fetchCredentials;
+
+    # Enable if SSL Handshake error occurs when connecing to Lambda.
+    # js_fetch_trusted_certificate /etc/ssl/certs/Amazon_Root_CA_1.pem;
+}
+
+location @lambda_function_arn {
+    internal;
+    include "serverless/lambda_ngx_proxy.conf";
+    proxy_set_header Authorization $lambdaFunctionARNAuth;
+    proxy_pass $lambda_url$lambdaURI;
+}
+
+location @lambda_function_url {
+    internal;
+    include "serverless/lambda_ngx_proxy.conf";
+    proxy_set_header Authorization $lambdaFunctionURLAuth;
+    proxy_pass $lambda_url;
+}
diff --git a/common/lambda-core/lambda_ngx_http.conf b/common/lambda-core/lambda_ngx_http.conf
new file mode 100644
index 0000000..bc83b30
--- /dev/null
+++ b/common/lambda-core/lambda_ngx_http.conf
@@ -0,0 +1,28 @@
+js_import /etc/nginx/awssig/awscredentials.js;
+js_import /etc/nginx/awssig/awssig4.js;
+js_import /etc/nginx/serverless/lambdagateway.js;
+
+# This header is needed when doing v4 signature authentication. It
+# specifies the timestamp in which the signature was generated and is used with
+# the x-amz-date header.
+js_set $awsDate                 awssig4.awsHeaderDate;
+js_set $awsPayloadHash          awssig4.awsHeaderPayloadHash;
+js_set $awsSessionToken         awscredentials.sessionToken;
+js_set $lambdaFunctionARNAuth   lambdagateway.lambdaFunctionARNAuth;
+js_set $lambdaFunctionURLAuth   lambdagateway.lambdaFunctionURLAuth;
+js_set $lambdaFunctionARNHost   lambdagateway.lambdaFunctionARNHost;
+js_set $lambdaPort              lambdagateway.lambdaPort;
+js_set $lambdaProto             lambdagateway.lambdaProto;
+js_set $lambdaURI               lambdagateway.lambdaURI;
+js_set $lambdaURL               lambdagateway.lambdaURL;
+
+resolver 8.8.8.8;
+
+map_hash_bucket_size 128;
+
+# Extracts only the path from the requested URI. This strips out all query
+# parameters and anchors in order to prevent extraneous data from being sent
+# to Lambda.
+map $request_uri $uri_path {
+    "~^(?P<path>.*?)(\?.*)*$"  $path;
+}
diff --git a/common/lambda-core/lambda_ngx_proxy.conf b/common/lambda-core/lambda_ngx_proxy.conf
new file mode 100644
index 0000000..cf897a8
--- /dev/null
+++ b/common/lambda-core/lambda_ngx_proxy.conf
@@ -0,0 +1,26 @@
+# Don't allow any headers from the client to avoid messing with Lambda at all.
+proxy_pass_request_headers off;
+
+# Enable passing of the server name through TLS Server Name Indication extension.
+proxy_ssl_server_name on;
+proxy_ssl_name $lambda_host;
+
+# HTTP signed headers to include in the AWS signature.
+proxy_set_header x-amz-date           $awsDate;
+proxy_set_header x-amz-content-sha256 $awsPayloadHash;
+proxy_set_header x-amz-security-token $awsSessionToken;
+
+# Use keep alive connections to improve performance.
+proxy_http_version 1.1;
+proxy_set_header Connection '';
+
+# We strip off all of the AWS specific headers from the server so that there is
+# nothing identifying the object as having originated in the Lambda.
+js_header_filter lambdagateway.editHeaders;
+
+# Comment out to catch all errors from Lambda and sanitize them so that the user
+# can't gain intelligence about the Lambda being proxied.
+#proxy_intercept_errors on;
+
+# Comment out to receive the error messages returned by Lambda
+#error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 =404 @error404;
diff --git a/common/etc/nginx/include/lambdagateway.js b/common/lambda-core/lambdagateway.js
similarity index 60%
rename from common/etc/nginx/include/lambdagateway.js
rename to common/lambda-core/lambdagateway.js
index d48682d..46048a1 100644
--- a/common/etc/nginx/include/lambdagateway.js
+++ b/common/lambda-core/lambdagateway.js
@@ -14,9 +14,9 @@
  *  limitations under the License.
  */
 
-import awscred from "./awscredentials.js";
-import awssig4 from "./awssig4.js";
-import utils from "./utils.js";
+import awscred from "../awssig/awscredentials.js";
+import awssig4 from "../awssig/awssig4.js";
+import utils from "../awssig/utils.js";
 
 /**
  * Constant defining the service requests are being signed for.
@@ -24,56 +24,136 @@ import utils from "./utils.js";
  */
 const SERVICE = 'lambda';
 
-utils.requireEnvVar('LAMBDA_SERVER');
+utils.requireEnvVar('LAMBDA_REGION');
 utils.requireEnvVar('LAMBDA_SERVER_PROTO');
+utils.requireEnvVar('LAMBDA_SERVER');
 utils.requireEnvVar('LAMBDA_SERVER_PORT');
-utils.requireEnvVar('LAMBDA_REGION');
 
 
 /**
- * Creates an AWS authentication signature based on the global settings and
- * the passed request parameter.
+ * Creates an AWS authentication signature to invole Lambda Function ARN based
+ * on the global settings and the passed request parameter.
  *
  * @param r {Request} HTTP request object
  * @returns {string} AWS authentication signature
  */
-function lambdaAuth(r) {
+function lambdaFunctionARNAuth(r) {
     const host = process.env['LAMBDA_SERVER'];
     const region = process.env['LAMBDA_REGION'];
-    // const uri = '/2015-03-31/' + r.variables.request_uri + '/invocations';
-    r.log('#### URI for lambdaAuth(): ' + r.variables.request_uri)
     const queryParams = '';
     const credentials = awscred.readCredentials(r);
 
-    let signature = awssig4.signatureV4(
-        r, awscred.getNow(), region, SERVICE, 
+    const signature = awssig4.signatureV4(
+        r, awscred.getNow(), region, SERVICE,
         r.variables.request_uri, queryParams, host, credentials
     );
     return signature;
 }
 
 /**
- * Redirects the request to the appropriate location. 
+ * Creates an AWS authentication signature to invole Lambda Function URL based
+ * on the global settings and the passed request parameter.
+ *
+ * @param r {Request} HTTP request object
+ * @returns {string} AWS authentication signature
+ */
+function lambdaFunctionURLAuth(r) {
+    const host = r.variables.lambda_host ? r.variables.lambda_host : '';
+    const region = process.env['LAMBDA_REGION'];
+    const queryParams = '';
+    const credentials = awscred.readCredentials(r);
+    const requestURI = '/';
+
+    const signature = awssig4.signatureV4(
+        r, awscred.getNow(), region, SERVICE,
+        requestURI, queryParams, host, credentials
+    );
+    return signature;
+}
+
+/**
+ * Redirects the request to the appropriate location of AWS Lambda Function ARN.
+ *
+ * @param r {Request} HTTP request object
+ */
+function redirectToLambdaFunctionARN(r) {
+    r.internalRedirect("@lambda_function_arn");
+}
+
+/**
+ * Redirects the request to the AWS Lambda Function URL.
  *
  * @param r {Request} HTTP request object
  */
-function redirectToLambda(r) {
-    r.internalRedirect("@lambda");
+function redirectToLambdaFunctionURL(r) {
+    r.internalRedirect("@lambda_function_url");
 }
 
 /**
- * Returns the Lambda path given the incoming request
+ * Returns the Lambda path given the incoming request.
  *
  * @param r HTTP request
  * @returns {string} uri for Lambda request
  */
 function lambdaURI(r) {
-    let uriPath = r.variables.uri_path;
-    let path = _escapeURIPath(uriPath);
+    const uriPath = r.variables.uri_path ? r.variables.uri_path : '/';
+    const path = _escapeURIPath(uriPath);
     utils.debug_log(r, 'AWS Lambda Request URI: ' + path);
     return path;
 }
 
+/**
+ * Returns the host of Lambda Function ARN.
+ *
+ * @param r HTTP request
+ * @returns {string} host of Lambda Function ARN
+ */
+function lambdaFunctionARNHost(r) {
+    return process.env['LAMBDA_SERVER'];
+}
+
+/**
+ * Returns the protocol of Lambda Function ARN/URL.
+ *
+ * @param r HTTP request
+ * @returns {string} protocol of Lambda Function ARN/URL
+ */
+function lambdaProto(r) {
+    const proto = process.env['LAMBDA_SERVER_PROTO'];
+    utils.debug_log(r, 'AWS Lambda Server Protocol: ' + proto);
+    return proto;
+}
+
+/**
+ * Returns the port of Lambda Function ARN/URL.
+ *
+ * @param r HTTP request
+ * @returns {string} port of Lambda Function ARN/URL
+ */
+function lambdaPort(r) {
+    const port = process.env['LAMBDA_SERVER_PORT'];
+    utils.debug_log(r, 'AWS Lambda Server Port: ' + port);
+    return port;
+}
+
+/**
+ * Returns the Lambda URL given the environment variables.
+ *
+ * @param r HTTP request
+ * @returns {string} URL for Lambda request
+ */
+function lambdaURL(r) {
+    const proto = process.env['LAMBDA_SERVER_PROTO'];
+    const server = process.env['LAMBDA_SERVER'];
+    const port = process.env['LAMBDA_SERVER_PORT'];
+
+    // Generate lambda URL using env variables as the following example:
+    //   "https://lambda.us-east-2.amazonaws.com";
+    const url = `${proto}://${server}:${port}`; 
+    utils.debug_log(r, 'AWS Lambda Request URL: ' + url);
+    return url;
+}
+
 /**
  * Flag indicating debug mode operation. If true, additional information
  * about signature generation will be logged.
@@ -82,12 +162,6 @@ function lambdaURI(r) {
 
 const ADDITIONAL_HEADER_PREFIXES_TO_STRIP = utils.parseArray(process.env['HEADER_PREFIXES_TO_STRIP']);
 
-/**
- * Default filename for index pages to be read off of the backing object store.
- * @type {string}
- */
-const INDEX_PAGE = "index.html";
-
 /**
  * Transform the headers returned from Lambda such that there isn't information
  * leakage about Lambda and do other tasks needed for appropriate gateway output.
@@ -128,37 +202,10 @@ function _isHeaderToBeStripped(headerName, additionalHeadersToStrip) {
     return false;
 }
 
-/**
- * Outputs the timestamp used to sign the request, so that it can be added to
- * the 'Date' header and sent by NGINX.
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} RFC2616 timestamp
- */
-function lambdaDate(r) {
-    return awscred.getNow().toUTCString();
-}
-
-/**
- * Outputs the timestamp used to sign the request, so that it can be added to
- * the 'x-amz-date' header and sent by NGINX. The output format is
- * ISO 8601: YYYYMMDD'T'HHMMSS'Z'.
- * @see {@link https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html | Handling dates in Signature Version 4}
- *
- * @param r {Request} HTTP request object (not used, but required for NGINX configuration)
- * @returns {string} ISO 8601 timestamp
- */
-function awsHeaderDate(r) {
-    return utils.getAmzDatetime(
-        awscred.getNow(), 
-        utils.getEightDigitDate(awscred.getNow())
-    );
-}
-
 function trailslashControl(r) {
     if (APPEND_SLASH) {
         const hasExtension = /\/[^.\/]+\.[^.]+$/;
-        if (!hasExtension.test(r.variables.uri_path)  && !_isDirectory(r.variables.uri_path)){
+        if (!hasExtension.test(r.variables.uri_path) && !_isDirectory(r.variables.uri_path)) {
             return r.internalRedirect("@trailslash");
         }
     }
@@ -221,12 +268,16 @@ function _isDirectory(path) {
 
 
 export default {
-    awsHeaderDate,
     editHeaders,
-    lambdaAuth,
-    lambdaDate,
+    lambdaFunctionARNAuth,
+    lambdaFunctionARNHost,
+    lambdaFunctionURLAuth,
+    lambdaPort,
+    lambdaProto,
     lambdaURI,
-    redirectToLambda,
+    lambdaURL,
+    redirectToLambdaFunctionARN,
+    redirectToLambdaFunctionURL,
     trailslashControl,
     // These functions do not need to be exposed, but they are exposed so that
     // unit tests can run against them.
diff --git a/common/lambda-emulator/Dockerfile b/common/lambda-emulator/Dockerfile
new file mode 100644
index 0000000..dae080b
--- /dev/null
+++ b/common/lambda-emulator/Dockerfile
@@ -0,0 +1,13 @@
+FROM public.ecr.aws/lambda/python:3.8
+
+# Install the function's dependencies using file requirements.txt
+# from your project folder.
+
+COPY requirements.txt  .
+RUN  pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
+
+# Copy function code
+COPY app/lambda_function.py ${LAMBDA_TASK_ROOT}
+
+# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
+CMD [ "lambda_function.lambda_handler" ] 
diff --git a/common/lambda-emulator/Makefile b/common/lambda-emulator/Makefile
new file mode 100644
index 0000000..21f28ce
--- /dev/null
+++ b/common/lambda-emulator/Makefile
@@ -0,0 +1,16 @@
+start:
+	docker-compose up -d
+
+ps:
+	docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Names}}"
+
+watch:
+	watch 'docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Names}}"'
+
+down:
+	docker-compose down
+
+clean: 
+	docker kill $$(docker ps -q) 2> /dev/null || true
+	docker system prune -a
+	docker volume rm $(docker volume ls -qf dangling=true)
diff --git a/common/lambda-emulator/README.md b/common/lambda-emulator/README.md
new file mode 100644
index 0000000..5250ff5
--- /dev/null
+++ b/common/lambda-emulator/README.md
@@ -0,0 +1,58 @@
+# AWS Lambda Runtime Interface Emulator
+
+The **AWS Lambda Runtime Interface Emulator (RIE)** is a proxy for the Lambda Runtime API that allows you to locally test your Lambda function packaged as a container image. The emulator is a lightweight web server that converts HTTP requests into JSON events to pass to the Lambda function in the container image.
+
+> Note: The RIE does not emulate **Lambda’s security and authentication configurations**, or Lambda orchestration.
+
+
+## Getting Started
+
+- **Implement a Lambda Function:**
+  
+  e.g., [`app/lambda_function.py`](./app/lambda_function.py):
+
+  ```python
+    import json
+
+    def lambda_handler(event, context):
+        return {
+            'statusCode': 200,
+            'body': {
+                'request': event,
+                'response': 'Hello from NGINX Lambda Gateway Emulator!'
+            }
+        }
+  ```
+
+- **Start a Lambda Emulator:**
+  ```bash
+  make start
+  ```
+
+- **Check if Lambda Emulator is started:**
+  ```bash
+  make watch
+  ```
+  ![](../../docs/img/lambda_emulator.png)
+
+- **Test a function via Lambda Emulator:**
+  ```bash
+  curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"message": "This is to test a Lambda Function ARN."}'
+
+  curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
+  ```
+
+- **Stop a Lambda Emulator:**
+  ```bash
+  make down
+  ```
+
+- **Clean Lambda Emulator Container Image:**
+  ```bash
+  make clean
+  ```
+
+## References
+- [Testing Lambda container images locally](https://docs.aws.amazon.com/lambda/latest/dg/images-test.html)
+- [Using AWS Lambda environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html)
+- [GitHub: AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator)
diff --git a/common/lambda-emulator/app/lambda_function.py b/common/lambda-emulator/app/lambda_function.py
new file mode 100644
index 0000000..4c58d44
--- /dev/null
+++ b/common/lambda-emulator/app/lambda_function.py
@@ -0,0 +1,10 @@
+import json
+
+def lambda_handler(event, context):
+    return {
+        'statusCode': 200,
+        'body': {
+            'request': event,
+            'response': 'Hello from NGINX Lambda Gateway Emulator - /foo!'
+        }
+    }
diff --git a/common/lambda-emulator/docker-compose.yml b/common/lambda-emulator/docker-compose.yml
new file mode 100644
index 0000000..0ac5373
--- /dev/null
+++ b/common/lambda-emulator/docker-compose.yml
@@ -0,0 +1,23 @@
+version: '3'
+services:
+
+  lambda_emulator:
+    hostname: lambda_emulator
+    container_name: lambda_emulator
+    image: lambda_emulator
+    build:
+      context: ./
+      dockerfile: Dockerfile
+    env_file:
+      - settings.env
+    volumes:
+      - type: bind
+        source: ./app
+        target: /var/task/
+    ports:
+      - "9000:8080"
+    networks:
+      - mynetwork
+
+networks:
+  mynetwork:
diff --git a/test/data/bucket-1/statichost/noindexdir/multipledir/index.html b/common/lambda-emulator/requirements.txt
similarity index 100%
rename from test/data/bucket-1/statichost/noindexdir/multipledir/index.html
rename to common/lambda-emulator/requirements.txt
diff --git a/common/lambda-emulator/settings.env b/common/lambda-emulator/settings.env
new file mode 100644
index 0000000..7624d52
--- /dev/null
+++ b/common/lambda-emulator/settings.env
@@ -0,0 +1,5 @@
+AWS_ACCESS_KEY_ID=aaaaa
+AWS_SECRET_ACCESS_KEY=bbbbb
+AWS_SESSION_TOKEN=ccccc
+AWS_REGION=us-east-2
+AWS_LAMBDA_FUNCTION_NAME=foo
diff --git a/deployments/ecs/cloudformation/s3gateway.yaml b/deployments/ecs/cloudformation/s3gateway.yaml
deleted file mode 100644
index a64bb2d..0000000
--- a/deployments/ecs/cloudformation/s3gateway.yaml
+++ /dev/null
@@ -1,263 +0,0 @@
-AWSTemplateFormatVersion: '2010-09-09'
-Parameters:
-  NewBucketName:
-    Default: <ENTER_RANDOM_BUCKET_NAME_HERE>
-    Description: S3 Bucket Name
-    Type: String
-  Subnet1:
-    Default: <ENTER_YOUR_VALUE_HERE>
-    Description: ID of the first subnet to be used for resources
-    Type: String
-  Subnet2:
-    Default: <ENTER_YOUR_VALUE_HERE>
-    Description: ID of the second subnet to be used for resources
-    Type: String
-  VpcId:
-    Default: <ENTER_YOUR_VALUE_HERE>
-    Description: ID of the VPC to be used for resources
-    Type: String
-  ContainerName:
-    Default: s3gateway
-    Description: Name of the NGINX Container. No need to change this
-    Type: String
-  ResourceNamePrefix:
-    Default: nginx-s3-gateway
-    Description: Common prefix used for resource names. No need to change this
-    Type: String
-Outputs:
-  PublicDNS:
-    Description: DNS name of load balancer
-    Value: !GetAtt 'ALB.DNSName'
-Resources:
-  ALB:
-    Properties:
-      Name: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - alb
-      SecurityGroups:
-        - !GetAtt 'S3GatewaySG.GroupId'
-      SubnetMappings:
-        - SubnetId: !Ref 'Subnet1'
-        - SubnetId: !Ref 'Subnet2'
-      Type: application
-    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
-  ALBHttpListener:
-    Properties:
-      DefaultActions:
-        - ForwardConfig:
-            TargetGroups:
-              - TargetGroupArn: !Ref 'ALBTargetGroup'
-          Type: forward
-      LoadBalancerArn: !Ref 'ALB'
-      Port: 80
-      Protocol: HTTP
-    Type: AWS::ElasticLoadBalancingV2::Listener
-  ALBTargetGroup:
-    Properties:
-      Name: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - log-group
-      Port: 80
-      Protocol: HTTP
-      ProtocolVersion: HTTP1
-      TargetGroupAttributes:
-        - Key: deregistration_delay.timeout_seconds
-          Value: '150'
-      TargetType: ip
-      VpcId: !Ref 'VpcId'
-    Type: AWS::ElasticLoadBalancingV2::TargetGroup
-  Cluster:
-    Properties:
-      ClusterName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - cluster
-    Type: AWS::ECS::Cluster
-  ECSLogGroup:
-    Properties:
-      LogGroupName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - logs
-      RetentionInDays: 14
-    Type: AWS::Logs::LogGroup
-  ECSTaskExecutionPolicy:
-    Properties:
-      PolicyDocument:
-        Statement:
-          - Action:
-              - logs:CreateLogStream
-              - logs:CreateLogGroup
-              - logs:PutLogEvents
-            Effect: Allow
-            Resource:
-              - '*'
-        Version: '2012-10-17'
-      PolicyName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - ecs-task-execution-policy
-      Roles:
-        - !Ref 'ECSTaskExecutionRole'
-    Type: AWS::IAM::Policy
-  ECSTaskExecutionRole:
-    Properties:
-      AssumeRolePolicyDocument:
-        Statement:
-          - Action:
-              - sts:AssumeRole
-            Effect: Allow
-            Principal:
-              Service:
-                - ecs-tasks.amazonaws.com
-        Version: '2012-10-17'
-      Description: An IAM role to enable ECS agents to perform AWS operations such as creating CloudWatch logs.
-      RoleName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - ecs-task-execution-role
-    Type: AWS::IAM::Role
-  ECSTaskPolicy:
-    Properties:
-      PolicyDocument:
-        Statement:
-          - Action:
-              - s3:GetObject
-              - s3:ListBucket
-            Effect: Allow
-            Resource:
-              - !Sub
-                - arn:aws:s3:::${bucketName}/*
-                - bucketName: !Ref 'NewBucketName'
-              - !Sub
-                - arn:aws:s3:::${bucketName}
-                - bucketName: !Ref 'NewBucketName'
-        Version: '2012-10-17'
-      PolicyName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - ecs-task-policy
-      Roles:
-        - !Ref 'ECSTaskRole'
-    Type: AWS::IAM::Policy
-  ECSTaskRole:
-    Properties:
-      AssumeRolePolicyDocument:
-        Statement:
-          - Action:
-              - sts:AssumeRole
-            Effect: Allow
-            Principal:
-              Service:
-                - ecs-tasks.amazonaws.com
-        Version: '2012-10-17'
-      Description: An IAM role to enable ECS containers to perform AWS operations such as accessing S3 buckets.
-      RoleName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - ecs-task-role
-    Type: AWS::IAM::Role
-  S3Bucket:
-    Properties:
-      BucketName: !Ref 'NewBucketName'
-    Type: AWS::S3::Bucket
-  S3GatewaySG:
-    Properties:
-      GroupDescription: Security group for NGINX S3 Gateway Infra
-      GroupName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - sg
-      SecurityGroupEgress:
-        - CidrIp: '0.0.0.0/0'
-          Description: Allow all outbound IPv4 traffic
-          IpProtocol: '-1'
-        - CidrIpv6: ::/0
-          Description: Allow all outbound IPv6 traffic
-          IpProtocol: '-1'
-      SecurityGroupIngress:
-        - CidrIp: '0.0.0.0/0'
-          Description: Allow HTTP Traffic on 80
-          FromPort: 80
-          IpProtocol: tcp
-          ToPort: 80
-        - CidrIp: '0.0.0.0/0'
-          Description: Allow HTTPS Traffic on 443
-          FromPort: 443
-          IpProtocol: tcp
-          ToPort: 443
-      VpcId: !Ref 'VpcId'
-    Type: AWS::EC2::SecurityGroup
-  S3GatewayService:
-    DependsOn: ALBHttpListener
-    Properties:
-      Cluster: !Ref 'Cluster'
-      DesiredCount: 1
-      LaunchType: FARGATE
-      LoadBalancers:
-        - ContainerName: !Ref 'ContainerName'
-          ContainerPort: 80
-          TargetGroupArn: !Ref 'ALBTargetGroup'
-      NetworkConfiguration:
-        AwsvpcConfiguration:
-          AssignPublicIp: ENABLED
-          SecurityGroups:
-            - !GetAtt 'S3GatewaySG.GroupId'
-          Subnets:
-            - !Ref 'Subnet1'
-            - !Ref 'Subnet2'
-      ServiceName: !Join
-        - '-'
-        - - !Ref 'ResourceNamePrefix'
-          - service
-      TaskDefinition: !Ref 'TaskDefinition'
-    Type: AWS::ECS::Service
-  TaskDefinition:
-    DependsOn: S3Bucket
-    Properties:
-      ContainerDefinitions:
-        - Environment:
-            - Name: ALLOW_DIRECTORY_LIST
-              Value: 'true'
-            - Name: AWS_SIGS_VERSION
-              Value: '4'
-            - Name: S3_BUCKET_NAME
-              Value: !Ref 'S3Bucket'
-            - Name: S3_REGION
-              Value: !Ref 'AWS::Region'
-            - Name: S3_SERVER_PORT
-              Value: '443'
-            - Name: S3_SERVER_PROTO
-              Value: https
-            - Name: S3_SERVER
-              Value: !Join
-                - .
-                - - s3
-                  - !Ref 'AWS::Region'
-                  - amazonaws.com
-            - Name: S3_STYLE
-              Value: default
-            - Name: S3_DEBUG
-              Value: 'false'
-          Image: ghcr.io/nginxinc/nginx-s3-gateway/nginx-oss-s3-gateway:latest-njs-oss
-          LogConfiguration:
-            LogDriver: awslogs
-            Options:
-              awslogs-group: !Ref 'ECSLogGroup'
-              awslogs-region: !Ref 'AWS::Region'
-              awslogs-stream-prefix: ecs
-          Name: !Ref 'ContainerName'
-          PortMappings:
-            - ContainerPort: 80
-              HostPort: 80
-      Cpu: '1024'
-      ExecutionRoleArn: !GetAtt 'ECSTaskExecutionRole.Arn'
-      Family: !Ref 'ContainerName'
-      Memory: '2048'
-      NetworkMode: awsvpc
-      RequiresCompatibilities:
-        - FARGATE
-      TaskRoleArn: !GetAtt 'ECSTaskRole.Arn'
-    Type: AWS::ECS::TaskDefinition
diff --git a/docker-compose.yml b/docker-compose.yml
index 23873c7..ceb3a0a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,23 +1,21 @@
 version: '3'
 services:
-
-  nplus_lambda_gateway:
-    hostname: nplus_lambda_gateway
-    container_name: nplus_lambda_gateway
-    image: nplus_lambda_gateway
+  nginx_lambda_gateway:
+    hostname: nginx_lambda_gateway
+    container_name: nginx_lambda_gateway
+    image: nginx_lambda_gateway
     build:
       context: ./
-      dockerfile: Dockerfile.plus
-    env_file:
-      - settings.test
+      # Enable this when using NGINX OSS
+      dockerfile: docker/Dockerfile.oss
+      
+      # Enable this when using NGINX Plus
+      # dockerfile: docker/Dockerfile.plus
     volumes:
-      - type: bind
-        source: ./common/etc/nginx/include/
-        target: /etc/nginx/include/
+      - ./common/etc/nginx/conf.d:/etc/nginx/conf.d
+      - ./common/lambda-core:/etc/nginx/serverless
+      - ./common/awssig/core:/etc/nginx/awssig
     ports:
-      - "81:80"
-    networks:
-      - mynetwork
-
-networks:
-  mynetwork:
+      - "80:80"
+    env_file:
+      - settings.env
diff --git a/docker/Dockerfile.oss b/docker/Dockerfile.oss
new file mode 100644
index 0000000..2e4c42b
--- /dev/null
+++ b/docker/Dockerfile.oss
@@ -0,0 +1,16 @@
+FROM nginx
+
+LABEL maintainer="Shawn"
+
+RUN mkdir -p /etc/nginx/serverless && \
+    mkdir -p /etc/nginx/conf.d  
+
+RUN chmod -R 644 /etc/nginx
+RUN chmod -R 644 /etc/nginx/serverless
+RUN chmod -R 644 /etc/nginx/conf.d
+
+COPY  common/lambda-core/*          /etc/nginx/serverless/
+COPY  common/etc/nginx/nginx.conf   /etc/nginx/
+
+STOPSIGNAL SIGTERM
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/docker/Dockerfile.plus b/docker/Dockerfile.plus
new file mode 100644
index 0000000..be0eaac
--- /dev/null
+++ b/docker/Dockerfile.plus
@@ -0,0 +1,91 @@
+FROM debian:bullseye-slim
+
+LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
+
+# Define NGINX versions for NGINX Plus and NGINX Plus modules
+# Uncomment this block and the versioned nginxPackages block in the main RUN
+# instruction to install a specific release
+ENV NGINX_VERSION   28
+ENV NJS_VERSION     0.7.10
+ENV PKG_RELEASE     1~bullseye
+
+RUN  mkdir -p /etc/ssl/nginx
+COPY common/ssl/*.crt /etc/ssl/nginx/
+COPY common/ssl/*.key /etc/ssl/nginx/
+
+RUN set -x \
+    # Create nginx user/group first, to be consistent throughout Docker variants
+    && addgroup --system --gid 101 nginx \
+    && adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \
+    && apt-get update \
+    && apt-get install --no-install-recommends --no-install-suggests -y \
+    ca-certificates \
+    gnupg1 \
+    lsb-release \
+    vim \
+    && \
+    NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
+    found=''; \
+    for server in \
+    hkp://keyserver.ubuntu.com:80 \
+    pgp.mit.edu \
+    ; do \
+    echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
+    apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
+    done; \
+    test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
+    apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
+    # Install the latest release of NGINX Plus and/or NGINX Plus modules
+    # Uncomment individual modules if necessary
+    # Use versioned packages over defaults to specify a release
+    && nginxPackages=" \
+    nginx-plus \
+    # nginx-plus=${NGINX_VERSION}-${PKG_RELEASE} \
+    # nginx-plus-module-xslt \
+    # nginx-plus-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} \
+    # nginx-plus-module-geoip \
+    # nginx-plus-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} \
+    # nginx-plus-module-image-filter \
+    # nginx-plus-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} \
+    # nginx-plus-module-perl \
+    # nginx-plus-module-perl=${NGINX_VERSION}-${PKG_RELEASE} \
+    nginx-plus-module-njs \
+    nginx-plus-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} \
+    " \
+    && echo "Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";" > /etc/apt/apt.conf.d/90nginx \
+    && echo "Acquire::https::pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx \
+    && echo "Acquire::https::pkgs.nginx.com::SslCert     \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx \
+    && echo "Acquire::https::pkgs.nginx.com::SslKey      \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx \
+    && printf "deb https://pkgs.nginx.com/plus/debian `lsb_release -cs` nginx-plus\n" > /etc/apt/sources.list.d/nginx-plus.list \
+    # && mkdir -p /etc/ssl/nginx \
+    # && cat nginx-repo.crt > /etc/ssl/nginx/nginx-repo.crt \
+    # && cat nginx-repo.key > /etc/ssl/nginx/nginx-repo.key \
+    && apt-get update \
+    && apt-get install --no-install-recommends --no-install-suggests -y \
+    $nginxPackages \
+    curl \
+    gettext-base \
+    && apt-get remove --purge -y lsb-release \
+    && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx-plus.list \
+    && rm -rf /etc/apt/apt.conf.d/90nginx /etc/ssl/nginx \
+    # Forward request logs to Docker log collector
+    && ln -sf /dev/stdout /var/log/nginx/access.log \
+    && ln -sf /dev/stderr /var/log/nginx/error.log
+
+RUN mkdir -p /etc/nginx/conf.d         \
+    mkdir -p /etc/nginx/awssig      && \
+    mkdir -p /etc/nginx/serverless  && \
+    mkdir -p /etc/nginx/status 
+
+RUN chmod -R 644 /etc/nginx
+RUN chmod -R 644 /etc/nginx/awssig
+RUN chmod -R 644 /etc/nginx/serverless
+RUN chmod -R 644 /etc/nginx/conf.d
+
+COPY  common/awssig/core/*          /etc/nginx/awssig/
+COPY  common/lambda-core/*          /etc/nginx/serverless/
+COPY  common/etc/nginx/nginx.conf   /etc/nginx/
+
+STOPSIGNAL SIGQUIT
+
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/docs/development.md b/docs/development.md
index 35a27ef..e4be3f0 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -1,65 +1,94 @@
 # Development Guide
 
-## Integrating with AWS Signature
-
-Update the following files when enhancing `nginx-s3-gateway` to integrate with AWS signature whenever AWS releases a new version of signature or you have a new PR:
-
-- NGINX Proxy: [`/etc/nginx/conf.d/default.conf`](/common/etc/nginx/templates/gateway/s3_location.conf.template)
-- AWS Credentials Lib: [`/etc/nginx/include/awscredentials.js`](/common/etc/nginx/include/awscredentials.js)
-  > Note: The `fetchCredentials()` is going to be part of here soon.
-
-- AWS Signature Lib per version:
-  - [`/etc/nginx/include/awssig2.js`](/common/etc/nginx/include/awssig2.js)
-  - [`/etc/nginx/include/awssig4.js`](/common/etc/nginx/include/awssig4.js)
+- [Integrating with AWS Signature](#integrating-with-aws-signature)
+- [Enhancing the Gateway](#enhancing-the-gateway)
+  - [Enhancing gateway configuration](#enhancing-gateway-configuration)
+  - [Examples](#examples)
 
-- Lambda Integration Lib: [`/etc/nginx/include/lambdagateway.js`](/common/etc/nginx/include/lambdagateway.js)
-- Common Lib for all of NJS: [`/etc/nginx/include/utils.js`](/common/etc/nginx/include/utils.js)
 
-![](./img/nginx-s3-gateway-signature-flow.png)
-
-## Extending the Gateway
+## Integrating with AWS Signature
 
-### Extending gateway configuration via container images
+Update the following files when enhancing `nginx-lambda-gateway` to integrate with AWS signature whenever AWS releases a new version of signature or you have a new PR:
 
-#### `conf.d` Directory
+- NGINX Proxy: [`/etc/nginx/conf.d/nginx_lambda_gateway.conf`](../common/etc/nginx/conf.d/nginx_lambda_gateway.conf)
+- AWS Credentials Lib: [`/etc/nginx/serverless/awscredentials.js`](../common/lambda-core/awscredentials.js)
+- AWS Signature Lib per version:
+  - [`/etc/nginx/include/awssig4.js`](../common/lambda-core/awssig4.js)
+- AWS Lambda Integration Lib: [`/etc/nginx/serverless/lambdagateway.js`](../common/lambda-core/lambdagateway.js)
+- Common reusable Lib for all of NJS codebases: [`/etc/nginx/serverless/utils.js`](../common/lambda-core/utils.js)
 
-On the container image, all files with the extension `.conf` in the 
-directory `/etc/nginx/conf.d` will be loaded into the configuration
-of the base `http` block within the main NGINX configuration.
+![](../docs/img/nginx-lambda-gateway-aws-signature-integration.png)
 
-This allows for extension of the configuration by adding additional
-configuration files into the container image extending the base
-gateway image.
+## Enhancing the Gateway
 
-#### Stub Files
+### Enhancing gateway configuration
 
-On the container image there are three NGINX configuration stub files:
+All files with the extension `.conf` in the directory of `/etc/nginx/conf.d` and `/etc/nginx/serverless` will be loaded into the configuration of the base `http` block within the `/etc/nginx/nginx.conf` of main NGINX configuration.
 
-* [`/etc/nginx/conf.d/s3_server.conf`](/common/etc/nginx/templates/gateway/s3_location.conf.template)
-* [`/etc/nginx/conf.d/s3_location.conf`](/common/etc/nginx/templates/gateway/s3_server.conf.template) 
-* [`/etc/nginx/conf.d/s3listing_location.conf`](/common/etc/nginx/templates/gateway/s3listing_location.conf.template)
+To enhance the feature of `nginx-lambda-gateway`, additional configuration or enhancements can be altered in the following files before either building the container image or Systemd service:
 
-Each of these files can be overwritten in a container image that inherits
-from the S3 Gateway container image, so that additional NGINX configuration
-directives can be inserted into the gateway configuration.
+- NGINX Lambda Gateway main configuration: [`/etc/nginx/conf.d/nginx_lambda_gateway.conf`](../common/etc/nginx/conf.d/nginx_lambda_gateway.conf)
+- NGINX API gateway configuration for AWS Lambda integration: [`/etc/nginx/serverless/lambda_ngx_apis.conf`](../common/lambda-core/lambda_ngx_apis.conf)
+- NGINX configuration of importing NJS codebases and map directives for AWS Lambda integration: [`/etc/nginx/serverless/lambda_ngx_http.conf`](../common/lambda-core/lambda_ngx_http.conf)
+- NGINX proxy configuration prior to invoking AWS Lambda Functions: [`/etc/nginx/serverless/lambda_ngx_proxy.conf`](../common/lambda-core/lambda_ngx_proxy.conf)
 
 ### Examples
 
-In the [examples/ directory](/examples), there are `Dockerfile` examples that 
-show how to extend the base functionality of the NGINX S3 Gateway by adding
-additional modules.
-
-* [Enabling Brotli Compression in Docker](/examples/brotli-compression)
-* [Enabling GZip Compression in Docker](/examples/gzip-compression)
-* [Installing Modsecurity in Docker](/examples/modsecurity)
+In the [`examples/`](../examples/) directory, there are several use cases that show how to extend the base functionality of the NGINX Lambda Gateway by adding additional configuration and modules.
+
+- [`nginx-lambda-gateway` proxy's '/' location to all AWS Lambda Function ARNs](../examples/01-all-lambda-function-arns/)
+  ```bash
+  make start-01
+  curl --location --request POST 'http://localhost/2015-03-31/functions/foo/invocations'
+  curl --location 'http://localhost/2015-03-31/functions/quota-notification/invocations' \
+       --header 'Content-Type: application/json' \
+       --data '{ 
+                  "userId": "user-01",
+                  "message": "The user'\''s API quota has been exhausted" 
+               }'
+  make down-01
+  make clean
+  ```
+
+- [`nginx-lambda-gateway` proxy's one API endpoint to one AWS Lambda Function ARN](../examples/02-one-lambda-function-arn/)
+  ```bash
+  make start-02
+  curl --location 'http://localhost/2015-03-31/functions/foo/invocations' \
+       --header 'Content-Type: application/json'                          \
+       --data '{"message": "This is a sample message"}'
+  make down-02
+  make clean
+  ```
+
+- [`nginx-lambda-gateway` proxy's one API endpoint to one AWS Lambda Function URL](../examples/03-one-lambda-function-url/)
+  ```bash
+  make start-03
+  curl --location 'http://localhost/bar'           \
+       --header   'Content-Type: application/json' \
+       --data     '{ "message": "This is a sample message" }'
+  make down-03
+  make clean
+  ```
+
+- [`nginx-lambda-gateway` proxy to both of AWS Lambda Function ARN(s) and URL(s)](../examples/04-lambda-function-arn-url/)
+  ```bash
+  make start-04
+  curl --location --request POST 'http://localhost/2015-03-31/functions/foo/invocations'
+  curl --location --request POST 'http://localhost/2015-03-31/functions/bar/invocations'
+  curl --location 'http://localhost/2015-03-31/functions/foo/invocations' \
+       --header 'Content-Type: application/json'                          \
+       --data '{"message": "This is a sample message"}'
+  curl --location 'http://localhost/bar'           \
+       --header   'Content-Type: application/json' \
+       --data     '{ "message": "This is a sample message" }'
+  make down-04
+  make clean
+  ```
+
+- (TBD) Adding OIDC authentication into the `nginx-lambda-gateway`.
+- (TBD) Rate Limiting to the `nginx-lambda-gateway`.
+- (TBD) Protecting `nginx-lambda-gateway` with WAF.
 
 ## Testing
 
-Automated tests require `docker`, `docker-compose`, `curl` and `md5sum` to be
-installed. To run all unit tests and integration tests, run the following command.
-If you invoke the test script with a plus parameter, you will need to add your
-NGINX repository keys to the `plus/etc/ssl/nginx` directory
-
-```
-$ ./test.sh <nginx type - 'oss', 'latest-njs-oss', 'unprivileged', 'plus', or 'latest-njs-plus'>
-```
+- TBD for unit-test and integration-test
diff --git a/docs/getting_started.md b/docs/getting_started.md
index ebb7e6c..0df0e41 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -1,382 +1,154 @@
 # Getting Started Guide
 
-## Contents
+**TABLE OF CONTENTS:**
+- [Prerequisites](#prerequisites)
+- [Quick Starter: Running in Your Laptop](#quick-starter-running-in-your-laptop)
+- [Running as a Systemd Service](#running-as-a-systemd-service)
+- [Running in Containers](#running-in-containers)
+- [Running Using AWS Instance Profile Credentials](#running-using-aws-instance-profile-credentials)
+- [Troubleshooting](#troubleshooting)
+
+## Prerequisites
+- Update a submodule of `nginx-aws-signature` library
+  
+  ```bash
+  make submodule
+  ```
 
-[Configuration](#configuration)  
-[Running as a Systemd Service](#running-as-a-systemd-service)  
-[Running in Containers](#running-in-containers)  
-[Running Using AWS Instance Profile Credentials](#running-using-aws-instance-profile-credentials)  
-[Troubleshooting](#troubleshooting)  
+- Create a AWS Lambda Function
+  
+  ![](../docs/img/lambda-func-creation.png)
 
-## Configuration
+- Implement and devploy a [AWS Lambda Function](../examples/01-all-lambda-function-arns/lambda_functions/foo.py)
 
-The following environment variables are used to configure the gateway when
-running as a Container or as a Systemd service.
+  ![](../docs/img/lambda-func-deployment.png)
 
-| Name                                  | Required? | Allowed Values               | Default   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                           |
-| ------------------------------------- | --------- | ---------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `ALLOW_DIRECTORY_LIST`                | Yes       | `true`, `false`              | `false`   | Flag enabling directory listing                                                                                                                                                                                                                                                                                                                                                                                                                       |
-| `AWS_SIGS_VERSION`                    | Yes       | 2, 4                         |           | AWS Signatures API version                                                                                                                                                                                                                                                                                                                                                                                                                            |
-| `AWS_ACCESS_KEY_ID`                    | Yes       |                              |           | Access key                                                                                                                                                                                                                                                                                                                                                                                                                                            |
-| `AWS_SECRET_ACCESS_KEY`                       | Yes       |                              |           | Secret access key                                                                                                                                                                                                                                                                                                                                                                                                                                     |
-| `AWS_SESSION_TOKEN`                       | No        |                              |           | Session token.                                                                                                                                                                                                                                                                                                                                                                                                                                      |
-| `S3_BUCKET_NAME`                      | Yes       |                              |           | Name of S3 bucket to proxy requests to                                                                                                                                                                                                                                                                                                                                                                                                                |
-| `S3_REGION`                           | Yes       |                              |           | Region associated with API                                                                                                                                                                                                                                                                                                                                                                                                                            |
-| `S3_SERVER_PORT`                      | Yes       |                              |           | SSL/TLS port to connect to                                                                                                                                                                                                                                                                                                                                                                                                                            |
-| `S3_SERVER_PROTO`                     | Yes       | `http`, `https`              |           | Protocol to used connect to S3 server                                                                                                                                                                                                                                                                                                                                                                                                                 |
-| `S3_SERVER`                           | Yes       |                              |           | S3 host to connect to                                                                                                                                                                                                                                                                                                                                                                                                                                 |
-| `S3_STYLE`                            | Yes       | `virtual`, `path`, `default` | `default` | The S3 host/path method. <li>`virtual` is the method that that uses DNS-style bucket+hostname:port. This is the `default` value. <li>`path` is a method that appends the bucket name as the first directory in the URI's path. This method is used by many S3 compatible services. <br/><br/>See this [AWS blog article](https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/) for further information.            |
-| `S3_DEBUG`                            | No        | `true`, `false`              | `false`   | Flag enabling AWS signatures debug output                                                                                                                                                                                                                                                                                                                                                                                                             |
-| `APPEND_SLASH_FOR_POSSIBLE_DIRECTORY` | No        | `true`, `false`              | `false`   | Flag enabling the return a 302 with a `/` appended to the path. This is independent of the behavior selected in `ALLOW_DIRECTORY_LIST` or `PROVIDE_INDEX_PAGE`.                                                                                                                                                                                                                                                                                       |
-| `DNS_RESOLVERS`                       | No        |                              |           | DNS resolvers (separated by single spaces) to configure NGINX with                                                                                                                                                                                                                                                                                                                                                                                    |
-| `PROXY_CACHE_VALID_OK`                | No        |                              |           | Sets caching time for response code 200 and 302                                                                                                                                                                                                                                                                                                                                                                                                       |
-| `PROXY_CACHE_VALID_NOTFOUND`          | No        |                              |           | Sets caching time for response code 404                                                                                                                                                                                                                                                                                                                                                                                                               |
-| `PROXY_CACHE_VALID_FORBIDDEN`         | No        |                              |           | Sets caching time for response code 403                                                                                                                                                                                                                                                                                                                                                                                                               |
-| `PROVIDE_INDEX_PAGE`                  | No        | `true`, `false`              | `false`   | Flag which returns the index page if there is one when requesting a directory. Cannot be enabled with `ALLOW_DIRECTORY_LIST`.                                                                                                                                                                                                                                                                                                                         |
-| `JS_TRUSTED_CERT_PATH`                | No        |                              |           | Enables the `js_fetch_trusted_certificate` directive when retrieving AWS credentials and sets the path (on the container) to the specified path                                                                                                                                                                                                                                                                                                       |
-| `HEADER_PREFIXES_TO_STRIP`            | No        |                              |           | A list of HTTP header prefixes that exclude headers client responses. List should be specified in lower-case and a semicolon (;) should be used to as a deliminator between values. For example: `x-goog-;x-something-`                                                                                                                                                                                                                               |
-| `CORS_ENABLED`                        | No        | `true`, `false`              | `false`   | Flag that enables CORS headers on GET requests and enables pre-flight OPTIONS requests. If enabled, this will add CORS headers for "fully open" cross domain requests by default, meaning all domains are allowed, similar to the settings show in [this example](https://enable-cors.org/server_nginx.html). CORS settings can be fine-tuned by overwriting the [`cors.conf.template`](/common/etc/nginx/templates/gateway/cors.conf.template) file. |
-| `CORS_ALLOWED_ORIGIN`                 | No        |                              |           | value to set to be returned from the CORS `Access-Control-Allow-Origin` header. This value is only used if CORS is enabled. (default: \*)                                                                                                                                                                                                                                                                                                             |
+- [**Optional:** Download NGINX Plus license files](https://www.nginx.com/free-trial-request/), and copy them to [`./common/etc/ssl/`](../common/etc/ssl/)
 
+  ```
+  nginx-repo.crt
+  nginx-repo.key
+  ```
+  > Note: This step is only required when running `nginx-lambda-gateway` using NGINX Plus.
+
+- Configure environment variables in [`settings.env`](../settings.env)
+
+  | Name                       | Required? | Allowed Values  | Default                              | Description                                   |
+  |----------------------------|-----------|-----------------|--------------------------------------|-----------------------------------------------|
+  | `LAMBDA_REGION`            | Yes       |                 | `${AWS_REGION}`                      | Lambda region whose servers you want to send the requests |
+  | `LAMBDA_SERVER_PROTO`      | Yes       | `http`, `https` | `https`                              | Protocol to connect to Lambda server          |
+  | `LAMBDA_SERVER`            | Yes       |                 | `lambda.${AWS_REGION}.amazonaws.com` | Lambda host to connect to                     |
+  | `LAMBDA_SERVER_PORT`       | Yes       |                 | `443`                                | SSL/TLS port to connect to                    |
+  | `AWS_ACCESS_KEY_ID`        | No        |                 | `${AWS_ACCESS_KEY_ID}`               | AWS access key associated with an IAM account |
+  | `AWS_SECRET_ACCESS_KEY`    | No        |                 | `${AWS_SECRET_ACCESS_KEY}`           | AWS secret key associated with the access key |
+  | `AWS_SESSION_TOKEN`        | No        |                 | `${AWS_SESSION_TOKEN}`               | AWS session token value that is required if you are using temporary security credentials |
+  | `DEBUG`                    | No        | `true`, `false` | `false`                              | Flag enabling AWS signatures debug output     |
+  | `HEADER_PREFIXES_TO_STRIP` | No        | `true`, `false` | `false`                              | A list of HTTP header prefixes that exclude headers client responses. List should be specified in lower-case and a semicolon (;) should be used to as a deliminator between values. For example: `x-amz-;x-something-` |
+
+  > Note: 
+  > - Define the following environment variables in your machine when using the above default values.
+  >   e.g.: `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` in `~/.bash_profile`.
+  > - `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` are only used to configure the gateway when running as a Container or as a Systemd service.
+ 
+- **Optional:** Edit nginx configuration
+
+  Skip this step when using 80 port and one AWS region for multiple AWS Lambda Function ARNs. Otherwise, configure the [`/etc/nginx/conf.d/nginx_lambda_gateway.conf`](../common/etc/nginx/conf.d/nginx_lambda_gateway.conf):
+
+  ```nginx
+  map $request_uri $lambda_host {
+    # Use default host ($lambdaFunctionARNHost) when using one region for
+    # multiple Lambda Function ARNs per NGINX Lambda Gateway.
+    default $lambdaFunctionARNHost;
+
+    # Add default host per endpoint when using multiple regions for
+    # multiple Lambda Function ARNs per NGINX Lambda Gateway.
+    # '/2015-03-31/functions/foo/invocations' $lambdaFunctionARNHost;
+
+    # Add the following host with ediging {url_id} and {aws-region} per endpoint
+    # when using AWS Lambda Function URL
+    # '/bar' {url-id}.lambda-url.{aws-region}.on.aws;
+  }
+
+  map $request_uri $lambda_url {
+    # Use default Lambda server URL when using AWS Lambda Function ARN.
+    default  $lambdaProto://$lambda_host:$lambdaPort;
+
+    # Add Lambda server URL per endpoint when using AWS Lambda Function URL.
+    # '/bar' $lambdaProto://$lambda_host/;
+  }
+
+  server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Use this config when using a proxy to all AWS Lambda Function ARNs.
+    location / {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Add this config per endpoint when using a proxy to a Lambda Function ARN.
+    # - arn:aws:lambda:{aws-region}:{account-id}:function:foo
+    # location /2015-03-31/functions/foo/invocations {
+    #     auth_request /aws/credentials/retrieval;
+    #     js_content lambdagateway.redirectToLambdaFunctionARN;
+    # }
+
+    # Add this config per endpoint when using a proxy to a Lambda Function URL.
+    # - https://{url-id}.lambda-url.{aws-region}.on.aws/
+    # location /bar {
+    #     auth_request /aws/credentials/retrieval;
+    #     js_content lambdagateway.redirectToLambdaFunctionURL;
+    # }
+
+    # Enable when debugging is needed
+    # error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    # access_log /var/log/nginx/access.log main;
+  }
+  ```
 
-If you are using [AWS instance profile credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html),
-you will need to omit the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` variables from
-the configuration.
+## Quick Starter: Running in Your Laptop
+- [Install and run Docker](https://docs.docker.com/engine/install/)
+- Start a NGINX Lambda Gateway container
+  ```bash
+  make start
+  ```
 
-When running with Docker, the above environment variables can be set in a file 
-with the `--env-file` flag. When running as a Systemd service, the environment
-variables are specified in the `/etc/nginx/environment` file. An example of
-the format of the file can be found in the [settings.example](/settings.example)
-file.
+- Check if a NGINX Lambda Gateway container is running
+  ```bash
+  make watch
+  ``` 
   
-There are few optional environment variables that can be used.
-
-* `HOSTNAME` - (optional) The value will be used for Role Session Name. The default value is nginx-s3-gateway.
-* `STS_ENDPOINT` - (optional) Overrides the STS endpoint to be used in applicable setups. This is not required when running on EKS. See the EKS portion of the guide below for more details.
-* `AWS_STS_REGIONAL_ENDPOINTS` - (optional) Allows for a regional STS endpoint to be
-  selected. When the regional model is selected then the STS endpoint generated will
-  be coded to the current AWS region. This environment variable will be ignored if
-  `STS_ENDPOINT` is set. Valid options are: `global` (default) or `regional`.
+  ![](./img/make-watch.png)
 
+- Invoke a Lambda Function ARN via NGINX Lambda Gateway
+  
+  ```bash
+  curl --location 'http://localhost/2015-03-31/functions/foo/invocations' \
+       --header 'Content-Type: application/json'                          \
+       --data '{ 
+           "message": "This is a sample message" 
+       }'
+  ```
 
-### Configuring Directory Listing
-
-Listing of S3 directories ([folders](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html)) is supported when the
-`ALLOW_DIRECTORY_LIST` environment variable is set to `1`. Directory listing 
-output can be customized by changing the
-[XSL stylesheet](https://www.w3schools.com/xml/xsl_intro.asp): [`common/etc/nginx/include/listing.xsl`](/common/etc/nginx/include/listing.xsl).
-If you are not using AWS S3 as your backend, you may see some inconsistency in 
-the behavior with how directory listing works with HEAD requests. Additionally,
-due to limitations in proxy response processing, invalid S3 folder requests will 
-result in log messages like:
-```
- libxml2 error: "Extra content at the end of the document"
-```
-
-Another limitation is that when using v2 signatures with HEAD requests, the
-gateway will not return 200 for valid folders.
-
-### Static Site Hosting
+- Stop a NGINX Lambda Gateway container
+  ```bash
+  make down
+  ```
 
-When `PROVIDE_INDEX_PAGE` environment variable is set to 1, the gateway will
-transform `/some/path/` to `/some/path/index.html` when retrieving from S3.  
-Default of "index.html" can be edited in `lambdagateway.js`. 
-It will also redirect `/some/path` to `/some/path/` when S3 returns 404 on 
-`/some/path` if `APPEND_SLASH_FOR_POSSIBLE_DIRECTORY` is set. `path` has to 
-look like a possible directory, it must not start with a `.` and not have an 
-extension.  
+- Clean a NGINX Lambda Gateway container image
+  ```bash
+  make clean
+  ```
 
 ## Running as a Systemd Service
-
-A [install script](/standalone_ubuntu_oss_install.sh) for the gateway shows
-how to install NGINX from a package repository, checkout the gateway source, 
-and configure it using the supplied environment variables.
-
-To run the script copy it to your destination system, load the environment
-variables mentioned in the [configuration section](#configuration) into memory,
-and then execute the script. The script takes one optional parameter that 
-specifies the name of the branch to download files from.
+- TBD
 
 ## Running in Containers
-
-### Running the Public Open Source NGINX Container Image
-
-The latest builds of the gateway (that use open source NGINX) are available on 
-the project's Github [package repository](https://github.com/nginxinc/nginx-s3-gateway/pkgs/container/nginx-s3-gateway%2Fnginx-oss-s3-gateway).
-
-To run with the public open source image, replace the `settings` file specified
-below with a file containing your settings, and run the following command:
-```
-docker run --env-file ./settings --publish 80:80 --name nginx-s3-gateway \
-    ghcr.io/nginxinc/nginx-s3-gateway/nginx-oss-s3-gateway:latest
-```
-
-If you would like to run with the latest njs version, run:
-```
-docker run --env-file ./settings --publish 80:80 --name nginx-s3-gateway \
-    ghcr.io/nginxinc/nginx-s3-gateway/nginx-oss-s3-gateway:latest-njs-oss 
-```
-
-Alternatively, if you would like to pin your version to a specific point in
-time release, find the version with an embedded date and run:
-```
-docker run --env-file ./settings --publish 80:80 --name nginx-s3-gateway \
-    ghcr.io/nginxinc/nginx-s3-gateway/nginx-oss-s3-gateway:latest-njs-oss-20220310
-```
-
-### Building the Public Open Source NGINX Container Image
-
-In order to build the NGINX OSS container image, do a `docker build` as follows
-from the project root directory:
-
-```
-docker build --file Dockerfile.oss --tag nginx-s3-gateway:oss --tag nginx-s3-gateway .
-```
-
-Alternatively, if you would like to use the latest version of
-[njs](https://nginx.org/en/docs/njs/), you can build an image from the latest 
-njs source by building this image after building the parent image above:
-```
-docker build --file Dockerfile.oss --tag nginx-s3-gateway --tag nginx-s3-gateway:latest-njs-oss .
-```
-
-After building, you can run the image by issuing the following command and 
-replacing the path to the `settings` file with a file containing your specific
-environment variables.
-```
-docker run --env-file ./settings --publish 80:80 --name nginx-s3-gateway \
-    nginx-s3-gateway:oss
-```
-
-In the same way, if you want to use NGINX OSS container image as a non-root, unprivileged user,
-you can build it as follows:
-```
-docker build --file Dockerfile.unprivileged --tag nginx-s3-gateway --tag nginx-s3-gateway:unprivileged-oss .
-```
-And run the image binding the container port 8080 to 80 in the host like:
-```
-docker run --env-file ./settings --publish 80:8080 --name nginx-s3-gateway \
-    nginx-s3-gateway:unprivileged-oss
-```
-
-It is worth noting that due to the way the startup scripts work, even the unprivileged container will not work with a read-only root filesystem or a specific uid/gid set other then the default of  `101`.
-
-### Building the NGINX Plus Container Image
-
-In order to build the NGINX Plus container image, copy your NGINX Plus 
-repository keys (`nginx-repo.crt` and `nginx-repo.key`) into the 
-`plus/etc/ssl/nginx` directory before building.
-
-If you are using a version of Docker that supports Buildkit, then you can
-build the image as follows in order to prevent your private keys from
-being stored in the container image.
-
-To build, run the following from the project root directory:
-
-```
-DOCKER_BUILDKIT=1 docker build \
-    --file Dockerfile.buildkit.plus \
-    --tag nginx-plus-s3-gateway --tag nginx-plus-s3-gateway:plus \
-    --secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt \
-    --secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key \
-    --squash .
-```
-
-Otherwise, if you don't have Buildkit available, then build as follows. If you
-want to remove the private keys from the image, then you may need to do a
-post-build squash operation using a utility like
-[docker-squash](https://pypi.org/project/docker-squash/).
-
-```
-docker build --file Dockerfile.plus --tag nginx-plus-s3-gateway --tag nginx-plus-s3-gateway:plus .
-``` 
-
-Alternatively, if you would like to use the latest version of
-[njs](https://nginx.org/en/docs/njs/) with NGINX Plus, you can build an image
-from the latest njs source by building this image after building the parent 
-image above:
-```
-docker build --file Dockerfile.plus --tag nginx-plus-s3-gateway --tag nginx-plus-s3-gateway:latest-njs-plus .
-```
-
-After building, you can run the image by issuing the following command and
-replacing the path to the `settings` file with a file containing your specific
-environment variables.
-```
-docker run --env-file ./settings --publish 80:80 --name nginx-plus-s3-gateway \
-    nginx-plus-s3-gateway:plus
-```
+- TBD
 
 ## Running Using AWS Instance Profile Credentials
-
-[AWS instance profiles](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#ec2-instance-profile)
-allow you to assign a role to a compute so that other AWS services can trust
-the instance without having to store authentication keys in the compute 
-instance. This is useful for the gateway because it allows us to run the
-gateway without storing an unchanging `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and 
-`AWS_SESSION_TOKEN` in a file on disk or in an easily read environment variable.
-
-Instance profiles work by providing credentials to the instance via the
-[AWS Metadata API](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html).
-When the API is queried, it provides the keys allowed to the instance. Those
-keys regularly expire, so services using them must refresh frequently.
-
-### Running in EC2 with an IAM Policy
-
-Following the [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#permission-to-pass-iam-roles)
-we can create a IAM role and launch an instance associated with it. On that
-instance, if we run the gateway as a Systemd service there are no additional
-steps. We just run the install script without specifying the
-`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables.
-
-However, if we want to run the gateway as a container instance on that 
-EC2 instance, then we will need to run the following command using the AWS
-CLI tool to allow the metadata endpoint to be accessed from within a container.
-
-```
-aws ec2 modify-instance-metadata-options --instance-id <instance id> \
-    --http-put-response-hop-limit 3 --http-endpoint enabled
-```
-
-After that has been run we can start the container normally and omit the
-`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables.
-
-### Running in ECS with an IAM Policy
-
-The commands below all reference the [`deployments/ecs/cloudformation/s3gateway.cf`](/deployments/ecs/cloudformation/s3gateway.yaml) file. This file will need to be
-modified.
-
-- Update the following 4 parameters in the `Parameters` section of the CloudFormation file for your specific AWS account:
-  - `NewBucketName` - any S3 bucket name. Remember that S3 bucket names must be globally unique
-  - `VpcId` - Any VPC ID on your AWS account
-  - `Subnet1` - Any subnet ID that's in the VPC used above
-  - `Subnet2` - Any subnet ID that's in the VPC used above
-- Run the following command to deploy the stack (this assumes you have the AWS CLI & credentials setup correctly on your host machine and you are running in the project root directory):
-
-  ```sh
-  aws cloudformation create-stack \
-    --stack-name nginx-s3-gateway \
-    --capabilities CAPABILITY_NAMED_IAM \
-    --template-body file://deployments/ecs/cloudformation/s3gateway.yaml
-  ```
-
-- Wait for the CloudFormation Stack deployment to complete
-  (can take about 3-5 minutes)
-  - You can query the stack status with this command:
-    ```sh
-    aws cloudformation describe-stacks \
-      --stack-name nginx-s3-gateway \
-      --query "Stacks[0].StackStatus"
-    ```
-- Wait until the query above shows `"CREATE_COMPLETE"`
-- Run the following command to get the URL used to access the service:
-  ```sh
-  aws cloudformation describe-stacks \
-    --stack-name nginx-s3-gateway \
-    --query "Stacks[0].Outputs[0].OutputValue"
-  ```
-  - Upload a file to the bucket first to prevent getting a `404` when visiting 
-    the URL in your browser
-  ```sh
-  # i.e.
-  aws s3 cp README.md s3://<bucket_name>
-  ```
-- View the container logs in CloudWatch from the AWS web console
-- Run the following command to delete the stack and all resources:
-  ```sh
-  aws cloudformation delete-stack \
-    --stack-name nginx-s3-gateway
-  ```
-
-## Running on EKS with IAM roles for service accounts
-
-If you are planning to use the container image on an EKS cluster, you can use a [service account]((https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)) which can assume a role using [AWS Security Token Service](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html).
-
-- Create a new [AWS IAM OIDC Provider](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html). If you are using AWS EKS Cluster, then the IAM OIDC Provider should already be created as the part of cluster creation. So validate it before you create the new IAM OIDC Provider.
-- Configuring a [Kubernetes service account to assume an IAM role](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html)
-- [Annotate the Service Account](https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html) using IAM Role create in the above step.
-- [Configure your pods, Deployments, etc to use the Service Account](https://docs.aws.amazon.com/eks/latest/userguide/pod-configuration.html)
-- As soon as the pods/deployments are updated, you will see the couple of Env Variables listed below in the pods.
-  - `AWS_ROLE_ARN` - Contains IAM Role ARN
-  - `AWS_WEB_IDENTITY_TOKEN_FILE`  - Contains the token which will be used to create temporary credentials using AWS Security Token Service.
-- You must also set the `AWS_REGION` and `JS_TRUSTED_CERT_PATH` environment variables as shown below in addition to the normal environment variables listed in the Configuration section.
-
-The following is a minimal set of resources to deploy:
-```yaml
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: nginx-s3-gateway
-  annotations:
-    eks.amazonaws.com/role-arn: "<role-arn>"
-    # See https://docs.aws.amazon.com/eks/latest/userguide/configure-sts-endpoint.html
-    eks.amazonaws.com/sts-regional-endpoints: "true"
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: nginx-s3-gateway
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      app: nginx-s3-gateway
-  template:
-    metadata:
-      labels:
-        app: nginx-s3-gateway
-    spec:
-      serviceAccountName: nginx-s3-gateway
-      containers:
-        - name: nginx-s3-gateway
-          image: "ghcr.io/nginxinc/nginx-s3-gateway/nginx-oss-s3-gateway:latest-20220916"
-          imagePullPolicy: IfNotPresent
-          env:
-            - name: S3_BUCKET_NAME
-              value: "<bucket>"
-            - name: S3_SERVER
-              value: "s3.<aws region>.amazonaws.com"
-            - name: S3_SERVER_PROTO
-              value: "https"
-            - name: S3_SERVER_PORT
-              value: "443"
-            - name: S3_STYLE
-              value: "virtual"
-            - name: S3_REGION
-              value: "<aws region>"
-            - name: AWS_REGION
-              value: "<aws region>"
-            - name: AWS_SIGS_VERSION
-              value: "4"
-            - name: ALLOW_DIRECTORY_LIST
-              value: "false"
-            - name: PROVIDE_INDEX_PAGE
-              value: "false"
-            - name: JS_TRUSTED_CERT_PATH
-              value: "/etc/ssl/certs/Amazon_Root_CA_1.pem"
-
-          ports:
-            - name: http
-              containerPort: 80
-              protocol: TCP
-          livenessProbe:
-            httpGet:
-              path: /health
-              port: http
-          readinessProbe:
-            httpGet:
-              path: /health
-              port: http
-```
+- TBD
 
 ## Troubleshooting
-
-### Disable default `404` error message
-The default behavior of the container is to return a `404` error message for any non-`200` response code. This is implemented as a security feature to sanitize any error response from the S3 bucket being proxied. For container debugging purposes, this sanitization can be turned off by commenting out the following lines within [`default.conf.template`](https://github.com/nginxinc/nginx-s3-gateway/blob/master/common/etc/nginx/templates/default.conf.template). 
-```bash
-proxy_intercept_errors on;
-error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 =404 @error404;
-```
-
-### Error `403 Access Denied` for AWS Accounts with MFA Enabled
-The REST authentication method used in this container does not work with AWS IAM roles that have MFA enabled for authentication. Please use AWS IAM role credentials that do not have MFA enabled. 
\ No newline at end of file
+- TBD
diff --git a/docs/img/lambda-func-creation.png b/docs/img/lambda-func-creation.png
new file mode 100644
index 0000000..5d9045a
Binary files /dev/null and b/docs/img/lambda-func-creation.png differ
diff --git a/docs/img/lambda-func-deployment.png b/docs/img/lambda-func-deployment.png
new file mode 100644
index 0000000..26e9b06
Binary files /dev/null and b/docs/img/lambda-func-deployment.png differ
diff --git a/docs/img/lambda_emulator.png b/docs/img/lambda_emulator.png
new file mode 100644
index 0000000..1bbab84
Binary files /dev/null and b/docs/img/lambda_emulator.png differ
diff --git a/docs/img/make-watch.png b/docs/img/make-watch.png
new file mode 100644
index 0000000..7fbdfff
Binary files /dev/null and b/docs/img/make-watch.png differ
diff --git a/docs/img/nginx-lambda-gateway-aws-signature-integration.png b/docs/img/nginx-lambda-gateway-aws-signature-integration.png
new file mode 100644
index 0000000..1e96cb4
Binary files /dev/null and b/docs/img/nginx-lambda-gateway-aws-signature-integration.png differ
diff --git a/docs/img/nginx-lambda-gateway-intro.png b/docs/img/nginx-lambda-gateway-intro.png
new file mode 100644
index 0000000..4134161
Binary files /dev/null and b/docs/img/nginx-lambda-gateway-intro.png differ
diff --git a/docs/img/nginx-s3-gateway-signature-flow.png b/docs/img/nginx-s3-gateway-signature-flow.png
deleted file mode 100644
index 8cc152d..0000000
Binary files a/docs/img/nginx-s3-gateway-signature-flow.png and /dev/null differ
diff --git a/examples/01-all-lambda-function-arns/README.md b/examples/01-all-lambda-function-arns/README.md
new file mode 100644
index 0000000..39af4e6
--- /dev/null
+++ b/examples/01-all-lambda-function-arns/README.md
@@ -0,0 +1,3 @@
+# Example: Proxy To All Lambda Function ARNs
+
+This is an example of a NGINX proxy to all of the AWS Lambda Function ARNs.
diff --git a/examples/01-all-lambda-function-arns/docker-compose.yml b/examples/01-all-lambda-function-arns/docker-compose.yml
new file mode 100644
index 0000000..6e80d09
--- /dev/null
+++ b/examples/01-all-lambda-function-arns/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '3'
+services:
+  nginx_lambda_gateway_01:
+    hostname: nginx_lambda_gateway_01
+    container_name: nginx_lambda_gateway_01
+    image: nginx_lambda_gateway_01
+    build:
+      context: ../../
+      # Enable this when using NGINX OSS
+      dockerfile: ./docker/Dockerfile.oss
+      
+      # Enable this when using NGINX Plus
+      # dockerfile: ./docker/Dockerfile.plus
+    volumes:
+      - ../../examples/01-all-lambda-function-arns/:/etc/nginx/conf.d/
+      - ../../common/lambda-core:/etc/nginx/serverless
+      - ../../common/awssig/core:/etc/nginx/awssig
+    ports:
+      - "80:80"
+    env_file:
+      - ../../settings.env
diff --git a/examples/01-all-lambda-function-arns/lambda_functions/foo.py b/examples/01-all-lambda-function-arns/lambda_functions/foo.py
new file mode 100644
index 0000000..329ed1e
--- /dev/null
+++ b/examples/01-all-lambda-function-arns/lambda_functions/foo.py
@@ -0,0 +1,12 @@
+import json
+
+def lambda_handler(event, context):
+    """Sample lambda handler for a function of `foo`.
+    """
+    return {
+        'statusCode': 200,
+        'body': {
+            'request': event,
+            'response': 'Hello from NGINX Lambda Gateway - /foo!'
+        }
+    }
diff --git a/examples/01-all-lambda-function-arns/lambda_functions/quota-notification.py b/examples/01-all-lambda-function-arns/lambda_functions/quota-notification.py
new file mode 100644
index 0000000..034c5c5
--- /dev/null
+++ b/examples/01-all-lambda-function-arns/lambda_functions/quota-notification.py
@@ -0,0 +1,47 @@
+import base64
+import boto3
+import json
+import logging
+import os
+
+from botocore.exceptions import ClientError
+
+def lambda_handler(event, context):
+    """Sample lambda handler for a function of `nginx-noti` for nginx to send a
+       message to Amazon Simple Notification Service(SNS).
+    """
+    logger = logging.getLogger(__name__)
+    logger.setLevel(logging.INFO)
+    logger.info("request: " + json.dumps(event))
+
+    #topic_arn = os.environ.get('TOPIC_ARN')
+    topic_arn = "arn:aws:sns:{region}:{accont-id}:nginx-noti"
+    sns_client = boto3.client("sns")
+
+    # Generate a message from the event
+    message = json.dumps(event)
+    if 'body' in event:
+        code = event['body']
+        code_bytes = code.encode('ascii')
+        decoded = base64.b64decode(code_bytes)
+        message = decoded.decode('UTF-8')
+
+    try:
+        sent_message = sns_client.publish(
+            TargetArn=topic_arn,
+            Message=message
+        )
+
+        if sent_message is not None:
+            logger.info(f"Success - Message ID: {sent_message['MessageId']}")
+        return {
+            "statusCode": 200,
+            "body": {
+                'request': json.loads(message),
+                "response": "sent a message to AWS SNS"
+            }
+        }
+
+    except ClientError as e:
+        logger.error(e)
+        return None
diff --git a/examples/01-all-lambda-function-arns/nginx_lambda_gateway.conf b/examples/01-all-lambda-function-arns/nginx_lambda_gateway.conf
new file mode 100644
index 0000000..c975307
--- /dev/null
+++ b/examples/01-all-lambda-function-arns/nginx_lambda_gateway.conf
@@ -0,0 +1,30 @@
+include "serverless/lambda_ngx_http.conf";
+
+# Add the endpoint & host of Lambda server when using AWS Lambda Function URL.
+# Add the endpoint, and assign the value of $lambdaFunctionARNHost when using
+# AWS Lambda Function ARN.
+map $request_uri $lambda_host {
+    # Default host name is used for AWS Lambda Function ARN
+    default $lambdaFunctionARNHost;
+}
+
+# Add the endpoint when using AWS Lambda Function URL. The default value is for
+# the URL of AWS Lambda Function ARN.
+map $request_uri $lambda_url {
+    default $lambdaProto://$lambda_host:$lambdaPort;
+}
+
+server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Example of a proxy to all of the AWS Lambda Function ARNs.
+    location / {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Enable when debugging is needed
+    error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    access_log /var/log/nginx/access.log main;
+}
diff --git a/examples/02-one-lambda-function-arn/README.md b/examples/02-one-lambda-function-arn/README.md
new file mode 100644
index 0000000..8e8d257
--- /dev/null
+++ b/examples/02-one-lambda-function-arn/README.md
@@ -0,0 +1,3 @@
+# Example: Proxy To One Lambda Function ARN
+
+This is an example of a NGINX proxy to one the AWS Lambda Function ARN.
diff --git a/examples/02-one-lambda-function-arn/docker-compose.yml b/examples/02-one-lambda-function-arn/docker-compose.yml
new file mode 100644
index 0000000..45dbf17
--- /dev/null
+++ b/examples/02-one-lambda-function-arn/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '3'
+services:
+  nginx_lambda_gateway_02:
+    hostname: nginx_lambda_gateway_02
+    container_name: nginx_lambda_gateway_02
+    image: nginx_lambda_gateway_02
+    build:
+      context: ../../
+      # Enable this when using NGINX OSS
+      dockerfile: ./docker/Dockerfile.oss
+      
+      # Enable this when using NGINX Plus
+      # dockerfile: ./docker/Dockerfile.plus
+    volumes:
+      - ../../examples/02-one-lambda-function-arn/:/etc/nginx/conf.d/
+      - ../../common/lambda-core:/etc/nginx/serverless
+      - ../../common/awssig/core:/etc/nginx/awssig
+    ports:
+      - "80:80"
+    env_file:
+      - ../../settings.env
diff --git a/examples/02-one-lambda-function-arn/lambda_functions/foo.py b/examples/02-one-lambda-function-arn/lambda_functions/foo.py
new file mode 100644
index 0000000..75e9de5
--- /dev/null
+++ b/examples/02-one-lambda-function-arn/lambda_functions/foo.py
@@ -0,0 +1,11 @@
+import json
+
+def lambda_handler(event, context):
+    # TODO implement
+    return {
+        'statusCode': 200,
+        'body': {
+            'request': event,
+            'response': 'Hello from NGINX Lambda Gateway - /foo!'
+        }
+    }
diff --git a/examples/02-one-lambda-function-arn/lambda_functions/quota-notification.py b/examples/02-one-lambda-function-arn/lambda_functions/quota-notification.py
new file mode 100644
index 0000000..034c5c5
--- /dev/null
+++ b/examples/02-one-lambda-function-arn/lambda_functions/quota-notification.py
@@ -0,0 +1,47 @@
+import base64
+import boto3
+import json
+import logging
+import os
+
+from botocore.exceptions import ClientError
+
+def lambda_handler(event, context):
+    """Sample lambda handler for a function of `nginx-noti` for nginx to send a
+       message to Amazon Simple Notification Service(SNS).
+    """
+    logger = logging.getLogger(__name__)
+    logger.setLevel(logging.INFO)
+    logger.info("request: " + json.dumps(event))
+
+    #topic_arn = os.environ.get('TOPIC_ARN')
+    topic_arn = "arn:aws:sns:{region}:{accont-id}:nginx-noti"
+    sns_client = boto3.client("sns")
+
+    # Generate a message from the event
+    message = json.dumps(event)
+    if 'body' in event:
+        code = event['body']
+        code_bytes = code.encode('ascii')
+        decoded = base64.b64decode(code_bytes)
+        message = decoded.decode('UTF-8')
+
+    try:
+        sent_message = sns_client.publish(
+            TargetArn=topic_arn,
+            Message=message
+        )
+
+        if sent_message is not None:
+            logger.info(f"Success - Message ID: {sent_message['MessageId']}")
+        return {
+            "statusCode": 200,
+            "body": {
+                'request': json.loads(message),
+                "response": "sent a message to AWS SNS"
+            }
+        }
+
+    except ClientError as e:
+        logger.error(e)
+        return None
diff --git a/examples/02-one-lambda-function-arn/nginx_lambda_gateway.conf b/examples/02-one-lambda-function-arn/nginx_lambda_gateway.conf
new file mode 100644
index 0000000..e876674
--- /dev/null
+++ b/examples/02-one-lambda-function-arn/nginx_lambda_gateway.conf
@@ -0,0 +1,42 @@
+include "serverless/lambda_ngx_http.conf";
+
+# Add the endpoint & host of Lambda server when using AWS Lambda Function URL.
+# Add the endpoint, and assign the value of $lambdaFunctionARNHost when using
+# AWS Lambda Function ARN.
+map $request_uri $lambda_host {
+    # Use default host name when using one region for Lambda Function ARNs.
+    default $lambdaFunctionARNHost;
+
+    # Define each host name when using multiple regions for Lambda Function ARN.
+    '/2015-03-31/functions/foo/invocations'                $lambdaFunctionARNHost;
+    '/2015-03-31/functions/quota-notification/invocations' $lambdaFunctionARNHost;
+}
+
+# Add the endpoint when using AWS Lambda Function URL. The default value is for
+# the URL of AWS Lambda Function ARN.
+map $request_uri $lambda_url {
+    default $lambdaProto://$lambda_host:$lambdaPort;
+}
+
+server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Example 1 of a proxy to one AWS Lambda Function ARN.
+    # - arn:aws:lambda:{region}:{account-id}:function:foo
+    location /2015-03-31/functions/foo/invocations {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Example 2 of a proxy to one AWS Lambda Function ARN.
+    # - arn:aws:lambda:{region}:{account-id}:function:quota-notification
+    location /2015-03-31/functions/quota-notification/invocations {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Enable when debugging is needed
+    error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    access_log /var/log/nginx/access.log main;
+}
diff --git a/examples/03-one-lambda-function-url/README.md b/examples/03-one-lambda-function-url/README.md
new file mode 100644
index 0000000..04bddc1
--- /dev/null
+++ b/examples/03-one-lambda-function-url/README.md
@@ -0,0 +1,4 @@
+# Example: Proxy To One Lambda Function URL
+
+This is an example of a NGINX proxy to one the AWS Lambda Function URL.
+
diff --git a/examples/03-one-lambda-function-url/docker-compose.yml b/examples/03-one-lambda-function-url/docker-compose.yml
new file mode 100644
index 0000000..fcde61e
--- /dev/null
+++ b/examples/03-one-lambda-function-url/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '3'
+services:
+  nginx_lambda_gateway_03:
+    hostname: nginx_lambda_gateway_03
+    container_name: nginx_lambda_gateway_03
+    image: nginx_lambda_gateway_03
+    build:
+      context: ../../
+      # Enable this when using NGINX OSS
+      dockerfile: ./docker/Dockerfile.oss
+      
+      # Enable this when using NGINX Plus
+      # dockerfile: ./docker/Dockerfile.plus
+    volumes:
+      - ../../examples/03-one-lambda-function-url/:/etc/nginx/conf.d/
+      - ../../common/lambda-core:/etc/nginx/serverless
+      - ../../common/awssig/core:/etc/nginx/awssig
+    ports:
+      - "80:80"
+    env_file:
+      - ../../settings.env
diff --git a/examples/03-one-lambda-function-url/lambda_functions/bar.py b/examples/03-one-lambda-function-url/lambda_functions/bar.py
new file mode 100644
index 0000000..b8285da
--- /dev/null
+++ b/examples/03-one-lambda-function-url/lambda_functions/bar.py
@@ -0,0 +1,8 @@
+import json
+
+def lambda_handler(event, context):
+    # TODO implement
+    return {
+        'statusCode': 200,
+        'body': json.dumps('Hello from NGINX Lambda Gateway - /bar!')
+    }
diff --git a/examples/03-one-lambda-function-url/lambda_functions/quota-notification.py b/examples/03-one-lambda-function-url/lambda_functions/quota-notification.py
new file mode 100644
index 0000000..034c5c5
--- /dev/null
+++ b/examples/03-one-lambda-function-url/lambda_functions/quota-notification.py
@@ -0,0 +1,47 @@
+import base64
+import boto3
+import json
+import logging
+import os
+
+from botocore.exceptions import ClientError
+
+def lambda_handler(event, context):
+    """Sample lambda handler for a function of `nginx-noti` for nginx to send a
+       message to Amazon Simple Notification Service(SNS).
+    """
+    logger = logging.getLogger(__name__)
+    logger.setLevel(logging.INFO)
+    logger.info("request: " + json.dumps(event))
+
+    #topic_arn = os.environ.get('TOPIC_ARN')
+    topic_arn = "arn:aws:sns:{region}:{accont-id}:nginx-noti"
+    sns_client = boto3.client("sns")
+
+    # Generate a message from the event
+    message = json.dumps(event)
+    if 'body' in event:
+        code = event['body']
+        code_bytes = code.encode('ascii')
+        decoded = base64.b64decode(code_bytes)
+        message = decoded.decode('UTF-8')
+
+    try:
+        sent_message = sns_client.publish(
+            TargetArn=topic_arn,
+            Message=message
+        )
+
+        if sent_message is not None:
+            logger.info(f"Success - Message ID: {sent_message['MessageId']}")
+        return {
+            "statusCode": 200,
+            "body": {
+                'request': json.loads(message),
+                "response": "sent a message to AWS SNS"
+            }
+        }
+
+    except ClientError as e:
+        logger.error(e)
+        return None
diff --git a/examples/03-one-lambda-function-url/nginx_lambda_gateway.conf b/examples/03-one-lambda-function-url/nginx_lambda_gateway.conf
new file mode 100644
index 0000000..94d72cb
--- /dev/null
+++ b/examples/03-one-lambda-function-url/nginx_lambda_gateway.conf
@@ -0,0 +1,44 @@
+include "serverless/lambda_ngx_http.conf";
+
+# Add the endpoint & host of Lambda server when using AWS Lambda Function URL.
+# Add the endpoint, and assign the value of $lambdaFunctionARNHost when using
+# AWS Lambda Function ARN.
+map $request_uri $lambda_host {
+    # Use default host name when using one region for Lambda Function ARNs.
+    default $lambdaFunctionARNHost;
+
+    # Define each host per an API endpoint when using AWS Lambda Function URL
+    '/bar'                it6io4wr54p5ngkzygs4okvdmq0keqhf.lambda-url.us-east-2.on.aws;
+    '/quota-notification' uihoyehudzqnxd44iuyl3jrnxa0gczce.lambda-url.us-east-2.on.aws;
+}
+
+# Add the endpoint when using AWS Lambda Function URL. The default value is for
+# the URL of AWS Lambda Function ARN.
+map $request_uri $lambda_url {
+    default $lambdaProto://$lambda_host:$lambdaPort;
+    '/bar'                 $lambdaProto://$lambda_host/;
+    '/quota-notification'  $lambdaProto://$lambda_host/;
+}
+
+server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Example 1 of a proxy to one AWS Lambda Function URL.
+    # - https://it6io4wr54p5ngkzygs4okvdmq0keqhf.lambda-url.us-east-2.on.aws/
+    location /bar {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionURL;
+    }
+
+    # Example 2 of a proxy to one AWS Lambda Function URL.
+    # - https://uihoyehudzqnxd44iuyl3jrnxa0gczce.lambda-url.us-east-2.on.aws/
+    location /quota-notification {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionURL;
+    }
+
+    # Enable when debugging is needed
+    error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    access_log /var/log/nginx/access.log main;
+}
diff --git a/examples/04-lambda-function-arn-url/README.md b/examples/04-lambda-function-arn-url/README.md
new file mode 100644
index 0000000..43cad33
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/README.md
@@ -0,0 +1,3 @@
+# Example: Proxy To The Lambda Function ARN and URL
+
+This shows the combined example of NGINX proxies to the AWS Lambda Function ARN and URL.
diff --git a/examples/04-lambda-function-arn-url/docker-compose.yml b/examples/04-lambda-function-arn-url/docker-compose.yml
new file mode 100644
index 0000000..6ea41ce
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/docker-compose.yml
@@ -0,0 +1,21 @@
+version: '3'
+services:
+  nginx_lambda_gateway_04:
+    hostname: nginx_lambda_gateway_04
+    container_name: nginx_lambda_gateway_04
+    image: nginx_lambda_gateway_04
+    build:
+      context: ../../
+      # Enable this when using NGINX OSS
+      dockerfile: ./docker/Dockerfile.oss
+      
+      # Enable this when using NGINX Plus
+      # dockerfile: ./docker/Dockerfile.plus
+    volumes:
+      - ../../examples/04-lambda-function-arn-url/:/etc/nginx/conf.d/
+      - ../../common/lambda-core:/etc/nginx/serverless
+      - ../../common/awssig/core:/etc/nginx/awssig
+    ports:
+      - "80:80"
+    env_file:
+      - ../../settings.env
diff --git a/examples/04-lambda-function-arn-url/lambda_functions/bar.py b/examples/04-lambda-function-arn-url/lambda_functions/bar.py
new file mode 100644
index 0000000..b8285da
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/lambda_functions/bar.py
@@ -0,0 +1,8 @@
+import json
+
+def lambda_handler(event, context):
+    # TODO implement
+    return {
+        'statusCode': 200,
+        'body': json.dumps('Hello from NGINX Lambda Gateway - /bar!')
+    }
diff --git a/examples/04-lambda-function-arn-url/lambda_functions/foo.py b/examples/04-lambda-function-arn-url/lambda_functions/foo.py
new file mode 100644
index 0000000..75e9de5
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/lambda_functions/foo.py
@@ -0,0 +1,11 @@
+import json
+
+def lambda_handler(event, context):
+    # TODO implement
+    return {
+        'statusCode': 200,
+        'body': {
+            'request': event,
+            'response': 'Hello from NGINX Lambda Gateway - /foo!'
+        }
+    }
diff --git a/examples/04-lambda-function-arn-url/lambda_functions/quota-notification.py b/examples/04-lambda-function-arn-url/lambda_functions/quota-notification.py
new file mode 100644
index 0000000..034c5c5
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/lambda_functions/quota-notification.py
@@ -0,0 +1,47 @@
+import base64
+import boto3
+import json
+import logging
+import os
+
+from botocore.exceptions import ClientError
+
+def lambda_handler(event, context):
+    """Sample lambda handler for a function of `nginx-noti` for nginx to send a
+       message to Amazon Simple Notification Service(SNS).
+    """
+    logger = logging.getLogger(__name__)
+    logger.setLevel(logging.INFO)
+    logger.info("request: " + json.dumps(event))
+
+    #topic_arn = os.environ.get('TOPIC_ARN')
+    topic_arn = "arn:aws:sns:{region}:{accont-id}:nginx-noti"
+    sns_client = boto3.client("sns")
+
+    # Generate a message from the event
+    message = json.dumps(event)
+    if 'body' in event:
+        code = event['body']
+        code_bytes = code.encode('ascii')
+        decoded = base64.b64decode(code_bytes)
+        message = decoded.decode('UTF-8')
+
+    try:
+        sent_message = sns_client.publish(
+            TargetArn=topic_arn,
+            Message=message
+        )
+
+        if sent_message is not None:
+            logger.info(f"Success - Message ID: {sent_message['MessageId']}")
+        return {
+            "statusCode": 200,
+            "body": {
+                'request': json.loads(message),
+                "response": "sent a message to AWS SNS"
+            }
+        }
+
+    except ClientError as e:
+        logger.error(e)
+        return None
diff --git a/examples/04-lambda-function-arn-url/nginx_lambda_gateway.conf b/examples/04-lambda-function-arn-url/nginx_lambda_gateway.conf
new file mode 100644
index 0000000..bdab186
--- /dev/null
+++ b/examples/04-lambda-function-arn-url/nginx_lambda_gateway.conf
@@ -0,0 +1,68 @@
+include "serverless/lambda_ngx_http.conf";
+
+# Add the endpoint & host of Lambda server when using AWS Lambda Function URL.
+# Add the endpoint, and assign the value of $lambdaFunctionARNHost when using
+# AWS Lambda Function ARN.
+map $request_uri $lambda_host {
+    # Use default host name when using one region for Lambda Function ARNs.
+    default $lambdaFunctionARNHost;
+
+    # Define each host name when using multiple regions for Lambda Function ARN.
+    '/2015-03-31/functions/foo/invocations'                $lambdaFunctionARNHost;
+    '/2015-03-31/functions/quota-notification/invocations' $lambdaFunctionARNHost;
+
+    # Define each host per an API endpoint when using AWS Lambda Function URL
+    '/bar'                it6io4wr54p5ngkzygs4okvdmq0keqhf.lambda-url.us-east-2.on.aws;
+    '/quota-notification' uihoyehudzqnxd44iuyl3jrnxa0gczce.lambda-url.us-east-2.on.aws; 
+}
+
+# Add the endpoint when using AWS Lambda Function URL. The default value is for
+# the URL of AWS Lambda Function ARN.
+map $request_uri $lambda_url {
+    default $lambdaProto://$lambda_host:$lambdaPort;
+    '/bar'                 $lambdaProto://$lambda_host/;
+    '/quota-notification'  $lambdaProto://$lambda_host/;
+}
+
+server {
+    include "serverless/lambda_ngx_apis.conf";
+    listen 80; # Use SSL/TLS in production
+
+    # Example of a proxy to all of the AWS Lambda Function ARNs.
+    location / {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Example 1 of a proxy to one AWS Lambda Function ARN.
+    # - arn:aws:lambda:{region}:{account-id}:function:foo
+    location /2015-03-31/functions/foo/invocations {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Example 2 of a proxy to one AWS Lambda Function ARN.
+    # - arn:aws:lambda:{region}:{account-id}:function:quota-notification
+    location /2015-03-31/functions/quota-notification/invocations {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionARN;
+    }
+
+    # Example 3 of a proxy to one AWS Lambda Function URL.
+    # - https://it6io4wr54p5ngkzygs4okvdmq0keqhf.lambda-url.us-east-2.on.aws/
+    location /bar {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionURL;
+    }
+
+    # Example 4 of a proxy to one AWS Lambda Function URL.
+    # - https://uihoyehudzqnxd44iuyl3jrnxa0gczce.lambda-url.us-east-2.on.aws/
+    location /quota-notification {
+        auth_request /aws/credentials/retrieval;
+        js_content lambdagateway.redirectToLambdaFunctionURL;
+    }
+
+    # Enable when debugging is needed
+    error_log  /var/log/nginx/error.log  debug; # Reduce severity level as required
+    access_log /var/log/nginx/access.log main;
+}
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..88ad34a
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,6 @@
+# NGINX Lambda Gateway Examples
+
+- [NGINX Lambda Gateway to all of the AWS Lambda Function ARNs](./01-all-lambda-function-arns/)
+- [NGINX Lambda Gateway to one AWS Lambda Function ARN](./02-one-lambda-function-arn/)
+- [NGINX Lambda Gateway to one AWS Lambda Function URL](./03-one-lambda-function-url/)
+- [NGINX Lambda Gateway to the AWS Lambda Function ARN and URL](./04-lambda-function-arn-url/)
diff --git a/examples/brotli-compression/Dockerfile.oss b/examples/brotli-compression/Dockerfile.oss
deleted file mode 100644
index 4d7ecae..0000000
--- a/examples/brotli-compression/Dockerfile.oss
+++ /dev/null
@@ -1,45 +0,0 @@
-FROM nginxinc/nginx-s3-gateway
-
-ENV BROTLI_VERSION "v1.0.0rc"
-
-# Build Brotli module from source because there is no repository package
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    apt-get update -qq; \
-    apt-get install -y -qq build-essential libpcre3-dev git libbrotli1 libbrotli-dev; \
-    curl -o /tmp/nginx.tar.gz --retry 6 -Ls "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"; \
-    mkdir /tmp/nginx /tmp/brotli; \
-    tar -C /tmp/nginx --strip-components 1 -xzf /tmp/nginx.tar.gz; \
-    curl -o /tmp/brotli.tar.gz --retry 6 -Ls "https://github.com/google/ngx_brotli/archive/${BROTLI_VERSION}.tar.gz"; \
-    tar -C "/tmp/brotli" --strip-components 1 -xzf /tmp/brotli.tar.gz; \
-    cd /tmp/nginx; \
-./configure --add-dynamic-module=/tmp/brotli \
-                --without-http_gzip_module \
-                --prefix=/etc/nginx \
-                --sbin-path=/usr/sbin/nginx \
-                --modules-path=/usr/lib/nginx/modules \
-                --conf-path=/etc/nginx/nginx.conf \
-                --error-log-path=/var/log/nginx/error.log \
-                --http-log-path=/var/log/nginx/access.log \
-                --pid-path=/var/run/nginx.pid \
-                --lock-path=/var/run/nginx.lock \
-                --http-client-body-temp-path=/var/cache/nginx/client_temp \
-                --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
-                --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
-                --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
-                --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
-                --user=nginx --group=nginx --with-compat --with-file-aio \
-                --with-threads \
-                --with-compat \
-                --with-cc-opt="-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-${NGINX_VERSION}/debian/debuild-base/nginx-${NGINX_VERSION}=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC" \
-                --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'; \
-    make -j $(nproc) modules; \
-    cp /tmp/nginx/objs/ngx_http_brotli_filter_module.so /usr/lib/nginx/modules; \
-    cp /tmp/nginx/objs/ngx_http_brotli_static_module.so /usr/lib/nginx/modules; \
-    apt-get purge -y --auto-remove build-essential libpcre3-dev git libbrotli-dev; \
-    rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*
-
-# Update configuration to load module
-RUN sed -i '1s#^#load_module modules/ngx_http_brotli_filter_module.so;\n\n#' /etc/nginx/nginx.conf
-
-COPY etc/nginx/conf.d /etc/nginx/conf.d
diff --git a/examples/brotli-compression/Dockerfile.plus b/examples/brotli-compression/Dockerfile.plus
deleted file mode 100644
index c0d4443..0000000
--- a/examples/brotli-compression/Dockerfile.plus
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM nginx-plus-s3-gateway
-
-# Install Brolti from the NGINX Plus repository
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    apt-get -qq update; \
-    apt-get -qq install --no-install-recommends --no-install-suggests -y nginx-plus-module-brotli; \
-    rm -rf /var/lib/apt/lists/*
-
-# Update configuration to load module
-RUN sed -i '1s#^#load_module modules/ngx_http_brotli_filter_module.so;\n\n#' /etc/nginx/nginx.conf
-
-COPY etc/nginx/conf.d /etc/nginx/conf.d
diff --git a/examples/brotli-compression/etc/nginx/conf.d/brotli_compression.conf b/examples/brotli-compression/etc/nginx/conf.d/brotli_compression.conf
deleted file mode 100644
index 0015991..0000000
--- a/examples/brotli-compression/etc/nginx/conf.d/brotli_compression.conf
+++ /dev/null
@@ -1,36 +0,0 @@
-brotli on;
-brotli_comp_level 6;
-brotli_buffers 16 8k;
-brotli_min_length 1024;
-brotli_types
-  application/atom+xml
-  application/geo+json
-  application/javascript
-  application/x-javascript
-  application/json
-  application/ld+json
-  application/manifest+json
-  application/rdf+xml
-  application/rss+xml
-  application/vnd.ms-fontobject
-  application/wasm
-  application/x-web-app-manifest+json
-  application/xhtml+xml
-  application/xml
-  font/eot
-  font/otf
-  font/ttf
-  image/bmp
-  image/svg+xml
-  text/cache-manifest
-  text/calendar
-  text/css
-  text/javascript
-  text/markdown
-  text/plain
-  text/xml
-  text/vcard
-  text/vnd.rim.location.xloc
-  text/vtt
-  text/x-component
-  text/x-cross-domain-policy;
diff --git a/examples/gzip-compression/Dockerfile.oss b/examples/gzip-compression/Dockerfile.oss
deleted file mode 100644
index d609596..0000000
--- a/examples/gzip-compression/Dockerfile.oss
+++ /dev/null
@@ -1,3 +0,0 @@
-FROM nginxinc/nginx-s3-gateway
-
-COPY etc/nginx/conf.d /etc/nginx/conf.d
diff --git a/examples/gzip-compression/Dockerfile.plus b/examples/gzip-compression/Dockerfile.plus
deleted file mode 100644
index 65719a3..0000000
--- a/examples/gzip-compression/Dockerfile.plus
+++ /dev/null
@@ -1,3 +0,0 @@
-FROM nginx-plus-s3-gateway
-
-COPY etc/nginx/conf.d /etc/nginx/conf.d
diff --git a/examples/gzip-compression/etc/nginx/conf.d/gzip_compression.conf b/examples/gzip-compression/etc/nginx/conf.d/gzip_compression.conf
deleted file mode 100644
index ac15c28..0000000
--- a/examples/gzip-compression/etc/nginx/conf.d/gzip_compression.conf
+++ /dev/null
@@ -1,71 +0,0 @@
-# Credit: https://github.com/h5bp/server-configs-nginx/
-
-# ----------------------------------------------------------------------
-# | Compression                                                        |
-# ----------------------------------------------------------------------
-
-# https://nginx.org/en/docs/http/ngx_http_gzip_module.html
-
-# Enable gzip compression.
-# Default: off
-gzip on;
-
-# Compression level (1-9).
-# 5 is a perfect compromise between size and CPU usage, offering about 75%
-# reduction for most ASCII files (almost identical to level 9).
-# Default: 1
-gzip_comp_level 6;
-
-# Don't compress anything that's already small and unlikely to shrink much if at
-# all (the default is 20 bytes, which is bad as that usually leads to larger
-# files after gzipping).
-# Default: 20
-gzip_min_length 256;
-
-# Compress data even for clients that are connecting to us via proxies,
-# identified by the "Via" header (required for CloudFront).
-# Default: off
-gzip_proxied any;
-
-# Tell proxies to cache both the gzipped and regular version of a resource
-# whenever the client's Accept-Encoding capabilities header varies;
-# Avoids the issue where a non-gzip capable client (which is extremely rare
-# today) would display gibberish if their proxy gave them the gzipped version.
-# Default: off
-gzip_vary on;
-
-# Compress all output labeled with one of the following MIME-types.
-# `text/html` is always compressed by gzip module.
-# Default: text/html
-gzip_types
-  application/atom+xml
-  application/geo+json
-  application/javascript
-  application/x-javascript
-  application/json
-  application/ld+json
-  application/manifest+json
-  application/rdf+xml
-  application/rss+xml
-  application/vnd.ms-fontobject
-  application/wasm
-  application/x-web-app-manifest+json
-  application/xhtml+xml
-  application/xml
-  font/eot
-  font/otf
-  font/ttf
-  image/bmp
-  image/svg+xml
-  text/cache-manifest
-  text/calendar
-  text/css
-  text/javascript
-  text/markdown
-  text/plain
-  text/xml
-  text/vcard
-  text/vnd.rim.location.xloc
-  text/vtt
-  text/x-component
-  text/x-cross-domain-policy;
diff --git a/examples/modsecurity/Dockerfile.oss b/examples/modsecurity/Dockerfile.oss
deleted file mode 100644
index 19275dd..0000000
--- a/examples/modsecurity/Dockerfile.oss
+++ /dev/null
@@ -1,55 +0,0 @@
-FROM nginxinc/nginx-s3-gateway
-
-ENV MODSECURITY_VERSION "v1.0.1"
-ENV OWASP_RULESET_VERSION "v3.3.0"
-ENV OWASP_RULESET_CHECKSUM "1f4002b5cf941a9172b6250cea7e3465a85ef6ee"
-
-# Build modsecurity module from source because there is no repository package
-# Download OWASP ruleset
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    apt-get update -qq; \
-    apt-get install -y -qq build-essential libpcre3-dev git libmodsecurity3 libmodsecurity-dev curl libdigest-sha-perl; \
-    curl -o /tmp/nginx.tar.gz --retry 6 -Ls "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"; \
-    mkdir /tmp/nginx /tmp/modsecurity; \
-    tar -C /tmp/nginx --strip-components 1 -xzf /tmp/nginx.tar.gz; \
-    curl -o /tmp/modsecurity.tar.gz --retry 6 -Ls "https://github.com/SpiderLabs/ModSecurity-nginx/archive/${MODSECURITY_VERSION}.tar.gz"; \
-    tar -C "/tmp/modsecurity" --strip-components 1 -xzf /tmp/modsecurity.tar.gz; \
-    cd /tmp/nginx; \
-./configure --add-dynamic-module=/tmp/modsecurity \
-                --without-http_gzip_module \
-                --prefix=/etc/nginx \
-                --sbin-path=/usr/sbin/nginx \
-                --modules-path=/usr/lib/nginx/modules \
-                --conf-path=/etc/nginx/nginx.conf \
-                --error-log-path=/var/log/nginx/error.log \
-                --http-log-path=/var/log/nginx/access.log \
-                --pid-path=/var/run/nginx.pid \
-                --lock-path=/var/run/nginx.lock \
-                --http-client-body-temp-path=/var/cache/nginx/client_temp \
-                --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
-                --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
-                --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
-                --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
-                --user=nginx --group=nginx --with-compat --with-file-aio \
-                --with-threads \
-                --with-compat \
-                --with-cc-opt="-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-${NGINX_VERSION}/debian/debuild-base/nginx-${NGINX_VERSION}=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC" \
-                --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'; \
-    make -j $(nproc) modules; \
-    cp /tmp/nginx/objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules; \
-    curl -o /tmp/coreruleset.tar.gz --retry 6 -Ls "https://github.com/coreruleset/coreruleset/archive/${OWASP_RULESET_VERSION}.tar.gz"; \
-    echo "${OWASP_RULESET_CHECKSUM}  /tmp/coreruleset.tar.gz" | shasum -c; \
-    mkdir -p /usr/local/nginx/conf/owasp-modsecurity-crs; \
-    tar -C /usr/local/nginx/conf/owasp-modsecurity-crs --strip-components 1 -xzf /tmp/coreruleset.tar.gz; \
-    apt-get purge -y --auto-remove build-essential libpcre3-dev git libmodsecurity-dev curl libdigest-sha-perl; \
-    rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*
-
-# Update configuration to load module
-RUN sed -i '1s#^#load_module modules/ngx_http_modsecurity_module.so;\n#' /etc/nginx/nginx.conf
-
-# Update configuration to include modsecurity
-RUN sed -i 's#server {#server \{\n    include /etc/nginx/conf.d/gateway/modsecurity.conf;#' /etc/nginx/templates/default.conf.template
-
-COPY etc/nginx /etc/nginx
-COPY usr/local /usr/local
diff --git a/examples/modsecurity/Dockerfile.plus b/examples/modsecurity/Dockerfile.plus
deleted file mode 100644
index a44428a..0000000
--- a/examples/modsecurity/Dockerfile.plus
+++ /dev/null
@@ -1,25 +0,0 @@
-FROM nginx-plus-s3-gateway
-
-ENV OWASP_RULESET_VERSION "v3.3.0"
-ENV OWASP_RULESET_CHECKSUM "1f4002b5cf941a9172b6250cea7e3465a85ef6ee"
-
-# Install modsecurity from the NGINX Plus repository and download OWASP ruleset
-RUN set -eux \
-    export DEBIAN_FRONTEND=noninteractive; \
-    apt-get -qq update; \
-    apt-get -qq install --no-install-recommends --no-install-suggests -y curl libdigest-sha-perl nginx-plus-module-modsecurity; \
-    curl -o /tmp/coreruleset.tar.gz --retry 6 -Ls "https://github.com/coreruleset/coreruleset/archive/${OWASP_RULESET_VERSION}.tar.gz"; \
-    echo "${OWASP_RULESET_CHECKSUM}  /tmp/coreruleset.tar.gz" | shasum -c; \
-    mkdir -p /usr/local/nginx/conf/owasp-modsecurity-crs; \
-    tar -C /usr/local/nginx/conf/owasp-modsecurity-crs --strip-components 1 -xzf /tmp/coreruleset.tar.gz; \
-    apt-get -qq purge curl libdigest-sha-perl; \
-    rm -rf /var/lib/apt/lists/*
-
-# Update configuration to load module
-RUN sed -i '1s#^#load_module modules/ngx_http_modsecurity_module.so;\n#' /etc/nginx/nginx.conf
-
-# Update configuration to include modsecurity
-RUN sed -i 's#server {#server \{\n    include /etc/nginx/conf.d/gateway/modsecurity.conf;#' /etc/nginx/templates/default.conf.template
-
-COPY etc/nginx /etc/nginx
-COPY usr/local /usr/local
diff --git a/examples/modsecurity/etc/nginx/conf.d/gateway/modsecurity.conf b/examples/modsecurity/etc/nginx/conf.d/gateway/modsecurity.conf
deleted file mode 100644
index aa96520..0000000
--- a/examples/modsecurity/etc/nginx/conf.d/gateway/modsecurity.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-modsecurity on;
-modsecurity_rules_file /etc/nginx/modsec/main.conf;
diff --git a/examples/modsecurity/etc/nginx/modsec/main.conf b/examples/modsecurity/etc/nginx/modsec/main.conf
deleted file mode 100644
index 2c1270b..0000000
--- a/examples/modsecurity/etc/nginx/modsec/main.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-# Include the recommended configuration
-Include modsecurity.conf
-
-# Rules from OWASP ruleset
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/crs-setup.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
-Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
diff --git a/examples/modsecurity/etc/nginx/modsec/modsecurity.conf b/examples/modsecurity/etc/nginx/modsec/modsecurity.conf
deleted file mode 100644
index 7227101..0000000
--- a/examples/modsecurity/etc/nginx/modsec/modsecurity.conf
+++ /dev/null
@@ -1,264 +0,0 @@
-# -- Rule engine initialization ----------------------------------------------
-
-# Enable ModSecurity, attaching it to every transaction. Use detection
-# only to start with, because that minimises the chances of post-installation
-# disruption.
-#
-SecRuleEngine On
-
-
-# -- Request body handling ---------------------------------------------------
-
-# Allow ModSecurity to access request bodies. If you don't, ModSecurity
-# won't be able to see any POST parameters, which opens a large security
-# hole for attackers to exploit.
-#
-SecRequestBodyAccess On
-
-
-# Enable XML request body parser.
-# Initiate XML Processor in case of xml content-type
-#
-SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
-     "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
-
-# Enable JSON request body parser.
-# Initiate JSON Processor in case of JSON content-type; change accordingly
-# if your application does not use 'application/json'
-#
-SecRule REQUEST_HEADERS:Content-Type "application/json" \
-     "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
-
-# Maximum request body size we will accept for buffering. If you support
-# file uploads then the value given on the first line has to be as large
-# as the largest file you are willing to accept. The second value refers
-# to the size of data, with files excluded. You want to keep that value as
-# low as practical.
-#
-SecRequestBodyLimit 13107200
-SecRequestBodyNoFilesLimit 131072
-
-# What do do if the request body size is above our configured limit.
-# Keep in mind that this setting will automatically be set to ProcessPartial
-# when SecRuleEngine is set to DetectionOnly mode in order to minimize
-# disruptions when initially deploying ModSecurity.
-#
-SecRequestBodyLimitAction Reject
-
-# Verify that we've correctly processed the request body.
-# As a rule of thumb, when failing to process a request body
-# you should reject the request (when deployed in blocking mode)
-# or log a high-severity alert (when deployed in detection-only mode).
-#
-SecRule REQBODY_ERROR "!@eq 0" \
-"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
-
-# By default be strict with what we accept in the multipart/form-data
-# request body. If the rule below proves to be too strict for your
-# environment consider changing it to detection-only. You are encouraged
-# _not_ to remove it altogether.
-#
-SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
-"id:'200003',phase:2,t:none,log,deny,status:400, \
-msg:'Multipart request body failed strict validation: \
-PE %{REQBODY_PROCESSOR_ERROR}, \
-BQ %{MULTIPART_BOUNDARY_QUOTED}, \
-BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
-DB %{MULTIPART_DATA_BEFORE}, \
-DA %{MULTIPART_DATA_AFTER}, \
-HF %{MULTIPART_HEADER_FOLDING}, \
-LF %{MULTIPART_LF_LINE}, \
-SM %{MULTIPART_MISSING_SEMICOLON}, \
-IQ %{MULTIPART_INVALID_QUOTING}, \
-IP %{MULTIPART_INVALID_PART}, \
-IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
-FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
-
-# Did we see anything that might be a boundary?
-#
-# Here is a short description about the ModSecurity Multipart parser: the
-# parser returns with value 0, if all "boundary-like" line matches with
-# the boundary string which given in MIME header. In any other cases it returns
-# with different value, eg. 1 or 2.
-#
-# The RFC 1341 descript the multipart content-type and its syntax must contains
-# only three mandatory lines (above the content):
-# * Content-Type: multipart/mixed; boundary=BOUNDARY_STRING
-# * --BOUNDARY_STRING
-# * --BOUNDARY_STRING--
-#
-# First line indicates, that this is a multipart content, second shows that
-# here starts a part of the multipart content, third shows the end of content.
-#
-# If there are any other lines, which starts with "--", then it should be
-# another boundary id - or not.
-#
-# After 3.0.3, there are two kinds of types of boundary errors: strict and permissive.
-#
-# If multipart content contains the three necessary lines with correct order, but
-# there are one or more lines with "--", then parser returns with value 2 (non-zero).
-#
-# If some of the necessary lines (usually the start or end) misses, or the order
-# is wrong, then parser returns with value 1 (also a non-zero).
-#
-# You can choose, which one is what you need. The example below contains the
-# 'strict' mode, which means if there are any lines with start of "--", then
-# ModSecurity blocked the content. But the next, commented example contains
-# the 'permissive' mode, then you check only if the necessary lines exists in
-# correct order. Whit this, you can enable to upload PEM files (eg "----BEGIN.."),
-# or other text files, which contains eg. HTTP headers.
-#
-# The difference is only the operator - in strict mode (first) the content blocked
-# in case of any non-zero value. In permissive mode (second, commented) the
-# content blocked only if the value is explicit 1. If it 0 or 2, the content will
-# allowed.
-#
-
-#
-# See #1747 and #1924 for further information on the possible values for
-# MULTIPART_UNMATCHED_BOUNDARY.
-#
-SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
-    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
-
-
-# PCRE Tuning
-# We want to avoid a potential RegEx DoS condition
-#
-SecPcreMatchLimit 1000
-SecPcreMatchLimitRecursion 1000
-
-# Some internal errors will set flags in TX and we will need to look for these.
-# All of these are prefixed with "MSC_".  The following flags currently exist:
-#
-# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded.
-#
-SecRule TX:/^MSC_/ "!@streq 0" \
-        "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
-
-
-# -- Response body handling --------------------------------------------------
-
-# Allow ModSecurity to access response bodies.
-# You should have this directive enabled in order to identify errors
-# and data leakage issues.
-#
-# Do keep in mind that enabling this directive does increases both
-# memory consumption and response latency.
-#
-SecResponseBodyAccess On
-
-# Which response MIME types do you want to inspect? You should adjust the
-# configuration below to catch documents but avoid static files
-# (e.g., images and archives).
-#
-SecResponseBodyMimeType text/plain text/html text/xml
-
-# Buffer response bodies of up to 512 KB in length.
-SecResponseBodyLimit 524288
-
-# What happens when we encounter a response body larger than the configured
-# limit? By default, we process what we have and let the rest through.
-# That's somewhat less secure, but does not break any legitimate pages.
-#
-SecResponseBodyLimitAction ProcessPartial
-
-
-# -- Filesystem configuration ------------------------------------------------
-
-# The location where ModSecurity stores temporary files (for example, when
-# it needs to handle a file upload that is larger than the configured limit).
-#
-# This default setting is chosen due to all systems have /tmp available however,
-# this is less than ideal. It is recommended that you specify a location that's private.
-#
-SecTmpDir /tmp/
-
-# The location where ModSecurity will keep its persistent data.  This default setting
-# is chosen due to all systems have /tmp available however, it
-# too should be updated to a place that other users can't access.
-#
-SecDataDir /var/tmp/
-
-
-# -- File uploads handling configuration -------------------------------------
-
-# The location where ModSecurity stores intercepted uploaded files. This
-# location must be private to ModSecurity. You don't want other users on
-# the server to access the files, do you?
-#
-#SecUploadDir /opt/modsecurity/var/upload/
-
-# By default, only keep the files that were determined to be unusual
-# in some way (by an external inspection script). For this to work you
-# will also need at least one file inspection rule.
-#
-#SecUploadKeepFiles RelevantOnly
-
-# Uploaded files are by default created with permissions that do not allow
-# any other user to access them. You may need to relax that if you want to
-# interface ModSecurity to an external program (e.g., an anti-virus).
-#
-#SecUploadFileMode 0600
-
-
-# -- Debug log configuration -------------------------------------------------
-
-# The default debug log configuration is to duplicate the error, warning
-# and notice messages from the error log.
-#
-#SecDebugLog /opt/modsecurity/var/log/debug.log
-#SecDebugLogLevel 3
-
-
-# -- Audit log configuration -------------------------------------------------
-
-# Log the transactions that are marked by a rule, as well as those that
-# trigger a server error (determined by a 5xx or 4xx, excluding 404,
-# level response status codes).
-#
-SecAuditEngine RelevantOnly
-SecAuditLogRelevantStatus "^(?:5|4(?!04))"
-
-# Log everything we know about a transaction.
-SecAuditLogParts ABIJDEFHZ
-
-# Use a single file for logging. This is much easier to look at, but
-# assumes that you will use the audit log only ocassionally.
-#
-SecAuditLogType Serial
-#SecAuditLog /var/log/modsec_audit.log
-SecAuditLog /dev/stdout
-
-# Specify the path for concurrent audit logging.
-#SecAuditLogStorageDir /opt/modsecurity/var/audit/
-
-
-# -- Miscellaneous -----------------------------------------------------------
-
-# Use the most commonly used application/x-www-form-urlencoded parameter
-# separator. There's probably only one application somewhere that uses
-# something else so don't expect to change this value.
-#
-SecArgumentSeparator &
-
-# Settle on version 0 (zero) cookies, as that is what most applications
-# use. Using an incorrect cookie version may open your installation to
-# evasion attacks (against the rules that examine named cookies).
-#
-SecCookieFormat 0
-
-# Specify your Unicode Code Point.
-# This mapping is used by the t:urlDecodeUni transformation function
-# to properly map encoded data to your language. Properly setting
-# these directives helps to reduce false positives and negatives.
-#
-SecUnicodeMapFile unicode.mapping 20127
-
-# Improve the quality of ModSecurity by sharing information about your
-# current ModSecurity version and dependencies versions.
-# The following information will be shared: ModSecurity version,
-# Web Server version, APR version, PCRE version, Lua version, Libxml2
-# version, Anonymous unique id for host.
-SecStatusEngine On
-
diff --git a/examples/modsecurity/etc/nginx/modsec/unicode.mapping b/examples/modsecurity/etc/nginx/modsec/unicode.mapping
deleted file mode 100644
index 64b1637..0000000
--- a/examples/modsecurity/etc/nginx/modsec/unicode.mapping
+++ /dev/null
@@ -1,96 +0,0 @@
-(MAC - Roman)
-
-
-(MAC - Icelandic)
-
-
-1250  (ANSI - Central Europe)
-00a1:21 00a2:63 00a3:4c 00a5:59 00aa:61 00b2:32 00b3:33 00b9:31 00ba:6f 00bc:31 00bd:31 00be:33 00c0:41 00c3:41 00c5:41 00c6:41 00c8:45 00ca:45 00cc:49 00cf:49 00d1:4e 00d2:4f 00d5:4f 00d8:4f 00d9:55 00db:55 00e0:61 00e3:61 00e5:61 00e6:61 00e8:65 00ea:65 00ec:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f8:6f 00f9:75 00fb:75 00ff:79 0100:41 0101:61 0108:43 0109:63 010a:43 010b:63 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 013b:4c 013c:6c 0145:4e 0146:6e 014c:4f 014d:6f 014e:4f 014f:6f 0152:4f 0153:6f 0156:52 0157:72 015c:53 015d:73 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0180:62 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2032:27 2035:60 203c:21 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2191:5e 2194:2d 2195:7c 21a8:7c 2212:2d 2215:2f 2216:5c 2217:2a 221f:4c 2223:7c 2236:3a 223c:7e 2303:5e 2329:3c 232a:3e 2502:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263c:30 2640:2b 2642:3e 266a:64 266b:64 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1251  (ANSI - Cyrillic)
-00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 203c:21 2190:3c 2191:5e 2192:3e 2193:76 2194:2d 221a:76 221f:4c 2500:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2552:2d 2558:4c 2559:4c 255a:4c 255b:2d 255c:2d 255d:2d 2564:54 2565:54 2566:54 256a:2b 256b:2b 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1252  (ANSI - Latin I)
-0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c8:27 02cb:60 02cd:5f 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 0393:47 0398:54 03a3:53 03a6:46 03a9:4f 03b1:61 03b4:64 03b5:65 03c0:70 03c3:73 03c4:74 03c6:66 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2017:3d 2032:27 2035:60 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 207f:6e 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2212:2d 2215:2f 2216:5c 2217:2a 221a:76 221e:38 2223:7c 2229:6e 2236:3a 223c:7e 2261:3d 2264:3d 2265:3d 2303:5e 2320:28 2321:29 2329:3c 232a:3e 2500:2d 250c:2b 2510:2b 2514:2b 2518:2b 251c:2b 252c:2d 2534:2d 253c:2b 2550:2d 2552:2b 2553:2b 2554:2b 2555:2b 2556:2b 2557:2b 2558:2b 2559:2b 255a:2b 255b:2b 255c:2b 255d:2b 2564:2d 2565:2d 2566:2d 2567:2d 2568:2d 2569:2d 256a:2b 256b:2b 256c:2b 2584:5f 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1253  (ANSI - Greek)
-00b4:2f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 037e:3b 203c:21 2190:3c 2191:5e 2192:3e 2193:76 2194:2d 221f:4c 2500:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1254  (ANSI - Turkish)
-00dd:59 00fd:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c7:5e 02c8:27 02cb:60 02cd:5f 02d8:5e 02d9:27 0300:60 0302:5e 0331:5f 0332:5f 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2032:27 2035:60 203c:21 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2081:30 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2191:5e 2193:76 2194:2d 2195:7c 21a8:7c 2212:2d 2215:2f 2216:5c 2217:2a 221f:4c 2223:7c 2236:3a 223c:7e 2303:5e 2329:3c 232a:3e 2502:2d 250c:2d 2514:4c 2518:2d 251c:2b 2524:2b 252c:54 2534:2b 253c:2b 2550:3d 2554:2d 255a:4c 255d:2d 2566:54 256c:2b 2580:2d 2584:2d 2588:2d 2591:2d 2592:2d 2593:2d 25ac:2d 25b2:5e 25ba:3e 25c4:3c 25cb:30 25d9:30 263a:4f 263b:4f 263c:30 2640:2b 2642:3e 266a:64 266b:64 2758:7c 3000:20 3008:3c 3009:3e 301a:5b 301b:3d 301d:22 301e:22 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1255  (ANSI - Hebrew)
-0191:46 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1256  (ANSI - Arabic)
-0620:41 0621:41 0622:43 0623:45 0624:45 0625:45 0626:45 0627:49 0628:49 0629:4f 062a:55 062b:55 062c:55 062d:46 062e:43 062f:44 0630:45 0631:46 0632:47 0633:48 0634:49 0635:4a 0636:4b 0637:4c 0638:4d 0639:4e 063a:4f 0641:41 0642:42 0643:43 0644:44 0645:45 0646:46 0647:47 0648:48 0649:49 064a:4a 064b:4b 064c:4c 064d:4d 064e:4e 064f:4f 0650:50 0651:51 0652:52 
-
-1257  (ANSI - Baltic)
-ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-1258  (ANSI/OEM - Viet Nam)
-ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-20127 (US-ASCII)
-00a0:20 00a1:21 00a2:63 00a4:24 00a5:59 00a6:7c 00a9:43 00aa:61 00ab:3c 00ad:2d 00ae:52 00b2:32 00b3:33 00b7:2e 00b8:2c 00b9:31 00ba:6f 00bb:3e 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-20261 (T.61)
-f8dd:5c f8de:5e f8df:60 f8e0:7b f8fc:7d f8fd:7e f8fe:7f 
-
-20866 (Russian - KOI8)
-00a7:15 00ab:3c 00ad:2d 00ae:52 00b1:2b 00b6:14 00bb:3e 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2026:3a 2030:25 2039:3c 203a:3e 203c:13 2122:54 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 221f:1c 2302:7f 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 
-
-28591 (ISO 8859-1 Latin I)
-0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-28592 (ISO 8859-2 Central Europe)
-00a1:21 00a2:63 00a5:59 00a6:7c 00a9:43 00aa:61 00ab:3c 00ae:52 00b2:32 00b3:33 00b7:2e 00b9:31 00ba:6f 00bb:3e 00c0:41 00c3:41 00c5:41 00c6:41 00c8:45 00ca:45 00cc:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d5:4f 00d8:4f 00d9:55 00db:55 00e0:61 00e3:61 00e5:61 00e6:61 00e8:65 00ea:65 00ec:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f8:6f 00f9:75 00fb:75 00ff:79 0100:41 0101:61 0108:43 0109:63 010a:43 010b:63 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 013b:4c 013c:6c 0145:4e 0146:6e 014c:4f 014d:6f 014e:4f 014f:6f 0152:4f 0153:6f 0156:52 0157:72 015c:53 015d:73 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-28605 (ISO 8859-15 Latin 9)
-00a6:7c 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0138:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014a:4e 014b:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:54 0169:74 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0179:5a 017b:5a 017c:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:2e 2026:2e 2032:27 2035:60 2039:3c 203a:3e 2122:54 ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-37    (IBM EBCDIC - U.S./Canada)
-0004:37 0005:2d 0006:2e 0007:2f 0008:16 0009:05 000a:25 0014:3c 0015:3d 0016:32 0017:26 001a:3f 001b:27 0020:40 0021:5a 0022:7f 0023:7b 0024:5b 0025:6c 0026:50 0027:7d 0028:4d 0029:5d 002a:5c 002b:4e 002c:6b 002d:60 002e:4b 002f:61 003a:7a 003b:5e 003c:4c 003d:7e 003e:6e 003f:6f 0040:7c 005f:6d 0060:79 007c:4f 007f:07 0080:20 0081:21 0082:22 0083:23 0084:24 0085:15 0086:06 0087:17 0088:28 0089:29 008a:2a 008b:2b 008c:2c 008d:09 008e:0a 008f:1b 0090:30 0091:31 0092:1a 0093:33 0094:34 0095:35 0096:36 0097:08 0098:38 0099:39 009a:3a 009b:3b 009c:04 009d:14 009e:3e 00a0:41 00a2:4a 00a6:6a 00ac:5f 00c0:64 00c1:65 00c2:62 00c3:66 00c4:63 00c5:67 00c7:68 00c8:74 00c9:71 00ca:72 00cb:73 00cc:78 00cd:75 00ce:76 00cf:77 00d1:69 00df:59 00e0:44 00e1:45 00e2:42 00e3:46 00e4:43 00e5:47 00e7:48 00e8:54 00e9:51 00ea:52 00eb:53 00ec:58 00ed:55 00ee:56 00ef:57 00f1:49 00f8:70 ff01:5a ff02:7f ff03:7b ff04:5b ff05:6c ff06:50 ff07:7d ff08:4d ff09:5d ff0a:5c ff0b:4e ff0c:6b ff0d:60 ff0e:4b ff0f:61 ff1a:7a ff1b:5e ff1c:4c ff1d:7e ff1e:6e ff20:7c ff3f:6d ff40:79 ff5c:4f 
-
-437   (OEM - United States)
-00a4:0f 00a7:15 00a8:22 00a9:63 00ad:2d 00ae:72 00af:5f 00b3:33 00b4:27 00b6:14 00b8:2c 00b9:31 00be:5f 00c0:41 00c1:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d7:78 00d8:4f 00d9:55 00da:55 00db:55 00dd:59 00de:5f 00e3:61 00f0:64 00f5:6f 00f8:6f 00fd:79 00fe:5f 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02ca:27 02cb:60 02cd:5f 02dc:7e 0300:60 0301:27 0302:5e 0303:7e 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:60 2019:27 201a:2c 201c:22 201d:22 201e:2c 2020:2b 2022:07 2026:2e 2030:25 2032:27 2035:60 2039:3c 203a:3e 203c:13 2044:2f 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2082:32 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:09 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2122:54 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2212:2d 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 2758:7c 3000:20 3007:09 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-500   (IBM EBCDIC - International)
-0004:37 0005:2d 0006:2e 0007:2f 0008:16 0009:05 000a:25 0014:3c 0015:3d 0016:32 0017:26 001a:3f 001b:27 0020:40 0021:4f 0022:7f 0023:7b 0024:5b 0025:6c 0026:50 0027:7d 0028:4d 0029:5d 002a:5c 002b:4e 002c:6b 002d:60 002e:4b 002f:61 003a:7a 003b:5e 003c:4c 003d:7e 003e:6e 003f:6f 0040:7c 005b:4a 005d:5a 005e:5f 005f:6d 0060:79 007f:07 0080:20 0081:21 0082:22 0083:23 0084:24 0085:15 0086:06 0087:17 0088:28 0089:29 008a:2a 008b:2b 008c:2c 008d:09 008e:0a 008f:1b 0090:30 0091:31 0092:1a 0093:33 0094:34 0095:35 0096:36 0097:08 0098:38 0099:39 009a:3a 009b:3b 009c:04 009d:14 009e:3e 00a0:41 00a6:6a 00c0:64 00c1:65 00c2:62 00c3:66 00c4:63 00c5:67 00c7:68 00c8:74 00c9:71 00ca:72 00cb:73 00cc:78 00cd:75 00ce:76 00cf:77 00d1:69 00df:59 00e0:44 00e1:45 00e2:42 00e3:46 00e4:43 00e5:47 00e7:48 00e8:54 00e9:51 00ea:52 00eb:53 00ec:58 00ed:55 00ee:56 00ef:57 00f1:49 00f8:70 ff01:4f ff02:7f ff03:7b ff04:5b ff05:6c ff06:50 ff07:7d ff08:4d ff09:5d ff0a:5c ff0b:4e ff0c:6b ff0d:60 ff0e:4b ff0f:61 ff1a:7a ff1b:5e ff1c:4c ff1d:7e ff1e:6e ff20:7c ff3b:4a ff3d:5a ff3e:5f ff3f:6d ff40:79 
-
-850   (OEM - Multilingual Latin I)
-0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01a9:53 01ab:74 01ae:54 01af:55 01b0:75 01b6:5a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02cb:27 02cd:5f 02dc:7e 0300:27 0302:5e 0303:7e 030e:22 0331:5f 0332:5f 037e:3b 0393:47 03a3:53 03a6:46 03a9:4f 03b1:61 03b4:64 03b5:65 03c0:70 03c3:73 03c4:74 03c6:66 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:2e 2030:25 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:39 207f:6e 2080:30 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:50 2119:50 211a:51 211b:52 211c:52 211d:52 2122:54 2124:5a 2126:4f 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2211:53 2212:2d 2215:2f 2216:2f 2217:2a 2219:07 221a:56 221e:38 221f:1c 2229:6e 2236:3a 223c:7e 2248:7e 2261:3d 2264:3d 2265:3d 2302:7f 2303:5e 2320:28 2321:29 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 2713:56 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-860   (OEM - Portuguese)
-00a4:0f 00a5:59 00a7:15 00a8:22 00a9:63 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00be:33 00c4:41 00c5:41 00c6:41 00cb:45 00ce:49 00cf:49 00d0:44 00d6:4f 00d7:58 00d8:4f 00db:55 00dd:59 00de:54 00e4:61 00e5:61 00e6:61 00eb:65 00ee:69 00ef:69 00f0:64 00f6:6f 00f8:6f 00fb:75 00fd:79 00fe:74 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:5c 0161:7c 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0191:46 0192:66 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c0:7c 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 0278:66 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:5f 2011:5f 2013:5f 2014:5f 2017:5f 2018:27 2019:27 201a:2c 201c:22 201d:22 201e:22 2022:07 2024:07 2026:2e 2030:25 2032:27 2035:60 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212b:41 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 
-
-861   (OEM - Icelandic)
-00a2:63 00a4:0f 00a5:59 00a7:15 00a8:22 00a9:63 00aa:61 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00ba:6f 00be:33 00c0:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d4:4f 00d5:4f 00d7:58 00d9:55 00db:55 00e3:61 00ec:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f5:6f 00f9:75 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 0278:66 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 
-
-863   (OEM - Canadian French)
-00a1:21 00a5:59 00a9:63 00aa:61 00ad:16 00ae:72 00b9:33 00ba:6f 00c1:41 00c3:41 00c4:41 00c5:41 00c6:41 00cc:49 00cd:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d5:4f 00d6:4f 00d7:58 00d8:4f 00da:55 00dd:59 00de:54 00e1:61 00e3:61 00e4:61 00e5:61 00e6:61 00ec:69 00ed:69 00f0:64 00f1:6e 00f2:6f 00f5:6f 00f6:6f 00f8:6f 00fd:79 00fe:74 00ff:79 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:22 02ba:27 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02cb:60 02cd:5f 02dc:7e 0300:60 0302:5e 0303:7e 0304:16 0305:16 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20a7:50 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212b:41 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 301a:5b 301b:5d 30fb:07 
-
-865   (OEM - Nordic)
-00a2:63 00a5:59 00a7:15 00a8:22 00a9:63 00ad:5f 00ae:72 00af:16 00b3:33 00b4:2f 00b6:14 00b8:2c 00b9:31 00bb:3e 00be:33 00c0:41 00c1:41 00c2:41 00c3:41 00c8:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d7:58 00d9:55 00da:55 00db:55 00dd:59 00de:54 00e3:61 00f0:64 00f5:6f 00fd:79 00fe:74 0100:41 0101:61 0102:41 0103:61 0104:41 0105:61 0106:43 0107:63 0108:43 0109:63 010a:43 010b:63 010c:43 010d:63 010e:44 010f:64 0110:44 0111:64 0112:45 0113:65 0114:45 0115:65 0116:45 0117:65 0118:45 0119:65 011a:45 011b:65 011c:47 011d:67 011e:47 011f:67 0120:47 0121:67 0122:47 0123:67 0124:48 0125:68 0126:48 0127:68 0128:49 0129:69 012a:49 012b:69 012c:49 012d:69 012e:49 012f:69 0130:49 0131:69 0134:4a 0135:6a 0136:4b 0137:6b 0139:4c 013a:6c 013b:4c 013c:6c 013d:4c 013e:6c 0141:4c 0142:6c 0143:4e 0144:6e 0145:4e 0146:6e 0147:4e 0148:6e 014c:4f 014d:6f 014e:4f 014f:6f 0150:4f 0151:6f 0152:4f 0153:6f 0154:52 0155:72 0156:52 0157:72 0158:52 0159:72 015a:53 015b:73 015c:53 015d:73 015e:53 015f:73 0160:53 0161:73 0162:54 0163:74 0164:54 0165:74 0166:54 0167:74 0168:55 0169:75 016a:55 016b:75 016c:55 016d:75 016e:55 016f:75 0170:55 0171:75 0172:55 0173:75 0174:57 0175:77 0176:59 0177:79 0178:59 0179:5a 017b:5a 017c:7a 017d:5a 017e:7a 0180:62 0189:44 0197:49 019a:6c 019f:4f 01a0:4f 01a1:6f 01ab:74 01ae:54 01af:55 01b0:75 01b6:7a 01c3:21 01cd:41 01ce:61 01cf:49 01d0:69 01d1:4f 01d2:6f 01d3:55 01d4:75 01d5:55 01d6:75 01d7:55 01d8:75 01d9:55 01da:75 01db:55 01dc:75 01de:41 01df:61 01e4:47 01e5:67 01e6:47 01e7:67 01e8:4b 01e9:6b 01ea:4f 01eb:6f 01ec:4f 01ed:6f 01f0:6a 0261:67 02b9:27 02ba:22 02bc:27 02c4:5e 02c6:5e 02c8:27 02c9:16 02ca:2f 02cb:60 02cd:5f 02dc:7e 0300:60 0301:2f 0302:5e 0303:7e 0304:16 0305:16 0308:22 030e:22 0327:2c 0331:5f 0332:5f 037e:3b 04bb:68 0589:3a 066a:25 2000:20 2001:20 2002:20 2003:20 2004:20 2005:20 2006:20 2010:2d 2011:2d 2013:2d 2014:2d 2017:5f 2018:27 2019:27 201a:27 201c:22 201d:22 201e:22 2022:07 2024:07 2026:07 2030:25 2032:27 2035:27 2039:3c 203a:3e 203c:13 2044:2f 2070:30 2074:34 2075:35 2076:36 2077:37 2078:38 2080:30 2081:31 2083:33 2084:34 2085:35 2086:36 2087:37 2088:38 2089:39 20dd:4f 2102:43 2107:45 210a:67 210b:48 210c:48 210d:48 210e:68 2110:49 2111:49 2112:4c 2113:6c 2115:4e 2118:70 2119:50 211a:51 211b:52 211c:52 211d:52 2122:74 2124:5a 2128:5a 212a:4b 212c:42 212d:43 212e:65 212f:65 2130:45 2131:46 2133:4d 2134:6f 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 2205:4f 2212:5f 2215:2f 2216:5c 2217:2a 221f:1c 2223:7c 2236:3a 223c:7e 226b:3c 22c5:07 2302:7f 2303:5e 2329:3c 232a:3e 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e 3000:20 3007:4f 3008:3c 3009:3e 300b:3e 301a:5b 301b:5d 30fb:07 
-
-874   (ANSI/OEM - Thai)
-00a7:15 00b6:14 203c:13 2190:1b 2191:18 2192:1a 2193:19 2194:1d 2195:12 21a8:17 221f:1c 2302:7f 25ac:16 25b2:1e 25ba:10 25bc:1f 25c4:11 25cb:09 25d8:08 25d9:0a 263a:01 263b:02 263c:0f 2640:0c 2642:0b 2660:06 2663:05 2665:03 2666:04 266a:0d 266b:0e ff01:21 ff02:22 ff03:23 ff04:24 ff05:25 ff06:26 ff07:27 ff08:28 ff09:29 ff0a:2a ff0b:2b ff0c:2c ff0d:2d ff0e:2e ff0f:2f ff10:30 ff11:31 ff12:32 ff13:33 ff14:34 ff15:35 ff16:36 ff17:37 ff18:38 ff19:39 ff1a:3a ff1b:3b ff1c:3c ff1d:3d ff1e:3e ff20:40 ff21:41 ff22:42 ff23:43 ff24:44 ff25:45 ff26:46 ff27:47 ff28:48 ff29:49 ff2a:4a ff2b:4b ff2c:4c ff2d:4d ff2e:4e ff2f:4f ff30:50 ff31:51 ff32:52 ff33:53 ff34:54 ff35:55 ff36:56 ff37:57 ff38:58 ff39:59 ff3a:5a ff3b:5b ff3c:5c ff3d:5d ff3e:5e ff3f:5f ff40:60 ff41:61 ff42:62 ff43:63 ff44:64 ff45:65 ff46:66 ff47:67 ff48:68 ff49:69 ff4a:6a ff4b:6b ff4c:6c ff4d:6d ff4e:6e ff4f:6f ff50:70 ff51:71 ff52:72 ff53:73 ff54:74 ff55:75 ff56:76 ff57:77 ff58:78 ff59:79 ff5a:7a ff5b:7b ff5c:7c ff5d:7d ff5e:7e 
-
-932   (ANSI/OEM - Japanese Shift-JIS)
-00a1:21 00a5:5c 00a6:7c 00a9:63 00aa:61 00ad:2d 00ae:52 00b2:32 00b3:33 00b9:31 00ba:6f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00de:54 00df:73 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f0:64 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00fe:74 00ff:79 
-
-936   (ANSI/OEM - Simplified Chinese GBK)
-00a6:7c 00aa:61 00ad:2d 00b2:32 00b3:33 00b9:31 00ba:6f 00d0:44 00dd:59 00de:54 00e2:61 00f0:65 00fd:79 00fe:74 
-
-949   (ANSI/OEM - Korean)
-00a6:7c 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00ff:79 20a9:5c 
-
-950   (ANSI/OEM - Traditional Chinese Big5)
-00a1:21 00a6:7c 00a9:63 00aa:61 00ad:2d 00ae:52 00b2:32 00b3:33 00b9:31 00ba:6f 00c0:41 00c1:41 00c2:41 00c3:41 00c4:41 00c5:41 00c6:41 00c7:43 00c8:45 00c9:45 00ca:45 00cb:45 00cc:49 00cd:49 00ce:49 00cf:49 00d0:44 00d1:4e 00d2:4f 00d3:4f 00d4:4f 00d5:4f 00d6:4f 00d8:4f 00d9:55 00da:55 00db:55 00dc:55 00dd:59 00de:54 00df:73 00e0:61 00e1:61 00e2:61 00e3:61 00e4:61 00e5:61 00e6:61 00e7:63 00e8:65 00e9:65 00ea:65 00eb:65 00ec:69 00ed:69 00ee:69 00ef:69 00f0:65 00f1:6e 00f2:6f 00f3:6f 00f4:6f 00f5:6f 00f6:6f 00f8:6f 00f9:75 00fa:75 00fb:75 00fc:75 00fd:79 00fe:74 00ff:79 
-
-(UTF-7)
-
-
-(UTF-8)
-
-
diff --git a/examples/modsecurity/usr/local/nginx/conf/owasp-modsecurity-crs/crs-setup.conf b/examples/modsecurity/usr/local/nginx/conf/owasp-modsecurity-crs/crs-setup.conf
deleted file mode 100644
index 71d0a94..0000000
--- a/examples/modsecurity/usr/local/nginx/conf/owasp-modsecurity-crs/crs-setup.conf
+++ /dev/null
@@ -1,832 +0,0 @@
-# ------------------------------------------------------------------------
-# OWASP ModSecurity Core Rule Set ver.3.3.0
-# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
-#
-# The OWASP ModSecurity Core Rule Set is distributed under
-# Apache Software License (ASL) version 2
-# Please see the enclosed LICENSE file for full details.
-# ------------------------------------------------------------------------
-
-
-#
-# -- [[ Introduction ]] --------------------------------------------------------
-#
-# The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack
-# detection rules that provide a base level of protection for any web
-# application. They are written for the open source, cross-platform
-# ModSecurity Web Application Firewall.
-#
-# See also:
-# https://coreruleset.org/
-# https://github.com/SpiderLabs/owasp-modsecurity-crs
-# https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
-#
-
-
-#
-# -- [[ System Requirements ]] -------------------------------------------------
-#
-# CRS requires ModSecurity version 2.8.0 or above.
-# We recommend to always use the newest ModSecurity version.
-#
-# The configuration directives/settings in this file are used to control
-# the OWASP ModSecurity CRS. These settings do **NOT** configure the main
-# ModSecurity settings (modsecurity.conf) such as SecRuleEngine,
-# SecRequestBodyAccess, SecAuditEngine, SecDebugLog, and XML processing.
-#
-# The CRS assumes that modsecurity.conf has been loaded. It is bundled with
-# ModSecurity. If you don't have it, you can get it from:
-# 2.x: https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v2/master/modsecurity.conf-recommended
-# 3.x: https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
-#
-# The order of file inclusion in your webserver configuration should always be:
-# 1. modsecurity.conf
-# 2. crs-setup.conf (this file)
-# 3. rules/*.conf (the CRS rule files)
-#
-# Please refer to the INSTALL file for detailed installation instructions.
-#
-
-
-#
-# -- [[ Mode of Operation: Anomaly Scoring vs. Self-Contained ]] ---------------
-#
-# The CRS can run in two modes:
-#
-# -- [[ Anomaly Scoring Mode (default) ]] --
-# In CRS3, anomaly mode is the default and recommended mode, since it gives the
-# most accurate log information and offers the most flexibility in setting your
-# blocking policies. It is also called "collaborative detection mode".
-# In this mode, each matching rule increases an 'anomaly score'.
-# At the conclusion of the inbound rules, and again at the conclusion of the
-# outbound rules, the anomaly score is checked, and the blocking evaluation
-# rules apply a disruptive action, by default returning an error 403.
-#
-# -- [[ Self-Contained Mode ]] --
-# In this mode, rules apply an action instantly. This was the CRS2 default.
-# It can lower resource usage, at the cost of less flexibility in blocking policy
-# and less informative audit logs (only the first detected threat is logged).
-# Rules inherit the disruptive action that you specify (i.e. deny, drop, etc).
-# The first rule that matches will execute this action. In most cases this will
-# cause evaluation to stop after the first rule has matched, similar to how many
-# IDSs function.
-#
-# -- [[ Alert Logging Control ]] --
-# In the mode configuration, you must also adjust the desired logging options.
-# There are three common options for dealing with logging. By default CRS enables
-# logging to the webserver error log (or Event viewer) plus detailed logging to
-# the ModSecurity audit log (configured under SecAuditLog in modsecurity.conf).
-#
-# - To log to both error log and ModSecurity audit log file, use: "log,auditlog"
-# - To log *only* to the ModSecurity audit log file, use: "nolog,auditlog"
-# - To log *only* to the error log file, use: "log,noauditlog"
-#
-# Examples for the various modes follow.
-# You must leave one of the following options enabled.
-# Note that you must specify the same line for phase:1 and phase:2.
-#
-
-# Default: Anomaly Scoring mode, log to error log, log to ModSecurity audit log
-# - By default, offending requests are blocked with an error 403 response.
-# - To change the disruptive action, see RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
-#   and review section 'Changing the Disruptive Action for Anomaly Mode'.
-# - In Apache, you can use ErrorDocument to show a friendly error page or
-#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
-#
-# SecDefaultAction "phase:1,log,auditlog,pass"
-# SecDefaultAction "phase:2,log,auditlog,pass"
-
-# Example: Anomaly Scoring mode, log only to ModSecurity audit log
-# - By default, offending requests are blocked with an error 403 response.
-# - To change the disruptive action, see RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
-#   and review section 'Changing the Disruptive Action for Anomaly Mode'.
-# - In Apache, you can use ErrorDocument to show a friendly error page or
-#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
-#
-# SecDefaultAction "phase:1,nolog,auditlog,pass"
-# SecDefaultAction "phase:2,nolog,auditlog,pass"
-
-# Example: Self-contained mode, return error 403 on blocking
-# - In this configuration the default disruptive action becomes 'deny'. After a
-#   rule triggers, it will stop processing the request and return an error 403.
-# - You can also use a different error status, such as 404, 406, et cetera.
-# - In Apache, you can use ErrorDocument to show a friendly error page or
-#   perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html
-#
-
-# We want object to appear missing rather than denied in order to not leak data
-# about what is and isn't in the backing object store.
-SecDefaultAction "phase:1,log,auditlog,deny,status:404"
-SecDefaultAction "phase:2,log,auditlog,deny,status:404"
-
-# Example: Self-contained mode, redirect back to homepage on blocking
-# - In this configuration the 'tag' action includes the Host header data in the
-#   log. This helps to identify which virtual host triggered the rule (if any).
-# - Note that this might cause redirect loops in some situations; for example
-#   if a Cookie or User-Agent header is blocked, it will also be blocked when
-#   the client subsequently tries to access the homepage. You can also redirect
-#   to another custom URL.
-# SecDefaultAction "phase:1,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'"
-# SecDefaultAction "phase:2,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'"
-
-
-#
-# -- [[ Paranoia Level Initialization ]] ---------------------------------------
-#
-# The Paranoia Level (PL) setting allows you to choose the desired level
-# of rule checks that will add to your anomaly scores.
-#
-# With each paranoia level increase, the CRS enables additional rules
-# giving you a higher level of security. However, higher paranoia levels
-# also increase the possibility of blocking some legitimate traffic due to
-# false alarms (also named false positives or FPs). If you use higher
-# paranoia levels, it is likely that you will need to add some exclusion
-# rules for certain requests and applications receiving complex input.
-#
-# - A paranoia level of 1 is default. In this level, most core rules
-#   are enabled. PL1 is advised for beginners, installations
-#   covering many different sites and applications, and for setups
-#   with standard security requirements.
-#   At PL1 you should face FPs rarely. If you encounter FPs, please
-#   open an issue on the CRS GitHub site and don't forget to attach your
-#   complete Audit Log record for the request with the issue.
-# - Paranoia level 2 includes many extra rules, for instance enabling
-#   many regexp-based SQL and XSS injection protections, and adding
-#   extra keywords checked for code injections. PL2 is advised
-#   for moderate to experienced users desiring more complete coverage
-#   and for installations with elevated security requirements.
-#   PL2 comes with some FPs which you need to handle.
-# - Paranoia level 3 enables more rules and keyword lists, and tweaks
-#   limits on special characters used. PL3 is aimed at users experienced
-#   at the handling of FPs and at installations with a high security
-#   requirement.
-# - Paranoia level 4 further restricts special characters.
-#   The highest level is advised for experienced users protecting
-#   installations with very high security requirements. Running PL4 will
-#   likely produce a very high number of FPs which have to be
-#   treated before the site can go productive.
-#
-# All rules will log their PL to the audit log;
-# example: [tag "paranoia-level/2"]. This allows you to deduct from the
-# audit log how the WAF behavior is affected by paranoia level.
-#
-# It is important to also look into the variable
-# tx.enforce_bodyproc_urlencoded (Enforce Body Processor URLENCODED)
-# defined below. Enabling it closes a possible bypass of CRS.
-#
-# Uncomment this rule to change the default:
-#
-SecAction \
-  "id:900000,\
-   phase:1,\
-   nolog,\
-   pass,\
-   t:none,\
-   setvar:tx.paranoia_level=4"
-
-
-# It is possible to execute rules from a higher paranoia level but not include
-# them in the anomaly scoring. This allows you to take a well-tuned system on
-# paranoia level 1 and add rules from paranoia level 2 without having to fear
-# the new rules would lead to false positives that raise your score above the
-# threshold.
-# This optional feature is enabled by uncommenting the following rule and
-# setting the tx.executing_paranoia_level.
-# Technically, rules up to the level defined in tx.executing_paranoia_level
-# will be executed, but only the rules up to tx.paranoia_level affect the
-# anomaly scores.
-# By default, tx.executing_paranoia_level is set to tx.paranoia_level.
-# tx.executing_paranoia_level must not be lower than tx.paranoia_level.
-#
-# Please notice that setting tx.executing_paranoia_level to a higher paranoia
-# level results in a performance impact that is equally high as setting
-# tx.paranoia_level to said level.
-#
-#SecAction \
-#  "id:900001,\
-#   phase:1,\
-#   nolog,\
-#   pass,\
-#   t:none,\
-#   setvar:tx.executing_paranoia_level=1"
-
-
-#
-# -- [[ Enforce Body Processor URLENCODED ]] -----------------------------------
-#
-# ModSecurity selects the body processor based on the Content-Type request
-# header. But clients are not always setting the Content-Type header for their
-# request body payloads. This will leave ModSecurity with limited vision into
-# the payload.  The variable tx.enforce_bodyproc_urlencoded lets you force the
-# URLENCODED body processor in these situations. This is off by default, as it
-# implies a change of the behaviour of ModSecurity beyond CRS (the body
-# processor applies to all rules, not only CRS) and because it may lead to
-# false positives already on paranoia level 1. However, enabling this variable
-# closes a possible bypass of CRS so it should be considered.
-#
-# Uncomment this rule to change the default:
-#
-#SecAction \
-#  "id:900010,\
-#   phase:1,\
-#   nolog,\
-#   pass,\
-#   t:none,\
-#   setvar:tx.enforce_bodyproc_urlencoded=1"
-
-
-#
-# -- [[ Anomaly Mode Severity Levels ]] ----------------------------------------
-#
-# Each rule in the CRS has an associated severity level.
-# These are the default scoring points for each severity level.
-# These settings will be used to increment the anomaly score if a rule matches.
-# You may adjust these points to your liking, but this is usually not needed.
-#
-# - CRITICAL severity: Anomaly Score of 5.
-#       Mostly generated by the application attack rules (93x and 94x files).
-# - ERROR severity: Anomaly Score of 4.
-#       Generated mostly from outbound leakage rules (95x files).
-# - WARNING severity: Anomaly Score of 3.
-#       Generated mostly by malicious client rules (91x files).
-# - NOTICE severity: Anomaly Score of 2.
-#       Generated mostly by the protocol rules (92x files).
-#
-# In anomaly mode, these scores are cumulative.
-# So it's possible for a request to hit multiple rules.
-#
-# (Note: In this file, we use 'phase:1' to set CRS configuration variables.
-# In general, 'phase:request' is used. However, we want to make absolutely sure
-# that all configuration variables are set before the CRS rules are processed.)
-#
-#SecAction \
-# "id:900100,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.critical_anomaly_score=5,\
-#  setvar:tx.error_anomaly_score=4,\
-#  setvar:tx.warning_anomaly_score=3,\
-#  setvar:tx.notice_anomaly_score=2"
-
-
-#
-# -- [[ Anomaly Mode Blocking Threshold Levels ]] ------------------------------
-#
-# Here, you can specify at which cumulative anomaly score an inbound request,
-# or outbound response, gets blocked.
-#
-# Most detected inbound threats will give a critical score of 5.
-# Smaller violations, like violations of protocol/standards, carry lower scores.
-#
-# [ At default value ]
-# If you keep the blocking thresholds at the defaults, the CRS will work
-# similarly to previous CRS versions: a single critical rule match will cause
-# the request to be blocked and logged.
-#
-# [ Using higher values ]
-# If you want to make the CRS less sensitive, you can increase the blocking
-# thresholds, for instance to 7 (which would require multiple rule matches
-# before blocking) or 10 (which would require at least two critical alerts - or
-# a combination of many lesser alerts), or even higher. However, increasing the
-# thresholds might cause some attacks to bypass the CRS rules or your policies.
-#
-# [ New deployment strategy: Starting high and decreasing ]
-# It is a common practice to start a fresh CRS installation with elevated
-# anomaly scoring thresholds (>100) and then lower the limits as your
-# confidence in the setup grows. You may also look into the Sampling
-# Percentage section below for a different strategy to ease into a new
-# CRS installation.
-#
-# [ Anomaly Threshold / Paranoia Level Quadrant ]
-#
-#     High Anomaly Limit   |   High Anomaly Limit
-#     Low Paranoia Level   |   High Paranoia Level
-#     -> Fresh Site        |   -> Experimental Site
-# ------------------------------------------------------
-#     Low Anomaly Limit    |   Low Anomaly Limit
-#     Low Paranoia Level   |   High Paranoia Level
-#     -> Standard Site     |   -> High Security Site
-#
-# Uncomment this rule to change the defaults:
-#
-#SecAction \
-# "id:900110,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.inbound_anomaly_score_threshold=5,\
-#  setvar:tx.outbound_anomaly_score_threshold=4"
-
-#
-# -- [[ Application Specific Rule Exclusions ]] ----------------------------------------
-#
-# Some well-known applications may undertake actions that appear to be
-# malicious. This includes actions such as allowing HTML or Javascript within
-# parameters. In such cases the CRS aims to prevent false positives by allowing
-# administrators to enable prebuilt, application specific exclusions on an
-# application by application basis.
-# These application specific exclusions are distinct from the rules that would
-# be placed in the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS configuration file as
-# they are prebuilt for specific applications. The 'REQUEST-900' file is
-# designed for users to add their own custom exclusions. Note, using these
-# application specific exclusions may loosen restrictions of the CRS,
-# especially if used with an application they weren't designed for. As a result
-# they should be applied with care.
-# To use this functionality you must specify a supported application. To do so
-# uncomment rule 900130. In addition to uncommenting the rule you will need to
-# specify which application(s) you'd like to enable exclusions for. Only a
-# (very) limited set of applications are currently supported, please use the
-# filenames prefixed with 'REQUEST-903' to guide you in your selection.
-# Such filenames use the following convention:
-# REQUEST-903.9XXX-{APPNAME}-EXCLUSIONS-RULES.conf
-#
-# It is recommended if you run multiple web applications on your site to limit
-# the effects of the exclusion to only the path where the excluded webapp
-# resides using a rule similar to the following example:
-# SecRule REQUEST_URI "@beginsWith /wordpress/" setvar:tx.crs_exclusions_wordpress=1
-
-#
-# Modify and uncomment this rule to select which application:
-#
-#SecAction \
-# "id:900130,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.crs_exclusions_cpanel=1,\
-#  setvar:tx.crs_exclusions_drupal=1,\
-#  setvar:tx.crs_exclusions_dokuwiki=1,\
-#  setvar:tx.crs_exclusions_nextcloud=1,\
-#  setvar:tx.crs_exclusions_wordpress=1,\
-#  setvar:tx.crs_exclusions_xenforo=1"
-
-#
-# -- [[ HTTP Policy Settings ]] ------------------------------------------------
-#
-# This section defines your policies for the HTTP protocol, such as:
-# - allowed HTTP versions, HTTP methods, allowed request Content-Types
-# - forbidden file extensions (e.g. .bak, .sql) and request headers (e.g. Proxy)
-#
-# These variables are used in the following rule files:
-# - REQUEST-911-METHOD-ENFORCEMENT.conf
-# - REQUEST-912-DOS-PROTECTION.conf
-# - REQUEST-920-PROTOCOL-ENFORCEMENT.conf
-
-# HTTP methods that a client is allowed to use.
-# Default: GET HEAD POST OPTIONS
-# Example: for RESTful APIs, add the following methods: PUT PATCH DELETE
-# Example: for WebDAV, add the following methods: CHECKOUT COPY DELETE LOCK
-#          MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK
-# Uncomment this rule to change the default.
-SecAction \
- "id:900200,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:'tx.allowed_methods=GET HEAD'"
-
-# Content-Types that a client is allowed to send in a request.
-# Default: |application/x-www-form-urlencoded| |multipart/form-data| |multipart/related|
-# |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json|
-# |application/cloudevents+json| |application/cloudevents-batch+json| |application/octet-stream|
-# |application/csp-report| |application/xss-auditor-report| |text/plain|
-# Uncomment this rule to change the default.
-#SecAction \
-# "id:900220,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json| |application/octet-stream| |application/csp-report| |application/xss-auditor-report| |text/plain|'"
-
-# Allowed HTTP versions.
-# Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0
-# Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0
-# Note that some web server versions use 'HTTP/2', some 'HTTP/2.0', so
-# we include both version strings by default.
-# Uncomment this rule to change the default.
-#SecAction \
-# "id:900230,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'"
-
-# Forbidden file extensions.
-# Guards against unintended exposure of development/configuration files.
-# Default: .asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/
-# Example: .bak/ .config/ .conf/ .db/ .ini/ .log/ .old/ .pass/ .pdb/ .rdb/ .sql/
-# Uncomment this rule to change the default.
-#SecAction \
-# "id:900240,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'"
-
-# Forbidden request headers.
-# Header names should be lowercase, enclosed by /slashes/ as delimiters.
-# Blocking Proxy header prevents 'httpoxy' vulnerability: https://httpoxy.org
-# Default: /proxy/ /lock-token/ /content-range/ /if/
-# Uncomment this rule to change the default.
-#SecAction \
-# "id:900250,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.restricted_headers=/proxy/ /lock-token/ /content-range/ /if/'"
-
-# File extensions considered static files.
-# Extensions include the dot, lowercase, enclosed by /slashes/ as delimiters.
-# Used in DoS protection rule. See section "Anti-Automation / DoS Protection".
-# Default: /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/
-# Uncomment this rule to change the default.
-SecAction \
- "id:900260,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'"
-
-# Content-Types charsets that a client is allowed to send in a request.
-# Default: utf-8|iso-8859-1|iso-8859-15|windows-1252
-# Uncomment this rule to change the default.
-# Use "|" to separate multiple charsets like in the rule defining
-# tx.allowed_request_content_type.
-#SecAction \
-# "id:900280,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'"
-
-#
-# -- [[ HTTP Argument/Upload Limits ]] -----------------------------------------
-#
-# Here you can define optional limits on HTTP get/post parameters and uploads.
-# This can help to prevent application specific DoS attacks.
-#
-# These values are checked in REQUEST-920-PROTOCOL-ENFORCEMENT.conf.
-# Beware of blocking legitimate traffic when enabling these limits.
-#
-
-# Block request if number of arguments is too high
-# Default: unlimited
-# Example: 255
-# Uncomment this rule to set a limit.
-SecAction \
- "id:900300,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.max_num_args=10"
-
-# Block request if the length of any argument name is too high
-# Default: unlimited
-# Example: 100
-# Uncomment this rule to set a limit.
-SecAction \
- "id:900310,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.arg_name_length=100"
-
-# Block request if the length of any argument value is too high
-# Default: unlimited
-# Example: 400
-# Uncomment this rule to set a limit.
-SecAction \
- "id:900320,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.arg_length=400"
-
-# Block request if the total length of all combined arguments is too high
-# Default: unlimited
-# Example: 64000
-# Uncomment this rule to set a limit.
-SecAction \
- "id:900330,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.total_arg_length=6400"
-
-# Block request if the file size of any individual uploaded file is too high
-# Default: unlimited
-# Example: 1048576
-# Uncomment this rule to set a limit.
-#SecAction \
-# "id:900340,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.max_file_size=1048576"
-
-# Block request if the total size of all combined uploaded files is too high
-# Default: unlimited
-# Example: 1048576
-# Uncomment this rule to set a limit.
-#SecAction \
-# "id:900350,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.combined_file_sizes=1048576"
-
-
-#
-# -- [[ Easing In / Sampling Percentage ]] -------------------------------------
-#
-# Adding the Core Rule Set to an existing productive site can lead to false
-# positives, unexpected performance issues and other undesired side effects.
-#
-# It can be beneficial to test the water first by enabling the CRS for a
-# limited number of requests only and then, when you have solved the issues (if
-# any) and you have confidence in the setup, to raise the ratio of requests
-# being sent into the ruleset.
-#
-# Adjust the percentage of requests that are funnelled into the Core Rules by
-# setting TX.sampling_percentage below. The default is 100, meaning that every
-# request gets checked by the CRS.  The selection of requests, which are going
-# to be checked, is based on a pseudo random number generated by ModSecurity.
-#
-# If a request is allowed to pass without being checked by the CRS, there is no
-# entry in the audit log (for performance reasons), but an error log entry is
-# written.  If you want to disable the error log entry, then issue the
-# following directive somewhere after the inclusion of the CRS
-# (E.g., RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf).
-#
-# SecRuleUpdateActionById 901150 "nolog"
-#
-# ATTENTION: If this TX.sampling_percentage is below 100, then some of the
-# requests will bypass the Core Rules completely and you lose the ability to
-# protect your service with ModSecurity.
-#
-# Uncomment this rule to enable this feature:
-#
-#SecAction "id:900400,\
-#  phase:1,\
-#  pass,\
-#  nolog,\
-#  setvar:tx.sampling_percentage=100"
-
-
-#
-# -- [[ Project Honey Pot HTTP Blacklist ]] ------------------------------------
-#
-# Optionally, you can check the client IP address against the Project Honey Pot
-# HTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a
-# free API key. Set it here with SecHttpBlKey.
-#
-# Project Honeypot returns multiple different malicious IP types.
-# You may specify which you want to block by enabling or disabling them below.
-#
-# Ref: https://www.projecthoneypot.org/httpbl.php
-# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey
-#
-# Uncomment these rules to use this feature:
-#
-#SecHttpBlKey XXXXXXXXXXXXXXXXX
-#SecAction "id:900500,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.block_search_ip=1,\
-#  setvar:tx.block_suspicious_ip=1,\
-#  setvar:tx.block_harvester_ip=1,\
-#  setvar:tx.block_spammer_ip=1"
-
-
-#
-# -- [[ GeoIP Database ]] ------------------------------------------------------
-#
-# There are some rulesets that inspect geolocation data of the client IP address
-# (geoLookup). The CRS uses geoLookup to implement optional country blocking.
-#
-# To use geolocation, we make use of the MaxMind GeoIP database.
-# This database is not included with the CRS and must be downloaded.
-#
-# There are two formats for the GeoIP database. ModSecurity v2 uses GeoLite (.dat files),
-# and ModSecurity v3 uses GeoLite2 (.mmdb files).
-#
-# If you use ModSecurity 3, MaxMind provides a binary for updating GeoLite2 files,
-# see https://github.com/maxmind/geoipupdate.
-#
-# Download the package for your OS, and read https://dev.maxmind.com/geoip/geoipupdate/
-# for configuration options.
-#
-# Warning: GeoLite (not GeoLite2) databases are considered legacy, and not being updated anymore.
-# See https://support.maxmind.com/geolite-legacy-discontinuation-notice/ for more info.
-#
-# Therefore, if you use ModSecurity v2, you need to regenerate updated .dat files
-# from CSV files first.
-#
-# You can achieve this using https://github.com/sherpya/geolite2legacy
-# Pick the zip files from maxmind site:
-# https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip
-#
-# Follow the guidelines for installing the tool and run:
-# ./geolite2legacy.py -i GeoLite2-Country-CSV.zip \
-#                     -f geoname2fips.csv -o /usr/share/GeoliteCountry.dat
-#
-# Update the database regularly, see Step 3 of the configuration link above.
-#
-# By default, when you execute `sudo geoipupdate` on Linux, files from the free database
-# will be downloaded to `/usr/share/GeoIP` (both v1 and v2).
-#
-# Then choose from:
-#   - `GeoLite2-Country.mmdb` (if you are using ModSecurity v3)
-#   - `GeoLiteCountry.dat`    (if you are using ModSecurity v2)
-#
-# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html
-# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html
-#
-# Uncomment only one of the next rules here to use this feature.
-# Choose the one depending on the ModSecurity version you are using, and change the path accordingly:
-#
-# For ModSecurity v3:
-#SecGeoLookupDB /usr/share/GeoIP/GeoLite2-Country.mmdb
-# For ModSecurity v2 (points to the converted one):
-#SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat
-
-#
-# -=[ Block Countries ]=-
-#
-# Rules in the IP Reputation file can check the client against a list of high
-# risk country codes. These countries have to be defined in the variable
-# tx.high_risk_country_codes via their ISO 3166 two-letter country code:
-# https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
-#
-# If you are sure that you are not getting any legitimate requests from a given
-# country, then you can disable all access from that country via this variable.
-# The rule performing the test has the rule id 910100.
-#
-# This rule requires SecGeoLookupDB to be enabled and the GeoIP database to be
-# downloaded (see the section "GeoIP Database" above.)
-#
-# By default, the list is empty. A list used by some sites was the following:
-# setvar:'tx.high_risk_country_codes=UA ID YU LT EG RO BG TR RU PK MY CN'"
-#
-# Uncomment this rule to use this feature:
-#
-#SecAction \
-# "id:900600,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:'tx.high_risk_country_codes='"
-
-
-#
-# -- [[ Anti-Automation / DoS Protection ]] ------------------------------------
-#
-# Optional DoS protection against clients making requests too quickly.
-#
-# When a client is making more than 100 requests (excluding static files) within
-# 60 seconds, this is considered a 'burst'. After two bursts, the client is
-# blocked for 600 seconds.
-#
-# Requests to static files are not counted towards DoS; they are listed in the
-# 'tx.static_extensions' setting, which you can change in this file (see
-# section "HTTP Policy Settings").
-#
-# For a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf.
-#
-# Uncomment this rule to use this feature:
-#
-SecAction \
- "id:900700,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:'tx.dos_burst_time_slice=60',\
-  setvar:'tx.dos_counter_threshold=100',\
-  setvar:'tx.dos_block_timeout=600'"
-
-
-#
-# -- [[ Check UTF-8 encoding ]] ------------------------------------------------
-#
-# The CRS can optionally check request contents for invalid UTF-8 encoding.
-# We only want to apply this check if UTF-8 encoding is actually used by the
-# site; otherwise it will result in false positives.
-#
-# Uncomment this rule to use this feature:
-#
-SecAction \
- "id:900950,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.crs_validate_utf8_encoding=1"
-
-
-#
-# -- [[ Blocking Based on IP Reputation ]] ------------------------------------
-#
-# Blocking based on reputation is permanent in the CRS. Unlike other rules,
-# which look at the individual request, the blocking of IPs is based on
-# a persistent record in the IP collection, which remains active for a
-# certain amount of time.
-#
-# There are two ways an individual client can become flagged for blocking:
-# - External information (RBL, GeoIP, etc.)
-# - Internal information (Core Rules)
-#
-# The record in the IP collection carries a flag, which tags requests from
-# individual clients with a flag named IP.reput_block_flag.
-# But the flag alone is not enough to have a client blocked. There is also
-# a global switch named tx.do_reput_block. This is off by default. If you set
-# it to 1 (=On), requests from clients with the IP.reput_block_flag will
-# be blocked for a certain duration.
-#
-# Variables
-# ip.reput_block_flag      Blocking flag for the IP collection record
-# ip.reput_block_reason    Reason (= rule message) that caused to blocking flag
-# tx.do_reput_block        Switch deciding if we really block based on flag
-# tx.reput_block_duration  Setting to define the duration of a block
-#
-# It may be important to know, that all the other core rules are skipped for
-# requests, when it is clear that they carry the blocking flag in question.
-#
-# Uncomment this rule to use this feature:
-#
-#SecAction \
-# "id:900960,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.do_reput_block=1"
-#
-# Uncomment this rule to change the blocking time:
-# Default: 300 (5 minutes)
-#
-#SecAction \
-# "id:900970,\
-#  phase:1,\
-#  nolog,\
-#  pass,\
-#  t:none,\
-#  setvar:tx.reput_block_duration=300"
-
-
-#
-# -- [[ Collection timeout ]] --------------------------------------------------
-#
-# Set the SecCollectionTimeout directive from the ModSecurity default (1 hour)
-# to a lower setting which is appropriate to most sites.
-# This increases performance by cleaning out stale collection (block) entries.
-#
-# This value should be greater than or equal to:
-# tx.reput_block_duration (see section "Blocking Based on IP Reputation") and
-# tx.dos_block_timeout (see section "Anti-Automation / DoS Protection").
-#
-# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecCollectionTimeout
-
-# Please keep this directive uncommented.
-# Default: 600 (10 minutes)
-SecCollectionTimeout 600
-
-
-#
-# -- [[ End of setup ]] --------------------------------------------------------
-#
-# The CRS checks the tx.crs_setup_version variable to ensure that the setup
-# has been loaded. If you are not planning to use this setup template,
-# you must manually set the tx.crs_setup_version variable before including
-# the CRS rules/* files.
-#
-# The variable is a numerical representation of the CRS version number.
-# E.g., v3.0.0 is represented as 300.
-#
-SecAction \
- "id:900990,\
-  phase:1,\
-  nolog,\
-  pass,\
-  t:none,\
-  setvar:tx.crs_setup_version=330"
diff --git a/oss/etc/nginx/conf.d/gateway/server_variables.conf b/oss/etc/nginx/conf.d/gateway/server_variables.conf
deleted file mode 100644
index cf0077e..0000000
--- a/oss/etc/nginx/conf.d/gateway/server_variables.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# Variable indicating to the awssig4.js script that singing key
-# caching is turned off. This feature uses the keyval store, so it
-# is only enabled when using NGINX Plus.
-set $cache_signing_key_enabled 0;
-
-# Variable indicating to the awscredentials.js script that session token
-# caching is turned on. This feature uses the keyval store, so it
-# is only enabled when using NGINX Plus.
-set $cache_instance_credentials_enabled 0;
diff --git a/oss/etc/nginx/templates/upstreams.conf.template b/oss/etc/nginx/templates/upstreams.conf.template
deleted file mode 100644
index aecdb9a..0000000
--- a/oss/etc/nginx/templates/upstreams.conf.template
+++ /dev/null
@@ -1,21 +0,0 @@
-# Use NGINX's non-blocking DNS resolution
-resolver ${DNS_RESOLVERS};
-
-upstream storage_urls {
-    # Upstreams are not refreshed until NGINX configuration is reloaded.
-    # NGINX Plus will dynamically reload upstreams when DNS records are changed.
-
-    # Be sure to specify the port in the S3_SERVER and be sure that port
-    # corresponds to the https/http in the proxy_pass directive.
-    server ${S3_SERVER}:${S3_SERVER_PORT};
-}
-
-upstream lambda_urls {
-    # Upstreams are not refreshed until NGINX configuration is reloaded.
-    # NGINX Plus will dynamically reload upstreams when DNS records are changed.
-
-    # Be sure to specify the port in the LAMBDA_SERVER and be sure that port
-    # corresponds to the https/http in the proxy_pass directive.
-    server ${LAMBDA_SERVER}:${LAMBDA_SERVER_PORT};
-    #server localhost:8080;
-}
diff --git a/plus/docker-entrypoint.d/10-listen-on-ipv6-by-default.sh b/plus/docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
deleted file mode 100644
index 70f4da0..0000000
--- a/plus/docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-# vim:sw=4:ts=4:et
-
-set -e
-
-ME=$(basename $0)
-DEFAULT_CONF_FILE="etc/nginx/conf.d/default.conf"
-
-# check if we have ipv6 available
-if [ ! -f "/proc/net/if_inet6" ]; then
-    echo >&3 "$ME: error: ipv6 not available"
-    exit 0
-fi
-
-if [ ! -f "/$DEFAULT_CONF_FILE" ]; then
-    echo >&3 "$ME: error: /$DEFAULT_CONF_FILE is not a file or does not exist"
-    exit 0
-fi
-
-# check if the file can be modified, e.g. not on a r/o filesystem
-touch /$DEFAULT_CONF_FILE 2>/dev/null || { echo >&3 "$ME: error: can not modify /$DEFAULT_CONF_FILE (read-only file system?)"; exit 0; }
-
-# check if the file is already modified, e.g. on a container restart
-grep -q "listen  \[::]\:80;" /$DEFAULT_CONF_FILE && { echo >&3 "$ME: error: IPv6 listen already enabled"; exit 0; }
-
-if [ -f "/etc/os-release" ]; then
-    . /etc/os-release
-else
-    echo >&3 "$ME: error: can not guess the operating system"
-    exit 0
-fi
-
-echo >&3 "$ME: Getting the checksum of /$DEFAULT_CONF_FILE"
-
-case "$ID" in
-    "debian")
-        CHECKSUM=$(dpkg-query --show --showformat='${Conffiles}\n' nginx | grep $DEFAULT_CONF_FILE | cut -d' ' -f 3)
-        echo "$CHECKSUM  /$DEFAULT_CONF_FILE" | md5sum -c - >/dev/null 2>&1 || {
-            echo >&3 "$ME: error: /$DEFAULT_CONF_FILE differs from the packaged version"
-            exit 0
-        }
-        ;;
-    "alpine")
-        CHECKSUM=$(apk manifest nginx 2>/dev/null| grep $DEFAULT_CONF_FILE | cut -d' ' -f 1 | cut -d ':' -f 2)
-        echo "$CHECKSUM  /$DEFAULT_CONF_FILE" | sha1sum -c - >/dev/null 2>&1 || {
-            echo >&3 "$ME: error: /$DEFAULT_CONF_FILE differs from the packages version"
-            exit 0
-        }
-        ;;
-    *)
-        echo >&3 "$ME: error: Unsupported distribution"
-        exit 0
-        ;;
-esac
-
-# enable ipv6 on default.conf listen sockets
-sed -i -E 's,listen       80;,listen       80;\n    listen  [::]:80;,' /$DEFAULT_CONF_FILE
-
-echo >&3 "$ME: Enabled listen on IPv6 in /$DEFAULT_CONF_FILE"
-
-exit 0
diff --git a/plus/docker-entrypoint.d/20-envsubst-on-templates.sh b/plus/docker-entrypoint.d/20-envsubst-on-templates.sh
deleted file mode 100644
index c57faed..0000000
--- a/plus/docker-entrypoint.d/20-envsubst-on-templates.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/sh
-
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-set -e
-
-ME=$(basename $0)
-
-auto_envsubst() {
-  local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}"
-  local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}"
-  local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}"
-
-  local template defined_envs relative_path output_path subdir
-  defined_envs=$(printf '${%s} ' $(env | cut -d= -f1))
-  [ -d "$template_dir" ] || return 0
-  if [ ! -w "$output_dir" ]; then
-    echo >&3 "$ME: ERROR: $template_dir exists, but $output_dir is not writable"
-    return 0
-  fi
-  find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do
-    relative_path="${template#$template_dir/}"
-    output_path="$output_dir/${relative_path%$suffix}"
-    subdir=$(dirname "$relative_path")
-    # create a subdirectory where the template file exists
-    mkdir -p "$output_dir/$subdir"
-    echo >&3 "$ME: Running envsubst on $template to $output_path"
-    envsubst "$defined_envs" < "$template" > "$output_path"
-  done
-}
-
-auto_envsubst
-
-exit 0
diff --git a/plus/etc/nginx/conf.d/gateway/server_variables.conf b/plus/etc/nginx/conf.d/gateway/server_variables.conf
deleted file mode 100644
index 851f0a9..0000000
--- a/plus/etc/nginx/conf.d/gateway/server_variables.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# Variable indicating to the lambdagateway.js script that singing key
-# caching is turned on. This feature uses the keyval store, so it
-# is only enabled when using NGINX Plus.
-set $cache_signing_key_enabled 1;
-
-# Variable indicating to the lambdagateway.js script that session token
-# caching is turned on. This feature uses the keyval store, so it
-# is only enabled when using NGINX Plus.
-set $cache_instance_credentials_enabled 1;
diff --git a/plus/etc/nginx/conf.d/instance_credential_cache.conf b/plus/etc/nginx/conf.d/instance_credential_cache.conf
deleted file mode 100644
index b2e030e..0000000
--- a/plus/etc/nginx/conf.d/instance_credential_cache.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-# This key value zone allows us to cache a portion of the cryptographic
-# signatures used by AWS v4 signatures.
-keyval_zone zone=instance_credential_cache:32k type=string timeout=6h;
-keyval 'instance_credential' $instance_credential_json zone=instance_credential_cache;
diff --git a/plus/etc/nginx/conf.d/v4_signing_key_cache.conf b/plus/etc/nginx/conf.d/v4_signing_key_cache.conf
deleted file mode 100644
index b18aab4..0000000
--- a/plus/etc/nginx/conf.d/v4_signing_key_cache.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-# This key value zone allows us to cache a portion of the cryptographic
-# signatures used by AWS v4 signatures.
-keyval_zone zone=aws_signing_cache:32k type=string timeout=24h;
-keyval 'aws_signing_key_hash' $signing_key_hash zone=aws_signing_cache;
diff --git a/plus/etc/nginx/templates/upstreams.conf.template b/plus/etc/nginx/templates/upstreams.conf.template
deleted file mode 100644
index 9ca1176..0000000
--- a/plus/etc/nginx/templates/upstreams.conf.template
+++ /dev/null
@@ -1,21 +0,0 @@
-# This configuration with NGINX Plus should dynamically reload S3 backends
-# as they change in DNS.
-
-# Use NGINX's non-blocking DNS resolution
-resolver ${DNS_RESOLVERS};
-
-upstream storage_urls {
-    zone s3_backends 64k;
-
-    # Be sure to specify the port in the S3_SERVER and be sure that port
-    # corresponds to the https/http in the proxy_pass directive.
-    server ${S3_SERVER}:${S3_SERVER_PORT} resolve;
-}
-
-upstream lambda_urls {
-    zone lambda_backends 256k;
-
-    # Be sure to specify the port in the LAMBDA_SERVER and be sure that port
-    # corresponds to the https/http in the proxy_pass directive.
-    server ${LAMBDA_SERVER}:${LAMBDA_SERVER_PORT} resolve;
-}
diff --git a/plus/etc/ssl/nginx/.gitignore b/plus/etc/ssl/nginx/.gitignore
deleted file mode 100644
index 1855abc..0000000
--- a/plus/etc/ssl/nginx/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-nginx-repo.crt
-nginx-repo.key
diff --git a/plus/usr/local/bin/add_nginx_plus_repo.sh b/plus/usr/local/bin/add_nginx_plus_repo.sh
deleted file mode 100644
index 6b24bd5..0000000
--- a/plus/usr/local/bin/add_nginx_plus_repo.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env sh
-
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-if [ ! -f "/etc/ssl/nginx/nginx-repo.crt" ]; then
-  >&2 echo "NGINX Plus repository certificate file not found at path: /etc/ssl/nginx/nginx-repo.crt"
-  exit 1
-fi
-
-if [ ! -f "/etc/ssl/nginx/nginx-repo.key" ]; then
-  >&2 echo "NGINX Plus repository key file not found at path: /etc/ssl/nginx/nginx-repo.key"
-  exit 1
-fi
-
-version_codename="$(grep '^VERSION_CODENAME=' /etc/os-release | awk -v FS='=' '{print $2}')"
-
-echo "Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";" >> /etc/apt/apt.conf.d/90nginx
-echo "Acquire::https::pkgs.nginx.com::Verify-Host \"true\";" >> /etc/apt/apt.conf.d/90nginx
-echo "Acquire::https::pkgs.nginx.com::SslCert     \"/etc/ssl/nginx/nginx-repo.crt\";" >> /etc/apt/apt.conf.d/90nginx
-echo "Acquire::https::pkgs.nginx.com::SslKey      \"/etc/ssl/nginx/nginx-repo.key\";" >> /etc/apt/apt.conf.d/90nginx
-echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://pkgs.nginx.com/plus/debian ${version_codename} nginx-plus" >> /etc/apt/sources.list.d/nginx-plus.list
diff --git a/plus/usr/share/keyrings/.gitattributes b/plus/usr/share/keyrings/.gitattributes
deleted file mode 100644
index b69c02c..0000000
--- a/plus/usr/share/keyrings/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-*.gpg binary
diff --git a/plus/usr/share/keyrings/nginx-archive-keyring.gpg b/plus/usr/share/keyrings/nginx-archive-keyring.gpg
deleted file mode 100644
index 82b5bff..0000000
Binary files a/plus/usr/share/keyrings/nginx-archive-keyring.gpg and /dev/null differ
diff --git a/settings.env b/settings.env
new file mode 100644
index 0000000..eb8343e
--- /dev/null
+++ b/settings.env
@@ -0,0 +1,9 @@
+AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
+AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
+AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
+DEBUG=false
+HEADER_PREFIXES_TO_STRIP=false
+LAMBDA_REGION=${AWS_REGION}
+LAMBDA_SERVER_PROTO=https
+LAMBDA_SERVER=lambda.${AWS_REGION}.amazonaws.com
+LAMBDA_SERVER_PORT=443
diff --git a/settings.example b/settings.example
deleted file mode 100644
index 4cefe71..0000000
--- a/settings.example
+++ /dev/null
@@ -1,17 +0,0 @@
-S3_BUCKET_NAME=my-bucket
-AWS_ACCESS_KEY_ID=ZZZZZZZZZZZZZZZZZZZZ
-AWS_SECRET_ACCESS_KEY=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-AWS_SESSION_TOKEN=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-S3_SERVER=s3-us-east-1.amazonaws.com
-S3_SERVER_PORT=443
-S3_SERVER_PROTO=https
-S3_REGION=us-east-1
-S3_STYLE=virtual
-S3_DEBUG=false
-AWS_SIGS_VERSION=4
-ALLOW_DIRECTORY_LIST=false
-PROVIDE_INDEX_PAGE=false
-APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=false
-PROXY_CACHE_VALID_OK=1h
-PROXY_CACHE_VALID_NOTFOUND=1m
-PROXY_CACHE_VALID_FORBIDDEN=30s
diff --git a/standalone_ubuntu_oss_install.sh b/standalone_ubuntu_oss_install.sh
deleted file mode 100644
index 3cccfb3..0000000
--- a/standalone_ubuntu_oss_install.sh
+++ /dev/null
@@ -1,376 +0,0 @@
-#!/usr/bin/env bash
-
-set -o errexit   # abort on nonzero exit status
-set -o pipefail  # don't hide errors within pipes
-
-if [ "$EUID" -ne 0 ];then
-  >&2 echo "This script requires root level access to run"
-  exit 1
-fi
-
-if ! dpkg --status grep 2>/dev/null | grep --quiet Status > /dev/null; then
-  >&2 echo "This script requires the grep package to be installed in order to run"
-  exit 1
-fi
-
-if ! dpkg --status coreutils 2>/dev/null | grep --quiet Status > /dev/null; then
-  >&2 echo "This script requires the coreutils package to be installed in order to run"
-  exit 1
-fi
-
-if ! dpkg --status apt 2>/dev/null | grep --quiet Status > /dev/null; then
-  >&2 echo "This script requires the apt package to be installed in order to run"
-  exit 1
-fi
-
-if ! dpkg --status wget 2>/dev/null | grep --quiet Status > /dev/null; then
-  >&2 echo "This script requires the wget package to be installed in order to run"
-  exit 1
-fi
-
-failed=0
-
-required=("S3_BUCKET_NAME" "S3_SERVER" "S3_SERVER_PORT" "S3_SERVER_PROTO"
-"S3_REGION" "S3_STYLE" "ALLOW_DIRECTORY_LIST" "AWS_SIGS_VERSION")
-
-if [ ! -z ${AWS_CONTAINER_CREDENTIALS_RELATIVE_URI+x} ]; then
-  echo "Running inside an ECS task, using container credentials"
-  uses_iam_creds=1
-elif curl --output /dev/null --silent --head --fail --connect-timeout 2 "http://169.254.169.254"; then
-  echo "Running inside an EC2 instance, using IMDS for credentials"
-  uses_iam_creds=1
-else
-  required+=("AWS_ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY")
-  uses_iam_creds=0
-fi
-
-if [[ -v AWS_SESSION_TOKEN ]]; then
-  echo "S3 Session token present"
-fi
-
-for name in ${required[@]}; do
-  if [ -z ${!name+x} ]; then
-      >&2 echo "Required ${name} environment variable missing"
-      failed=1
-  fi
-done
-
-if [ "${S3_SERVER_PROTO}" != "http" ] && [ "${S3_SERVER_PROTO}" != "https" ]; then
-    >&2 echo "S3_SERVER_PROTO contains an invalid value (${S3_SERVER_PROTO}). Valid values: http, https"
-    failed=1
-fi
-
-if [ "${AWS_SIGS_VERSION}" != "2" ] && [ "${AWS_SIGS_VERSION}" != "4" ]; then
-  >&2 echo "AWS_SIGS_VERSION contains an invalid value (${AWS_SIGS_VERSION}). Valid values: 2, 4"
-  failed=1
-fi
-
-if [ $failed -gt 0 ]; then
-  exit 1
-fi
-
-if [ "${1}" == "" ]; then
-  branch="master"
-else
-  branch="${1}"
-fi
-echo "Installing using github '${branch}' branch"
-
-
-echo "S3 Backend Environment"
-echo "Access Key ID: ${AWS_ACCESS_KEY_ID}"
-echo "Origin: ${S3_SERVER_PROTO}://${S3_BUCKET_NAME}.${S3_SERVER}:${S3_SERVER_PORT}"
-echo "Region: ${S3_REGION}"
-echo "Addressing Style: ${S3_STYLE}"
-echo "AWS Signatures Version: v${AWS_SIGS_VERSION}"
-echo "DNS Resolvers: ${DNS_RESOLVERS}"
-echo "Directory Listing Enabled: ${ALLOW_DIRECTORY_LIST}"
-echo "Proxy Caching Time for Valid Response: ${PROXY_CACHE_VALID_OK}"
-echo "Proxy Caching Time for Not Found Response: ${PROXY_CACHE_VALID_NOTFOUND}"
-echo "Proxy Caching Time for Forbidden Response: ${PROXY_CACHE_VALID_FORBIDDEN}"
-echo "CORS Enabled: ${CORS_ENABLED}"
-
-set -o nounset   # abort on unbound variable
-
-if [ ! -f /etc/apt/sources.list.d/nginx.list ]; then
-  release="$(grep 'VERSION_CODENAME' /etc/os-release | cut --delimiter='=' --field=2)"
-  echo "▶ Adding NGINX package repository"
-
-  cat > "/etc/apt/sources.list.d/nginx.list" << EOF
-deb https://nginx.org/packages/ubuntu/ $release nginx
-deb-src https://nginx.org/packages/ubuntu/ $release nginx
-EOF
-
-  key="ABF5BD827BD9BF62"
-  apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $key
-  apt-get -qq update
-fi
-
-to_install=""
-
-if ! dpkg --status nginx 2>/dev/null | grep --quiet Status > /dev/null; then
-  to_install="nginx"
-fi
-
-if ! dpkg --status nginx-module-njs 2>/dev/null | grep --quiet Status > /dev/null; then
-  # find latest njs version because the package manager gets this wrong
-  latest_njs_version="$(apt show -a nginx-module-njs 2>/dev/null | grep 'Version:' | cut --delimiter=' ' --field=2 | sort --reverse | head --lines=1)"
-  to_install="${to_install} nginx-module-njs=${latest_njs_version}"
-fi
-
-if ! dpkg --status nginx-module-xslt 2>/dev/null | grep --quiet Status > /dev/null; then
-  to_install="${to_install} nginx-module-xslt"
-fi
-
-
-if [ "${to_install}" != "" ]; then
-  apt-get -qq install --yes ${to_install}
-  echo "▶ Stopping nginx so that it can be configured as a S3 Gateway"
-  systemctl stop nginx
-fi
-
-echo "▶ Adding environment variables to NGINX configuration file: /etc/nginx/environment"
-cat > "/etc/nginx/environment" << EOF
-# Enables or disables directory listing for the S3 Gateway (true=enabled, false=disabled)
-ALLOW_DIRECTORY_LIST=${ALLOW_DIRECTORY_LIST}
-# AWS Authentication signature version (2=v2 authentication, 4=v4 authentication)
-AWS_SIGS_VERSION=${AWS_SIGS_VERSION}
-# Name of S3 bucket to proxy requests to
-S3_BUCKET_NAME=${S3_BUCKET_NAME}
-# Region associated with API
-S3_REGION=${S3_REGION}
-# SSL/TLS port to connect to
-S3_SERVER_PORT=${S3_SERVER_PORT}
-# Protocol to used connect to S3 server - 'http' or 'https'
-S3_SERVER_PROTO=${S3_SERVER_PROTO}
-# S3 host to connect to
-S3_SERVER=${S3_SERVER}
-# The S3 host/path method - 'virtual', 'path' or 'default'
-S3_STYLE=${S3_STYLE}
-# Flag (true/false) enabling AWS signatures debug output (default: false)
-S3_DEBUG=${S3_DEBUG}
-# Proxy caching time for response code 200 and 302
-PROXY_CACHE_VALID_OK=${PROXY_CACHE_VALID_OK}
-# Proxy caching time for response code 404
-PROXY_CACHE_VALID_NOTFOUND=${PROXY_CACHE_VALID_NOTFOUND}
-# Proxy caching time for response code 403
-PROXY_CACHE_VALID_FORBIDDEN=${PROXY_CACHE_VALID_FORBIDDEN}
-# Enables or disables CORS for the S3 Gateway (true=enabled, false=disabled)
-CORS_ENABLED=${CORS_ENABLED}
-EOF
-
-# By enabling CORS, we also need to enable the OPTIONS method which
-# is not normally used as part of the gateway. The following variable
-# defines the set of acceptable headers.
-if [ "${CORS_ENABLED}" == "1" ]; then
-    cat >> "/etc/nginx/environment" << EOF
-LIMIT_METHODS_TO="GET HEAD OPTIONS"
-LIMIT_METHODS_TO_CSV="GET, HEAD, OPTIONS"
-EOF
-else
-    cat >> "/etc/nginx/environment" << EOF
-LIMIT_METHODS_TO="GET HEAD"
-LIMIT_METHODS_TO_CSV="GET, HEAD"
-EOF
-fi
-
-if [ -z "${CORS_ALLOWED_ORIGIN+x}" ]; then
-CORS_ALLOWED_ORIGIN="*"
-fi
-
-cat >> "/etc/nginx/environment" << EOF
-CORS_ALLOWED_ORIGIN=${CORS_ALLOWED_ORIGIN}
-EOF
-
-# Only include these env vars if we are not using a instance profile credential
-# to obtain S3 permissions.
-if [ $uses_iam_creds -eq 0 ]; then
-  cat >> "/etc/nginx/environment" << EOF
-# AWS Access key
-AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
-# AWS Secret access key
-AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
-EOF
-  if [[ -v AWS_SESSION_TOKEN ]]; then
-    cat >> "/etc/nginx/environment" << EOF
-# AWS Session Token
-AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
-EOF
-  fi
-fi
-
-set +o nounset   # don't abort on unbound variable
-if [ -z ${DNS_RESOLVERS+x} ]; then
-  cat >> "/etc/default/nginx" << EOF
-# DNS resolvers (separated by single spaces) to configure NGINX with
-DNS_RESOLVERS=${DNS_RESOLVERS}
-EOF
-fi
-set -o nounset   # abort on unbound variable
-
-# Make sure that only the root user can access the environment variables file
-chown root:root /etc/nginx/environment
-chmod og-rwx /etc/nginx/environment
-
-cat > /usr/local/bin/template_nginx_config.sh << 'EOF'
-#!/usr/bin/env bash
-
-ME=$(basename $0)
-
-auto_envsubst() {
-  local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}"
-  local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}"
-  local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}"
-
-  local template defined_envs relative_path output_path subdir
-  defined_envs=$(printf '${%s} ' $(env | cut -d= -f1))
-  [ -d "$template_dir" ] || return 0
-  if [ ! -w "$output_dir" ]; then
-    echo "$ME: ERROR: $template_dir exists, but $output_dir is not writable"
-    return 0
-  fi
-  find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do
-    relative_path="${template#$template_dir/}"
-    output_path="$output_dir/${relative_path%$suffix}"
-    subdir=$(dirname "$relative_path")
-    # create a subdirectory where the template file exists
-    mkdir -p "$output_dir/$subdir"
-    echo "$ME: Running envsubst on $template to $output_path"
-    envsubst "$defined_envs" < "$template" > "$output_path"
-  done
-}
-
-# Attempt to read DNS Resolvers from /etc/resolv.conf
-if [ -z ${DNS_RESOLVERS+x} ]; then
-  export DNS_RESOLVERS="$(cat /etc/resolv.conf | grep nameserver | cut -d' ' -f2 | xargs)"
-fi
-
-auto_envsubst
-EOF
-chmod +x /usr/local/bin/template_nginx_config.sh
-
-echo "▶ Reconfiguring systemd for S3 Gateway"
-mkdir -p /etc/systemd/system/nginx.service.d
-cat > /etc/systemd/system/nginx.service.d/override.conf << 'EOF'
-[Service]
-EnvironmentFile=/etc/nginx/environment
-ExecStartPre=/usr/local/bin/template_nginx_config.sh
-EOF
-systemctl daemon-reload
-
-echo "▶ Creating NGINX configuration for S3 Gateway"
-mkdir -p /etc/nginx/include
-mkdir -p /etc/nginx/conf.d/gateway
-mkdir -p /etc/nginx/templates/gateway
-
-function download() {
-  wget --quiet --output-document="$2" "https://raw.githubusercontent.com/nginx-serverless/nginx-s3-gateway-v1/${branch}/$1"
-}
-
-if [ ! -f /etc/nginx/nginx.conf.orig ]; then
-  mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
-fi
-
-if [ ! -f /etc/nginx/conf.d/default.conf.orig ]; then
-  mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.orig
-fi
-
-cat > /etc/nginx/nginx.conf << 'EOF'
-user  nginx;
-worker_processes  auto;
-
-error_log  /var/log/nginx/error.log notice;
-pid        /var/run/nginx.pid;
-
-# NJS module used for implementing S3 authentication
-load_module modules/ngx_http_js_module.so;
-load_module modules/ngx_http_xslt_filter_module.so;
-
-# Preserve S3 environment variables for worker threads
-EOF
-
-# Only include these env vars if we are not using a instance profile credential
-# to obtain S3 permissions.
-if [ $uses_iam_creds -eq 0 ]; then
-  cat >> "/etc/nginx/environment" << EOF
-env AWS_ACCESS_KEY_ID;
-env AWS_SECRET_ACCESS_KEY;
-EOF
-  if [[ -v AWS_SESSION_TOKEN ]]; then
-    cat >> "/etc/nginx/environment" << EOF
-env AWS_SESSION_TOKEN;
-EOF
-  fi
-fi
-
-cat >> /etc/nginx/nginx.conf << 'EOF'
-env S3_BUCKET_NAME;
-env S3_SERVER;
-env S3_SERVER_PORT;
-env S3_SERVER_PROTO;
-env S3_REGION;
-env AWS_SIGS_VERSION;
-env S3_DEBUG;
-env S3_STYLE;
-env ALLOW_DIRECTORY_LIST;
-
-events {
-    worker_connections  1024;
-}
-
-
-http {
-    include       /etc/nginx/mime.types;
-    default_type  application/octet-stream;
-
-    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
-                      '$status $body_bytes_sent "$http_referer" '
-                      '"$http_user_agent" "$http_x_forwarded_for"';
-
-    access_log  /var/log/nginx/access.log  main;
-
-    sendfile        on;
-    #tcp_nopush     on;
-
-    keepalive_timeout  65;
-
-    #gzip  on;
-
-    # Settings for S3 cache
-    proxy_cache_path /var/cache/nginx/s3_proxy
-    levels=1:2
-    keys_zone=s3_cache:10m
-    max_size=10g
-    inactive=60m
-    use_temp_path=off;
-
-    include /etc/nginx/conf.d/*.conf;
-}
-EOF
-
-download "common/etc/nginx/include/listing.xsl" "/etc/nginx/include/listing.xsl"
-download "common/etc/nginx/include/awscredentials.js" "/etc/nginx/include/awscredentials.js"
-download "common/etc/nginx/include/awssig2.js" "/etc/nginx/include/awssig2.js"
-download "common/etc/nginx/include/awssig4.js" "/etc/nginx/include/awssig4.js"
-download "common/etc/nginx/include/lambdagateway.js" "/etc/nginx/include/lambdagateway.js"
-download "common/etc/nginx/include/s3gateway.js" "/etc/nginx/include/s3gateway.js"
-download "common/etc/nginx/include/utils.js" "/etc/nginx/include/utils.js"
-download "common/etc/nginx/templates/default.conf.template" "/etc/nginx/templates/default.conf.template"
-download "common/etc/nginx/templates/gateway/v2_headers.conf.template" "/etc/nginx/templates/gateway/v2_headers.conf.template"
-download "common/etc/nginx/templates/gateway/v2_js_vars.conf.template" "/etc/nginx/templates/gateway/v2_js_vars.conf.template"
-download "common/etc/nginx/templates/gateway/v4_headers.conf.template" "/etc/nginx/templates/gateway/v4_headers.conf.template"
-download "common/etc/nginx/templates/gateway/v4_js_vars.conf.template" "/etc/nginx/templates/gateway/v4_js_vars.conf.template"
-download "common/etc/nginx/templates/gateway/cors.conf.template" "/etc/nginx/templates/gateway/cors.conf.template"
-download "common/etc/nginx/templates/gateway/js_fetch_trusted_certificate.conf.template" "/etc/nginx/templates/gateway/js_fetch_trusted_certificate.conf.template"
-download "common/etc/nginx/templates/gateway/s3listing_location.conf.template" "/etc/nginx/templates/gateway/s3listing_location.conf.template"
-download "common/etc/nginx/templates/gateway/s3_location.conf.template" "/etc/nginx/templates/gateway/s3_location.conf.template"
-download "common/etc/nginx/templates/gateway/s3_server.conf.template" "/etc/nginx/templates/gateway/s3_server.conf.template"
-download "oss/etc/nginx/templates/upstreams.conf.template" "/etc/nginx/templates/upstreams.conf.template"
-download "oss/etc/nginx/conf.d/gateway/server_variables.conf" "/etc/nginx/conf.d/gateway/server_variables.conf"
-
-echo "▶ Creating directory for proxy cache"
-mkdir -p /var/cache/nginx/s3_proxy
-chown nginx:nginx /var/cache/nginx/s3_proxy
-
-echo "▶ Starting NGINX"
-systemctl start nginx
diff --git a/test.sh b/test.sh
deleted file mode 100755
index 6099163..0000000
--- a/test.sh
+++ /dev/null
@@ -1,360 +0,0 @@
-#!/usr/bin/env bash
-
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-set -o errexit   # abort on nonzero exit status
-set -o pipefail  # don't hide errors within pipes
-
-nginx_server_proto="http"
-nginx_server_host="localhost"
-nginx_server_port="8989"
-minio_server="http://localhost:9090"
-test_server="${nginx_server_proto}://${nginx_server_host}:${nginx_server_port}"
-test_fail_exit_code=2
-no_dep_exit_code=3
-script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-test_dir="${script_dir}/test"
-test_compose_config="${test_dir}/docker-compose.yaml"
-test_compose_project="ngt"
-
-p() {
-  printf "\033[34;1m▶\033[0m "
-  echo "$1"
-}
-
-e() {
-  >&2 echo "$1"
-}
-
-usage() { e "Usage: $0 [--latest-njs <default:false>] [--unprivileged <default:false>] [--type <default:oss|plus>" 1>&2; exit 1; }
-
-for arg in "$@"; do
-  shift
-  case "$arg" in
-    '--help')           set -- "$@" '-h'   ;;
-    '--latest-njs')     set -- "$@" '-j'   ;;
-    '--unprivileged')   set -- "$@" '-u'   ;;
-    '--type')           set -- "$@" '-t'   ;;
-    *)                  set -- "$@" "$arg" ;;
-  esac
-done
-
-while getopts "hjut:" arg; do
-    case "${arg}" in
-        j)
-            njs_latest="1"
-            ;;
-        u)
-            unprivileged="1"
-            ;;
-        t)
-            nginx_type="${OPTARG}"
-            ;;
-        *)
-            usage
-            ;;
-    esac
-done
-shift $((OPTIND-1))
-
-startup_message=""
-
-if [ -z "${nginx_type}" ]; then
-  nginx_type="oss"
-  startup_message="Starting NGINX ${nginx_type} (default)"
-elif ! { [ ${nginx_type} == "oss" ] || [ ${nginx_type} == "plus" ]; }; then
-    e "Invalid NGINX type: ${nginx_type} - must be either 'oss' or 'plus'"
-    usage
-else
-  startup_message="Starting NGINX ${nginx_type}"
-fi
-
-if [ -z "${njs_latest}" ]; then
-  njs_latest="0"
-  startup_message="${startup_message} with the release NJS module (default)"
-elif [ ${njs_latest} -eq 1 ]; then
-  startup_message="${startup_message} with the latest NJS module"
-else
-  startup_message="${startup_message} with the release NJS module"
-fi
-
-if [ -z "${unprivileged}" ]; then
-  unprivileged="0"
-  startup_message="${startup_message} in privileged mode (default)"
-elif [ ${unprivileged} -eq 1 ]; then
-  startup_message="${startup_message} in unprivileged mode"
-else
-  startup_message="${startup_message} in privileged mode"
-fi
-
-e "${startup_message}"
-
-set -o nounset   # abort on unbound variable
-
-docker_cmd="$(command -v docker)"
-if ! [ -x "${docker_cmd}" ]; then
-  e "required dependency not found: docker not found in the path or not executable"
-  exit ${no_dep_exit_code}
-fi
-
-docker_compose_cmd="$(command -v docker-compose)"
-if ! [ -x "${docker_compose_cmd}" ]; then
-  e "required dependency not found: docker-compose not found in the path or not executable"
-  exit ${no_dep_exit_code}
-fi
-
-curl_cmd="$(command -v curl)"
-if ! [ -x "${curl_cmd}" ]; then
-  e "required dependency not found: curl not found in the path or not executable"
-  exit ${no_dep_exit_code}
-fi
-
-wait_for_it_cmd="$(command -v wait-for-it || true)"
-if [ -x "${wait_for_it_cmd}" ]; then
-  wait_for_it_installed=1
-else
-  e "wait-for-it command not available, consider installing to prevent race conditions"
-  wait_for_it_installed=0
-fi
-
-if [ "${nginx_type}" = "plus" ]; then
-  if [ ! -f "./plus/etc/ssl/nginx/nginx-repo.crt" ]; then
-    e "NGINX Plus certificate file not found: $(pwd)/plus/etc/ssl/nginx/nginx-repo.crt"
-    exit ${no_dep_exit_code}
-  fi
-
-    if [ ! -f "./plus/etc/ssl/nginx/nginx-repo.key" ]; then
-    e "NGINX Plus key file not found: $(pwd)/plus/etc/ssl/nginx/nginx-repo.key"
-    exit ${no_dep_exit_code}
-  fi
-fi
-
-compose() {
-  # Hint to docker-compose the internal port to map for the container
-  if [ ${unprivileged} -eq 1 ]; then
-    export NGINX_INTERNAL_PORT=8080
-  else
-    export NGINX_INTERNAL_PORT=80
-  fi
-
-  "${docker_compose_cmd}" -f "${test_compose_config}" -p "${test_compose_project}" "$@"
-}
-
-integration_test() {
-  printf "\033[34;1m▶\033[0m"
-  printf "\e[1m Integration test suite for v%s signatures\e[22m\n" "$1"
-  printf "\033[34;1m▶\033[0m"
-  printf "\e[1m Integration test suite with ALLOW_DIRECTORY_LIST=%s\e[22m\n" "$2"
-  printf "\033[34;1m▶\033[0m"
-  printf "\e[1m Integration test suite with PROVIDE_INDEX_PAGE=%s\e[22m\n" "$3"
-  printf "\033[34;1m▶\033[0m"
-  printf "\e[1m Integration test suite with APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=%s\e[22m\n" "$4"
-
-  # See if Minio is already running, if it isn't then we don't need to build it
-  # COMPOSE_COMPATIBILITY=true Supports older style compose filenames with _ vs -
-
-  if [ -z "$(docker ps -q -f name=${test_compose_project}_minio-_1)" ]; then
-    p "Building Docker Compose environment"
-    COMPOSE_COMPATIBILITY=true AWS_SIGS_VERSION=$1 ALLOW_DIRECTORY_LIST=$2 PROVIDE_INDEX_PAGE=$3 APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=$4 compose up --no-start
-
-    p "Adding test data to container"
-    echo "Copying contents of ${test_dir}/data to Docker container ${test_compose_project}_minio_1:/"
-    "${docker_cmd}" cp "${test_dir}/data" "${test_compose_project}"_minio_1:/
-    echo "Docker diff output:"
-    "${docker_cmd}" diff "${test_compose_project}"_minio_1
-  fi
-
-  p "Starting Docker Compose Environment"
-  COMPOSE_COMPATIBILITY=true AWS_SIGS_VERSION=$1 ALLOW_DIRECTORY_LIST=$2 PROVIDE_INDEX_PAGE=$3 APPEND_SLASH_FOR_POSSIBLE_DIRECTORY=$4 compose up -d
-
-  if [ "${wait_for_it_installed}" ]; then
-    # Hit minio's health check end point to see if it has started up
-    for (( i=1; i<=3; i++ ))
-    do
-      echo "Querying minio server to see if it is ready"
-      minio_is_up="$(${curl_cmd} -s -o /dev/null -w '%{http_code}' "${minio_server}"/minio/health/cluster)"
-      if [ "${minio_is_up}" = "200" ]; then
-        break
-      else
-        sleep 2
-      fi
-    done
-
-    if [ -x "${wait_for_it_cmd}" ]; then
-      "${wait_for_it_cmd}" -h "${nginx_server_host}" -p "${nginx_server_port}"
-    fi
-  fi
-
-  p "Starting HTTP API tests (v$1 signatures)"
-  echo "  test/integration/test_api.sh \"$test_server\" \"$test_dir\" $1 $2 $3 $4"
-  bash "${test_dir}/integration/test_api.sh" "${test_server}" "${test_dir}" "$1" "$2" "$3" "$4";
-
-  # We check to see if NGINX is in fact using the correct version of AWS
-  # signatures as it was configured to do.
-  sig_versions_found_count=$(compose logs nginx-s3-gateway | grep -c "AWS Signatures Version: v$1\|AWS v$1 Auth")
-
-  if [ "${sig_versions_found_count}" -lt 3 ]; then
-    e "NGINX was not detected as using the correct signatures version - examine logs"
-    compose logs nginx-s3-gateway
-    exit "$test_fail_exit_code"
-  fi
-}
-
-finish() {
-  result=$?
-
-  if [ $result -ne 0 ]; then
-    e "Error running tests - outputting container logs"
-    compose logs
-  fi
-
-  p "Cleaning up Docker compose environment"
-  compose stop
-  compose rm -f
-
-  exit ${result}
-}
-trap finish EXIT ERR SIGTERM SIGINT
-
-### BUILD
-
-p "Building NGINX S3 gateway Docker image"
-if [ "${nginx_type}" = "plus" ]; then
-  if docker buildx > /dev/null 2>&1; then
-    p "Building using BuildKit"
-    export DOCKER_BUILDKIT=1
-    docker build -f Dockerfile.buildkit.${nginx_type} \
-      --secret id=nginx-crt,src=plus/etc/ssl/nginx/nginx-repo.crt \
-      --secret id=nginx-key,src=plus/etc/ssl/nginx/nginx-repo.key \
-      --no-cache --squash \
-      --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
-  else
-    docker build -f Dockerfile.${nginx_type} \
-      --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
-  fi
-else
-  docker build -f Dockerfile.${nginx_type} \
-    --tag nginx-s3-gateway --tag nginx-s3-gateway:${nginx_type} .
-fi
-
-if [ ${njs_latest} -eq 1 ]; then
-  p "Layering in latest NJS build"
-  docker build -f Dockerfile.latest-njs \
-    --tag nginx-s3-gateway --tag nginx-s3-gateway:latest-njs-${nginx_type} .
-fi
-
-if [ ${unprivileged} -eq 1 ]; then
-  p "Layering in unprivileged build"
-  docker build -f Dockerfile.unprivileged \
-    --tag nginx-s3-gateway --tag nginx-s3-gateway:unprivileged-${nginx_type} .
-fi
-
-### UNIT TESTS
-
-runUnitTestWithOutSessionToken() {
-  test_code="$1"
-
-  #MSYS_NO_PATHCONV=1 added to resolve automatic path conversion
-  # https://github.com/docker/for-win/issues/6754#issuecomment-629702199
-  MSYS_NO_PATHCONV=1 "${docker_cmd}" run  \
-    --rm                                  \
-    -v "$(pwd)/test/unit:/var/tmp"        \
-    --workdir /var/tmp                    \
-    -e "S3_DEBUG=true"                    \
-    -e "S3_STYLE=virtual"                 \
-    -e "AWS_ACCESS_KEY_ID=unit_test"       \
-    -e "AWS_SECRET_ACCESS_KEY=unit_test"          \
-    -e "S3_BUCKET_NAME=unit_test"         \
-    -e "S3_SERVER=unit_test"              \
-    -e "S3_SERVER_PROTO=https"            \
-    -e "S3_SERVER_PORT=443"               \
-    -e "S3_REGION=test-1"                 \
-    -e "AWS_SIGS_VERSION=4"               \
-    --entrypoint /usr/bin/njs             \
-    nginx-s3-gateway -t module -p '/etc/nginx' /var/tmp/"${test_code}" 
-}
-
-runUnitTestWithSessionToken() {
-  test_code="$1"
-
-  #MSYS_NO_PATHCONV=1 added to resolve automatic path conversion
-  # https://github.com/docker/for-win/issues/6754#issuecomment-629702199
-  MSYS_NO_PATHCONV=1 "${docker_cmd}" run  \
-    --rm                                  \
-    -v "$(pwd)/test/unit:/var/tmp"        \
-    --workdir /var/tmp                    \
-    -e "S3_DEBUG=true"                    \
-    -e "S3_STYLE=virtual"                 \
-    -e "AWS_ACCESS_KEY_ID=unit_test"       \
-    -e "AWS_SECRET_ACCESS_KEY=unit_test"          \
-    -e "AWS_SESSION_TOKEN=unit_test"       \
-    -e "S3_BUCKET_NAME=unit_test"         \
-    -e "S3_SERVER=unit_test"              \
-    -e "S3_SERVER_PROTO=https"            \
-    -e "S3_SERVER_PORT=443"               \
-    -e "S3_REGION=test-1"                 \
-    -e "AWS_SIGS_VERSION=4"               \
-    --entrypoint /usr/bin/njs             \
-    nginx-s3-gateway -t module -p '/etc/nginx' /var/tmp/"${test_code}" 
-}
-
-p "Running unit tests for utils"
-runUnitTestWithSessionToken "utils_test.js"
-
-p "Running unit tests with an access key ID and a secret key in Docker image"
-runUnitTestWithOutSessionToken "awscredentials_test.js"
-runUnitTestWithOutSessionToken "awssig2_test.js"
-runUnitTestWithOutSessionToken "awssig4_test.js"
-runUnitTestWithOutSessionToken "s3gateway_test.js"
-
-p "Running unit tests with an session token in Docker image"
-runUnitTestWithSessionToken "awscredentials_test.js"
-runUnitTestWithSessionToken "awssig2_test.js"
-runUnitTestWithSessionToken "awssig4_test.js"
-runUnitTestWithSessionToken "s3gateway_test.js"
-
-### INTEGRATION TESTS
-
-p "Testing API with AWS Signature V2 and allow directory listing off"
-integration_test 2 0 0 0
-
-compose stop nginx-s3-gateway # Restart with new config
-
-p "Testing API with AWS Signature V2 and allow directory listing on"
-integration_test 2 1 0 0
-
-compose stop nginx-s3-gateway # Restart with new config
-
-p "Testing API with AWS Signature V2 and static site on"
-integration_test 2 0 1 0
-
-compose stop nginx-s3-gateway # Restart with new config
-
-p "Test API with AWS Signature V4 and allow directory listing off"
-integration_test 4 0 0 0
-
-compose stop nginx-s3-gateway # Restart with new config
-
-p "Test API with AWS Signature V4 and allow directory listing on and appending /"
-integration_test 4 1 0 1
-
-compose stop nginx-s3-gateway # Restart with new config
-
-p "Test API with AWS Signature V4 and static site on appending /"
-integration_test 4 0 1 1
-
-p "All integration tests complete"
diff --git a/test/data/bucket-1/a.txt b/test/data/bucket-1/a.txt
deleted file mode 100644
index 272166e..0000000
--- a/test/data/bucket-1/a.txt
+++ /dev/null
@@ -1 +0,0 @@
-Let go, or be dragged.
diff --git a/test/data/bucket-1/a/%@!*()=$#^&|.txt b/test/data/bucket-1/a/%@!*()=$#^&|.txt
deleted file mode 100644
index 371d5ff..0000000
--- a/test/data/bucket-1/a/%@!*()=$#^&|.txt
+++ /dev/null
@@ -1 +0,0 @@
-We are but selling water next to a river.
diff --git a/test/data/bucket-1/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt b/test/data/bucket-1/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt
deleted file mode 100644
index 423ec8a..0000000
--- a/test/data/bucket-1/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-"Where the is not one thing, what then?"
-"Throw it away!"
-"With not one thing, what there is to throw away?"
-"Then carry it off!"
diff --git "a/test/data/bucket-1/a/c/\343\201\202" "b/test/data/bucket-1/a/c/\343\201\202"
deleted file mode 100644
index ae1b7e9..0000000
--- "a/test/data/bucket-1/a/c/\343\201\202"
+++ /dev/null
@@ -1 +0,0 @@
-aaaaaaaaaahhhhhhhhhhhhh
diff --git a/test/data/bucket-1/a/plus+plus.txt b/test/data/bucket-1/a/plus+plus.txt
deleted file mode 100644
index 1cb69e0..0000000
--- a/test/data/bucket-1/a/plus+plus.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-代悲白頭翁　　　Lament for the White-Haired Old Man
-洛陽城東桃李花　In the east of Luoyang City, Peach blossoms abound
-飛來飛去落誰家　Their petals float around, coming and going, to whose house will they fall?
-洛陽女児惜顔色　Girls in Luoyang cherish their complexion
-行逢落花長歎息　They breathe a deep sigh upon seeing the petals fall
-今年花落顔色改　This year the petals fall and their complexion changes
-明年花開復誰在　Who will be there when the flowers bloom next year?
-已見松柏摧為薪　I've seen the pines and cypresses destroyed and turned into firewood
-更聞桑田変成海　I hear that the mulberry fields have fallen into the sea
-古人無復洛城東　The people of old never came back to the east of Luoyang City
-今人還對落花風　The people of today likewise face the falling flowers in the wind
-年年歳歳花相似　Year after year, flowers look alike
-歳歳年年人不同　Year after year, the people are not the same
-寄言全盛紅顔子　I want you to get this message, my child, you are in your prime, with a rosy complexion
-應憐半死白頭翁　Take pity on the half-dead white-haired old man
-此翁白頭真可憐　You really must take pity on this white-haired old man
-伊昔紅顔美少年　For once upon a time, I used to be a red-faced handsome young man
-公子王孫芳樹下　A child of noble birth under a fragrant tree
-清歌妙舞落花前　Singing and dancing in front of the falling petals
-光禄池臺開錦繍　At the platform before the mirror pond, beautiful autumn leaves opening all around
-将軍楼閣畫神仙　The general’s pavilion is painted with gods and goddesses
-一朝臥病無相識　Once I was sick and no one knew me
-三春行楽在誰邉　Who will be at the shore for the spring outing?
-宛轉蛾眉能幾時　For how long will the moths gracefully turn about?
-須臾鶴髪亂如絲　The crane’s feathers are like tangled threads for just a moment
-但看古来歌舞地　Yet, look at the ancient places of song and dance
-惟有黄昏鳥雀悲　Only in twilight, do the birds lament
diff --git "a/test/data/bucket-1/a/\343\201\223\343\202\214\343\201\257\343\200\200This is ASCII \321\201\320\270\321\201\321\202\320\265\320\274\321\213  \327\227\327\237 .txt" "b/test/data/bucket-1/a/\343\201\223\343\202\214\343\201\257\343\200\200This is ASCII \321\201\320\270\321\201\321\202\320\265\320\274\321\213  \327\227\327\237 .txt"
deleted file mode 100644
index 08f8ebb..0000000
--- "a/test/data/bucket-1/a/\343\201\223\343\202\214\343\201\257\343\200\200This is ASCII \321\201\320\270\321\201\321\202\320\265\320\274\321\213  \327\227\327\237 .txt"	
+++ /dev/null
@@ -1 +0,0 @@
-What name do you use to call out to the emptiness?
diff --git a/test/data/bucket-1/b/c/'(1).txt b/test/data/bucket-1/b/c/'(1).txt
deleted file mode 100644
index 88c2ee1..0000000
--- a/test/data/bucket-1/b/c/'(1).txt
+++ /dev/null
@@ -1 +0,0 @@
-In the midst of movement and chaos, keep stillness inside of you.
\ No newline at end of file
diff --git a/test/data/bucket-1/b/c/= b/test/data/bucket-1/b/c/=
deleted file mode 100644
index 582ad56..0000000
--- a/test/data/bucket-1/b/c/=
+++ /dev/null
@@ -1,2 +0,0 @@
-This is an awful filename.
-このフィール名を選ばないでください
diff --git a/test/data/bucket-1/b/c/d.txt b/test/data/bucket-1/b/c/d.txt
deleted file mode 100644
index 0665a64..0000000
--- a/test/data/bucket-1/b/c/d.txt
+++ /dev/null
@@ -1 +0,0 @@
-When thoughts arise, then do all things arise. When thoughts vanish, then do all things vanish.
diff --git a/test/data/bucket-1/b/e.txt b/test/data/bucket-1/b/e.txt
deleted file mode 100644
index 1d3546d..0000000
--- a/test/data/bucket-1/b/e.txt
+++ /dev/null
@@ -1 +0,0 @@
-If only you could hear the sound of snow.
diff --git "a/test/data/bucket-1/b/\343\202\257\343\202\272\347\256\261/\343\202\264\343\203\237.txt" "b/test/data/bucket-1/b/\343\202\257\343\202\272\347\256\261/\343\202\264\343\203\237.txt"
deleted file mode 100644
index a0ed7d6..0000000
--- "a/test/data/bucket-1/b/\343\202\257\343\202\272\347\256\261/\343\202\264\343\203\237.txt"
+++ /dev/null
@@ -1 +0,0 @@
-What is the sound of two hands clapping?
diff --git "a/test/data/bucket-1/b/\343\203\226\343\203\204\343\203\226\343\203\204.txt" "b/test/data/bucket-1/b/\343\203\226\343\203\204\343\203\226\343\203\204.txt"
deleted file mode 100644
index 4e42dfd..0000000
--- "a/test/data/bucket-1/b/\343\203\226\343\203\204\343\203\226\343\203\204.txt"
+++ /dev/null
@@ -1 +0,0 @@
-Relax. Nothing is under control.
diff --git a/test/data/bucket-1/index.html b/test/data/bucket-1/index.html
deleted file mode 100644
index 809d266..0000000
--- a/test/data/bucket-1/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Test whether redirects to index.html
\ No newline at end of file
diff --git a/test/data/bucket-1/statichost/index.html b/test/data/bucket-1/statichost/index.html
deleted file mode 100644
index 612c5bb..0000000
--- a/test/data/bucket-1/statichost/index.html
+++ /dev/null
@@ -1 +0,0 @@
-static index
\ No newline at end of file
diff --git "a/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/%bad%file%name%" "b/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/%bad%file%name%"
deleted file mode 100644
index 87b5b38..0000000
--- "a/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/%bad%file%name%"
+++ /dev/null
@@ -1 +0,0 @@
-Filename encoding issues are hard.
diff --git "a/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/system.txt" "b/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/system.txt"
deleted file mode 100644
index 00e08e4..0000000
--- "a/test/data/bucket-1/\321\201\320\270\321\201\321\202\320\265\320\274\321\213/system.txt"
+++ /dev/null
@@ -1 +0,0 @@
-The rewrite will not fix it.
diff --git a/test/docker-compose.yaml b/test/docker-compose.yaml
deleted file mode 100644
index ffe09ff..0000000
--- a/test/docker-compose.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-version: "3"
-
-services:
-  nginx-s3-gateway:
-    # If minio client is up and running properly, we are reasonably sure that
-    # minio has properly started. That's why we depend on it here.
-    depends_on:
-      minio:
-        condition: service_healthy
-    image: "nginx-s3-gateway"
-    ports:
-      - "8989:${NGINX_INTERNAL_PORT-80}/tcp"
-    links:
-      - "minio"
-    restart: "no"
-    environment:
-      S3_BUCKET_NAME: "bucket-1"
-      AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
-      AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
-      S3_SERVER: "minio"
-      S3_SERVER_PORT: "9000"
-      S3_SERVER_PROTO: "http"
-      S3_REGION: "us-east-1"
-      S3_DEBUG: "true"
-      S3_STYLE: "virtual"
-      ALLOW_DIRECTORY_LIST:
-      PROVIDE_INDEX_PAGE:
-      APPEND_SLASH_FOR_POSSIBLE_DIRECTORY:
-      AWS_SIGS_VERSION:
-      STATIC_SITE_HOSTING:
-      PROXY_CACHE_VALID_OK: "1h"
-      PROXY_CACHE_VALID_NOTFOUND: "1m"
-      PROXY_CACHE_VALID_FORBIDDEN: "30s"
-
-  minio:
-    image: "minio/minio:RELEASE.2021-02-19T04-38-02Z"
-    ports:
-      - "9090:9000/tcp"
-    restart: "no"
-    command: "server --address :9000 /data"
-    environment:
-      MINIO_ACCESS_KEY: "AKIAIOSFODNN7EXAMPLE"
-      MINIO_SECRET_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
-      MINIO_REGION_NAME: "us-east-1"
-      MINIO_DOMAIN: "minio"
-      MINIO_BROWSER: "off"
-    healthcheck:
-      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
-      interval: 5s
-      timeout: 3s
-      retries: 3
-  # It may be useful to enable minio client so that you can debug what calls
-  # were made to minio by the gateway.
-#  minio-client:
-#    depends_on:
-#      - "minio"
-#    image: "minio/mc"
-#    restart: "no"
-#    command: "admin trace --verbose nginx-test-gateway"
-#    environment:
-#      MC_HOST_nginx-test-gateway: "http://AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY@minio:9000"
diff --git a/test/integration/test_api.sh b/test/integration/test_api.sh
deleted file mode 100644
index 1233dbd..0000000
--- a/test/integration/test_api.sh
+++ /dev/null
@@ -1,299 +0,0 @@
-#!/usr/bin/env bash
-
-#
-#  Copyright 2020 F5 Networks
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-
-set -o errexit   # abort on nonzero exit status
-set -o pipefail  # don't hide errors within pipes
-
-test_server=$1
-test_dir=$2
-signature_version=$3
-allow_directory_list=$4
-index_page=$5
-append_slash=$6
-test_fail_exit_code=2
-no_dep_exit_code=3
-checksum_length=32
-
-## Check for Windows Machine.  Temporary fix to skip non-ascii characters on Windows to run Integration Tests
-## I know there could be other windows machines that display OS differently or don't have the issue with UTF-8
-## but I don't have them to test.
-## remove this once UTF-8 issue solved.
-
-is_windows="0"
-if [ -z "${OS}" ] && [ "${OS}" == "Windows_NT" ]; then
-  is_windows="1"
-elif command -v uname > /dev/null; then
-  uname_output="$(uname -s)"
-  if [[ "${uname_output}" == *"_NT-"* ]]; then
-    is_windows="1"
-  fi
-fi
-
-set -o nounset   # abort on unbound variable
-
-e() {
-  >&2 echo "$1"
-}
-
-if [ -z "${test_server}" ]; then
-  e "missing first parameter: test server location (eg http://localhost:80)"
-fi
-
-if [ -z "${test_dir}" ]; then
-  e "missing second parameter: path to test data directory"
-fi
-
-curl_cmd="$(command -v curl)"
-if ! [ -x "${curl_cmd}" ]; then
-  e "required dependency not found: curl not found in the path or not executable"
-  exit ${no_dep_exit_code}
-fi
-
-checksum_cmd="$(command -v md5sum)"
-if ! [ -x "${curl_cmd}" ]; then
-  e "required dependency not found: md5sum not found in the path or not executable"
-  exit ${no_dep_exit_code}
-fi
-
-assertHttpRequestEquals() {
-  method="$1"
-  path="$2"
-
-  if [[ $path == /* ]]; then
-    uri="${test_server}${path}"
-  else
-    uri="${test_server}/${path}"
-  fi
-
-  if [ "${index_page}" == "1" ]; then
-    # Follow 302 redirect if testing static hosting
-    # Add the -v flag to the curl command below to debug why curl is failing
-    extra_arg="-L"
-  else
-    extra_arg=""
-  fi
-
-  printf "  \033[36;1m▲\033[0m "
-  echo "Testing object: ${method} ${path}"
-
-  if [ "${method}" = "HEAD" ]; then
-    expected_response_code="$3"
-    actual_response_code="$(${curl_cmd} -s -o /dev/null -w '%{http_code}' --head "${uri}" ${extra_arg})"
-
-    if [ "${expected_response_code}" != "${actual_response_code}" ]; then
-      e "Response code didn't match expectation. Request [${method} ${uri}] Expected [${expected_response_code}] Actual [${actual_response_code}]"
-      e "curl command: ${curl_cmd} -s -o /dev/null -w '%{http_code}' --head '${uri}' ${extra_arg}"
-      exit ${test_fail_exit_code}
-    fi
-  elif [ "${method}" = "GET" ]; then
-    body_data_path="${test_dir}/$3"
-
-    if [ -f "$body_data_path" ]; then
-      checksum_output="$(${checksum_cmd} "${body_data_path}")"
-      expected_checksum="${checksum_output:0:${checksum_length}}"
-
-      curl_checksum_output="$(${curl_cmd} -s -X "${method}" "${uri}" ${extra_arg} | ${checksum_cmd})"
-      s3_file_checksum="${curl_checksum_output:0:${checksum_length}}"
-
-      if [ "${expected_checksum}" != "${s3_file_checksum}" ]; then
-        e "Checksum doesn't match expectation. Request [${method} ${uri}] Expected [${expected_checksum}] Actual [${s3_file_checksum}]"
-        e "curl command: ${curl_cmd} -s -X '${method}' '${uri}' ${extra_arg} | ${checksum_cmd}"
-        exit ${test_fail_exit_code}
-      fi
-    else
-      expected_response_code="$3"
-      actual_response_code="$(${curl_cmd} -s -o /dev/null -w '%{http_code}' "${uri}" ${extra_arg})"
-
-      if [ "${expected_response_code}" != "${actual_response_code}" ]; then
-        e "Response code didn't match expectation. Request [${method} ${uri}] Expected [${expected_response_code}] Actual [${actual_response_code}]"
-        e "curl command: ${curl_cmd} -s -o /dev/null -w '%{http_code}' '${uri}' ${extra_arg}"
-        exit ${test_fail_exit_code}
-      fi
-    fi
-  else
-    e "Method unsupported: [${method}]"
-  fi
-}
-
-# Check to see if HTTP server is available
-set +o errexit
-# Allow curl command to fail with a non-zero exit code for this block because
-# we want to use it to test to see if the server is actually up.
-for (( i=1; i<=3; i++ )); do
-  # Add the -v flag to the curl command below to debug why curl is failing
-  response="$(${curl_cmd} -s -o /dev/null -w '%{http_code}' --head "${test_server}")"
-  if [ "${response}" != "000" ]; then
-    break
-  fi
-  wait_time="$((i * 2))"
-  e "Failed to access ${test_server} - trying again in ${wait_time} seconds, try ${i}/3"
-  sleep ${wait_time}
-done
-set -o errexit
-
-# Ordinary filenames
-
-assertHttpRequestEquals "HEAD" "a.txt" "200"
-assertHttpRequestEquals "HEAD" "a.txt?some=param&that=should&be=stripped#aaah" "200"
-assertHttpRequestEquals "HEAD" "b/c/d.txt" "200"
-assertHttpRequestEquals "HEAD" "b/c/../e.txt" "200"
-assertHttpRequestEquals "HEAD" "b/e.txt" "200"
-assertHttpRequestEquals "HEAD" "b//e.txt" "200"
-assertHttpRequestEquals "HEAD" "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" "200"
-
-# We try to request URLs that are properly encoded as well as URLs that
-# are not properly encoded to understand what works and what does not.
-
-# Weird filenames
-assertHttpRequestEquals "HEAD" "b/c/%3D" "200"
-assertHttpRequestEquals "HEAD" "b/c/=" "200"
-
-assertHttpRequestEquals "HEAD" "b/c/%40" "200"
-assertHttpRequestEquals "HEAD" "b/c/@" "200"
-
-assertHttpRequestEquals "HEAD" "b/c/%27%281%29.txt" "200"
-assertHttpRequestEquals "HEAD" "b/c/'(1).txt" "200"
-
-# These URLs do not work unencoded
-assertHttpRequestEquals "HEAD" 'a/plus%2Bplus.txt' "200"
-assertHttpRequestEquals "HEAD" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "200"
-
-# Testing these files does not currently work on Windows
-if [ ${is_windows} == "0" ]; then
-  assertHttpRequestEquals "HEAD" "a/c/%E3%81%82" "200"
-  assertHttpRequestEquals "HEAD" "a/c/あ" "200"
-
-  assertHttpRequestEquals "HEAD" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/%E3%82%B4%E3%83%9F.txt" "200"
-  assertHttpRequestEquals "HEAD" "b/クズ箱/ゴミ.txt" "200"
-
-  assertHttpRequestEquals "HEAD" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/system.txt" "200"
-  assertHttpRequestEquals "HEAD" "системы/system.txt" "200"
-
-  assertHttpRequestEquals "HEAD" "b/%E3%83%96%E3%83%84%E3%83%96%E3%83%84.txt" "200"
-  assertHttpRequestEquals "HEAD" "b/ブツブツ.txt" "200"
-
-  # These URLs do not work unencoded
-  assertHttpRequestEquals "HEAD" 'a/%25%40%21%2A%28%29%3D%24%23%5E%26%7C.txt' "200"
-  assertHttpRequestEquals "HEAD" 'a/%E3%81%93%E3%82%8C%E3%81%AF%E3%80%80This%20is%20ASCII%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%20%20%D7%97%D7%9F%20.txt' "200"
-fi
-
-# Expected 400s
-# curl will not send this to server now
-# assertHttpRequestEquals "HEAD" "request with unencoded spaces" "400"
-
-# Expected 404s
-if [ "${append_slash}" == "1" ] && [ "${index_page}" == "0" ]; then
-  assertHttpRequestEquals "HEAD" "not%20found" "302"
-  assertHttpRequestEquals "HEAD" "b/c" "302"
-else
-  assertHttpRequestEquals "HEAD" "not%20found" "404"
-  assertHttpRequestEquals "HEAD" "b/c" "404"
-fi
-
-# Directory HEAD 404s
-# Unfortunately, the logic here can't be properly encoded into the test.
-# With minio, we can't return anything *but* a 404 for HEAD requests to a directory.
-# With AWS S3, HEAD requests to a directory will return 200 *only* when we are
-# running with v4 signatures.
-# Now, both of these cases have the exception of HEAD returning 200 on the root
-# directory.
-if [ "${allow_directory_list}" == "1" ] || [ "${index_page}" == "1" ]; then
-  assertHttpRequestEquals "HEAD" "/" "200"
-else
-  assertHttpRequestEquals "HEAD" "/" "404"
-fi
-assertHttpRequestEquals "HEAD" "b/" "404"
-assertHttpRequestEquals "HEAD" "/b/c/" "404"
-assertHttpRequestEquals "HEAD" "/soap" "404"
-if [ "${append_slash}" == "1" ] && [ "${index_page}" == "0" ]; then
-assertHttpRequestEquals "HEAD" "b//c" "302"
-else
-assertHttpRequestEquals "HEAD" "b//c" "404"
-fi
-
-if [ "${index_page}" == "1" ]; then
-assertHttpRequestEquals "HEAD" "/statichost/" "200"
-assertHttpRequestEquals "HEAD" "/nonexistdir/noindexdir/" "404"
-assertHttpRequestEquals "HEAD" "/nonexistdir/noindexdir" "404"
-assertHttpRequestEquals "HEAD" "/statichost/noindexdir/multipledir/" "200"
-assertHttpRequestEquals "HEAD" "/nonexistdir/" "404"
-assertHttpRequestEquals "HEAD" "/nonexistdir" "404"
-  if [ ${append_slash} == "1" ]; then
-  assertHttpRequestEquals "HEAD" "/statichost" "200"
-  assertHttpRequestEquals "HEAD" "/statichost/noindexdir/multipledir" "200"
-  else
-  assertHttpRequestEquals "HEAD" "/statichost" "404"
-  assertHttpRequestEquals "HEAD" "/statichost/noindexdir/multipledir" "404"
-  fi
-fi
-
-# Verify GET is working
-assertHttpRequestEquals "GET" "a.txt" "data/bucket-1/a.txt"
-assertHttpRequestEquals "GET" "a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt" "data/bucket-1/a/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.txt"
-assertHttpRequestEquals "GET" "a.txt?some=param&that=should&be=stripped#aaah" "data/bucket-1/a.txt"
-assertHttpRequestEquals "GET" "b/c/d.txt" "data/bucket-1/b/c/d.txt"
-
-assertHttpRequestEquals "GET" "b/c/%3D" "data/bucket-1/b/c/="
-assertHttpRequestEquals "GET" "b/c/=" "data/bucket-1/b/c/="
-
-assertHttpRequestEquals "GET" "b/c/%27%281%29.txt" "data/bucket-1/b/c/'(1).txt"
-assertHttpRequestEquals "GET" "b/c/'(1).txt" "data/bucket-1/b/c/'(1).txt"
-
-assertHttpRequestEquals "GET" "b/e.txt" "data/bucket-1/b/e.txt"
-
-# These URLs do not work unencoded
-assertHttpRequestEquals "GET" 'a/plus%2Bplus.txt' "data/bucket-1/a/plus+plus.txt"
-
-# Testing these files does not currently work on Windows
-if [ ${is_windows} == "0" ]; then
-  assertHttpRequestEquals "GET" "a/c/%E3%81%82" "data/bucket-1/a/c/あ"
-  assertHttpRequestEquals "GET" "b/%E3%83%96%E3%83%84%E3%83%96%E3%83%84.txt" "data/bucket-1/b/ブツブツ.txt"
-  assertHttpRequestEquals "GET" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/%E3%82%B4%E3%83%9F.txt" "data/bucket-1/b/クズ箱/ゴミ.txt"
-  assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/system.txt" "data/bucket-1/системы/system.txt"
-  assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/%25bad%25file%25name%25" "data/bucket-1/системы/%bad%file%name%"
-  assertHttpRequestEquals "GET" 'a/%25%40%21%2A%28%29%3D%24%23%5E%26%7C.txt' 'data/bucket-1/a/%@!*()=$#^&|.txt'
-  assertHttpRequestEquals "GET" 'a/%E3%81%93%E3%82%8C%E3%81%AF%E3%80%80This%20is%20ASCII%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%20%20%D7%97%D7%9F%20.txt' "data/bucket-1/a/これは　This is ASCII системы  חן .txt"
-fi
-
-if [ "${index_page}" == "1" ]; then
-assertHttpRequestEquals "GET" "/statichost/" "data/bucket-1/statichost/index.html"
-assertHttpRequestEquals "GET" "/statichost/noindexdir/multipledir/" "data/bucket-1/statichost/noindexdir/multipledir/index.html"
-  if [ "${append_slash}" == "1" ]; then
-  assertHttpRequestEquals "GET" "/statichost" "data/bucket-1/statichost/index.html"
-  assertHttpRequestEquals "GET" "/statichost/noindexdir/multipledir" "data/bucket-1/statichost/noindexdir/multipledir/index.html"
-  fi
-fi
-
-if [ "${allow_directory_list}" == "1" ]; then
-  assertHttpRequestEquals "GET" "/" "200"
-  assertHttpRequestEquals "GET" "b/" "200"
-  assertHttpRequestEquals "GET" "/b/c/" "200"
-  assertHttpRequestEquals "GET" "b/%E3%82%AF%E3%82%BA%E7%AE%B1/" "200"
-  assertHttpRequestEquals "GET" "b/クズ箱/" "200"
-  assertHttpRequestEquals "GET" "%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B/" "200"
-  assertHttpRequestEquals "GET" "системы/" "200"
-  if [ "$append_slash" == "1" ]; then
-    assertHttpRequestEquals "GET" "b" "302"
-  else
-    assertHttpRequestEquals "GET" "b" "404"
-  fi
-elif [ "${index_page}" == "1" ]; then
-  assertHttpRequestEquals "GET" "/" "data/bucket-1/index.html"
-else
-  assertHttpRequestEquals "GET" "/" "404"
-fi
diff --git a/test/unit/awscredentials_test.js b/test/unit/awscredentials_test.js
deleted file mode 100644
index 42ee6c2..0000000
--- a/test/unit/awscredentials_test.js
+++ /dev/null
@@ -1,314 +0,0 @@
-#!env njs
-
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import awscred from "include/awscredentials.js";
-import fs from "fs";
-
-globalThis.ngx = {};
-
-
-function testReadCredentialsWithAccessSecretKeyAndSessionTokenSet() {
-    printHeader('testReadCredentialsWithAccessSecretKeyAndSessionTokenSet');
-    let r = {};
-    process.env['AWS_ACCESS_KEY_ID'] = 'SOME_ACCESS_KEY';
-    process.env['AWS_SECRET_ACCESS_KEY'] = 'SOME_SECRET_KEY';
-    if ('AWS_SESSION_TOKEN' in process.env) {
-        process.env['AWS_SESSION_TOKEN'] = 'SOME_SESSION_TOKEN';
-    }
-
-    try {
-        var credentials = awscred.readCredentials(r);
-        if (credentials.accessKeyId !== process.env['AWS_ACCESS_KEY_ID']) {
-            throw 'static credentials do not match returned value [accessKeyId]';
-        }
-        if (credentials.secretAccessKey !== process.env['AWS_SECRET_ACCESS_KEY']) {
-            throw 'static credentials do not match returned value [secretAccessKey]';
-        }
-        if ('AWS_SESSION_TOKEN' in process.env) {
-            if (credentials.sessionToken !== process.env['AWS_SESSION_TOKEN']) {
-                throw 'static credentials do not match returned value [sessionToken]';
-            }
-        } else {
-            if (credentials.sessionToken !== null) {
-                throw 'static credentials do not match returned value [sessionToken]';
-            }
-        }
-        if (credentials.expiration !== null) {
-            throw 'static credentials do not match returned value [expiration]';
-        }
-
-    } finally {
-        delete process.env.AWS_ACCESS_KEY_ID;
-        delete process.env.AWS_SECRET_ACCESS_KEY;
-        if ('AWS_SESSION_TOKEN' in process.env) {
-            delete process.env.AWS_SESSION_TOKEN;
-        }
-    }
-}
-
-function testReadCredentialsFromFilePath() {
-    printHeader('testReadCredentialsFromFilePath');
-    let r = {
-        variables: {
-            cache_instance_credentials_enabled: 0
-        }
-    };
-
-    var originalCredentialPath = process.env['AWS_CREDENTIALS_TEMP_FILE'];
-    var tempDir = (process.env['TMPDIR'] ? process.env['TMPDIR'] : '/tmp');
-    var uniqId = `${new Date().getTime()}-${Math.floor(Math.random()*101)}`;
-    var tempFile = `${tempDir}/credentials-unit-test-${uniqId}.json`;
-    var testData = '{"accessKeyId":"A","secretAccessKey":"B",' +
-        '"sessionToken":"C","expiration":"2022-02-15T04:49:08Z"}';
-    fs.writeFileSync(tempFile, testData);
-
-    try {
-        process.env['AWS_CREDENTIALS_TEMP_FILE'] = tempFile;
-        var credentials = awscred.readCredentials(r);
-        var testDataAsJSON = JSON.parse(testData);
-        if (credentials.accessKeyId !== testDataAsJSON.accessKeyId) {
-            throw 'JSON test data does not match credentials [accessKeyId]';
-        }
-        if (credentials.secretAccessKey !== testDataAsJSON.secretAccessKey) {
-            throw 'JSON test data does not match credentials [secretAccessKey]';
-        }
-        if (credentials.sessionToken !== testDataAsJSON.sessionToken) {
-            throw 'JSON test data does not match credentials [sessionToken]';
-        }
-        if (credentials.expiration !== testDataAsJSON.expiration) {
-            throw 'JSON test data does not match credentials [expiration]';
-        }
-    } finally {
-        if (originalCredentialPath) {
-            process.env['AWS_CREDENTIALS_TEMP_FILE'] = originalCredentialPath;
-        }
-        if (fs.statSync(tempFile, {throwIfNoEntry: false})) {
-            fs.unlinkSync(tempFile);
-        }
-    }
-}
-
-function testReadCredentialsFromNonexistentPath() {
-    printHeader('testReadCredentialsFromNonexistentPath');
-    let r = {
-        variables: {
-            cache_instance_credentials_enabled: 0
-        }
-    };
-    var originalCredentialPath = process.env['AWS_CREDENTIALS_TEMP_FILE'];
-    var tempDir = (process.env['TMPDIR'] ? process.env['TMPDIR'] : '/tmp');
-    var uniqId = `${new Date().getTime()}-${Math.floor(Math.random()*101)}`;
-    var tempFile = `${tempDir}/credentials-unit-test-${uniqId}.json`;
-
-    try {
-        process.env['AWS_CREDENTIALS_TEMP_FILE'] = tempFile;
-        var credentials = awscred.readCredentials(r);
-        if (credentials !== undefined) {
-            throw 'Credentials returned when no credentials file should be present';
-        }
-
-    } finally {
-        if (originalCredentialPath) {
-            process.env['AWS_CREDENTIALS_TEMP_FILE'] = originalCredentialPath;
-        }
-        if (fs.statSync(tempFile, {throwIfNoEntry: false})) {
-            fs.unlinkSync(tempFile);
-        }
-    }
-}
-
-function testReadAndWriteCredentialsFromKeyValStore() {
-    printHeader('testReadAndWriteCredentialsFromKeyValStore');
-
-    let accessKeyId = process.env['AWS_ACCESS_KEY_ID'];
-    let secretKey = process.env['AWS_SECRET_ACCESS_KEY'];
-    let sessionToken = null;
-    if ('AWS_SESSION_TOKEN' in process.env) {
-        sessionToken = process.env['AWS_SESSION_TOKEN'];
-    }
-    delete process.env.AWS_ACCESS_KEY_ID;
-    delete process.env.AWS_SECRET_ACCESS_KEY;
-    if ('AWS_SESSION_TOKEN' in process.env) {
-        delete process.env.AWS_SESSION_TOKEN
-    }
-    try {
-        let r = {
-            variables: {
-                cache_instance_credentials_enabled: 1,
-                instance_credential_json: null
-            }
-        };
-        let expectedCredentials = {
-            AccessKeyId: 'AN_ACCESS_KEY_ID',
-            Expiration: '2017-05-17T15:09:54Z',
-            RoleArn: 'TASK_ROLE_ARN',
-            SecretAccessKey: 'A_SECRET_ACCESS_KEY',
-            Token: 'A_SECURITY_TOKEN',
-        };
-
-        awscred.writeCredentials(r, expectedCredentials);
-        let credentials = JSON.stringify(awscred.readCredentials(r));
-        let expectedJson = JSON.stringify(expectedCredentials);
-
-        if (credentials !== expectedJson) {
-            console.log(`EXPECTED:\n${expectedJson}\nACTUAL:\n${credentials}`);
-            throw 'Credentials do not match expected value';
-        }
-    } finally {
-        process.env['AWS_ACCESS_KEY_ID'] = accessKeyId;
-        process.env['AWS_SECRET_ACCESS_KEY'] = secretKey;
-        if ('AWS_SESSION_TOKEN' in process.env) {
-            process.env['AWS_SESSION_TOKEN'] = sessionToken
-        }
-    }
-}
-
-async function testEcsCredentialRetrieval() {
-    printHeader('testEcsCredentialRetrieval');
-    process.env['AWS_ACCESS_KEY_ID'] = undefined;
-    process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/example';
-    globalThis.ngx.fetch = function (url) {
-        globalThis.recordedUrl = url;
-
-        return Promise.resolve({
-            ok: true,
-            json: function () {
-                return Promise.resolve({
-                    AccessKeyId: 'AN_ACCESS_KEY_ID',
-                    Expiration: '2017-05-17T15:09:54Z',
-                    RoleArn: 'TASK_ROLE_ARN',
-                    SecretAccessKey: 'A_SECRET_ACCESS_KEY',
-                    Token: 'A_SECURITY_TOKEN',
-                });
-            }
-        });
-    };
-    var r = {
-        "headersOut" : {
-            "Accept-Ranges": "bytes",
-            "Content-Length": 42,
-            "Content-Security-Policy": "block-all-mixed-content",
-            "Content-Type": "text/plain",
-            "X-Amz-Bucket-Region": "us-east-1",
-            "X-Amz-Request-Id": "166539E18A46500A",
-            "X-Xss-Protection": "1; mode=block"
-        },
-        log: function(msg) {
-            console.log(msg);
-        },
-        return: function(code) {
-            if (code !== 200) {
-                throw 'Expected 200 status code, got: ' + code;
-            }
-        },
-    };
-
-    await awscred.fetchCredentials(r);
-
-    if (globalThis.recordedUrl !== 'http://169.254.170.2/example') {
-        throw 'No or wrong ECS credentials fetch URL recorded: ' + globalThis.recordedUrl;
-    }
-}
-
-async function testEc2CredentialRetrieval() {
-    printHeader('testEc2CredentialRetrieval');
-    process.env['AWS_ACCESS_KEY_ID'] = undefined;
-    process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = undefined;
-    globalThis.ngx.fetch = function (url, options) {
-        if (url === 'http://169.254.169.254/latest/api/token' && options && options.method === 'PUT') {
-            return Promise.resolve({
-                ok: true,
-                text: function () {
-                    return Promise.resolve('A_TOKEN');
-                },
-            });
-        } else if (url === 'http://169.254.169.254/latest/meta-data/iam/security-credentials/') {
-            if (options && options.headers && options.headers['x-aws-ec2-metadata-token'] === 'A_TOKEN') {
-                return Promise.resolve({
-                    ok: true,
-                    text: function () {
-                        return Promise.resolve('A_ROLE_NAME');
-                    },
-                });
-            } else {
-                throw 'Invalid token passed: ' + options.headers['x-aws-ec2-metadata-token'];
-            }
-        }  else if (url === 'http://169.254.169.254/latest/meta-data/iam/security-credentials/A_ROLE_NAME') {
-            if (options && options.headers && options.headers['x-aws-ec2-metadata-token'] === 'A_TOKEN') {
-                return Promise.resolve({
-                    ok: true,
-                    json: function () {
-                        globalThis.credentialsIssued = true;
-                        return Promise.resolve({
-                            AccessKeyId: 'AN_ACCESS_KEY_ID',
-                            Expiration: '2017-05-17T15:09:54Z',
-                            RoleArn: 'TASK_ROLE_ARN',
-                            SecretAccessKey: 'A_SECRET_ACCESS_KEY',
-                            Token: 'A_SECURITY_TOKEN',
-                        });
-                    },
-                });
-            } else {
-                throw 'Invalid token passed: ' + options.headers['x-aws-ec2-metadata-token'];
-            }
-        } else {
-            throw 'Invalid request URL: ' + url;
-        }
-    };
-    var r = {
-        "headersOut" : {
-            "Accept-Ranges": "bytes",
-            "Content-Length": 42,
-            "Content-Security-Policy": "block-all-mixed-content",
-            "Content-Type": "text/plain",
-            "X-Amz-Bucket-Region": "us-east-1",
-            "X-Amz-Request-Id": "166539E18A46500A",
-            "X-Xss-Protection": "1; mode=block"
-        },
-        log: function(msg) {
-            console.log(msg);
-        },
-        return: function(code) {
-            if (code !== 200) {
-                throw 'Expected 200 status code, got: ' + code;
-            }
-        },
-    };
-
-    await awscred.fetchCredentials(r);
-
-    if (!globalThis.credentialsIssued) {
-        throw 'Did not reach the point where EC2 credentials were issues.';
-    }
-}
-
-async function test() {
-    await testEc2CredentialRetrieval();
-    await testEcsCredentialRetrieval();
-    testReadCredentialsWithAccessSecretKeyAndSessionTokenSet();
-    testReadCredentialsFromFilePath();
-    testReadCredentialsFromNonexistentPath();
-    testReadAndWriteCredentialsFromKeyValStore();
-}
-
-function printHeader(testName) {
-    console.log(`\n## ${testName}`);
-}
-
-test();
-console.log('Finished unit tests for awscredentials.js');
diff --git a/test/unit/awssig2_test.js b/test/unit/awssig2_test.js
deleted file mode 100644
index c61507b..0000000
--- a/test/unit/awssig2_test.js
+++ /dev/null
@@ -1,89 +0,0 @@
-#!env njs
-
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import awssig2 from "include/awssig2.js";
-import s3gateway from "include/s3gateway.js";
-
-
-function _runSignatureV2(r) {
-    r.log = function(msg) {
-        console.log(msg);
-    }
-    const timestamp = new Date('2020-08-11T19:42:14Z');
-    const bucket = 'test-bucket-1';
-    const accessKey = 'test-access-key-1';
-    const secret = 'pvgoBEA1z7zZKqN9RoKVksKh31AtNou+pspn+iyb'
-    const creds = {
-        accessKeyId:accessKey, secretAccessKey: secret, sessionToken: null
-    };
-
-    const httpDate = timestamp.toUTCString();
-    const expected = 'AWS test-access-key-1:VviSS4cFhUC6eoB4CYqtRawzDrc=';
-    const req_uri = '/'.concat(bucket, r.variables.uri_path);
-    let signature = awssig2.signatureV2(r, req_uri, httpDate, creds);
-
-    if (signature !== expected) {
-        throw 'V2 signature hash was not created correctly.\n' +
-        'Actual:   [' + signature + ']\n' +
-        'Expected: [' + expected + ']';
-    }
-}
-
-function testSignatureV2() {
-    printHeader('testSignatureV2');
-    // Note: since this is a read-only gateway, host, query parameters and all
-    // client headers will be ignored.
-    var r = {
-        "remoteAddress" : "172.17.0.1",
-        "headersIn" : {
-            "Connection" : "keep-alive",
-            "Accept-Encoding" : "gzip, deflate",
-            "Accept-Language" : "en-US,en;q=0.7,ja;q=0.3",
-            "Host" : "localhost:8999",
-            "User-Agent" : "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
-            "DNT" : "1",
-            "Cache-Control" : "max-age=0",
-            "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
-            "Upgrade-Insecure-Requests" : "1"
-        },
-        "uri" : "/a/c/ramen.jpg",
-        "method" : "GET",
-        "httpVersion" : "1.1",
-        "headersOut" : {},
-        "args" : {
-            "foo" : "bar"
-        },
-        "variables" : {
-            "uri_path": "/a/c/ramen.jpg"
-        },
-        "status" : 0
-    };
-
-    _runSignatureV2(r);
-}
-
-async function test() {
-    testSignatureV2();
-}
-
-function printHeader(testName) {
-    console.log(`\n## ${testName}`);
-}
-
-test();
-console.log('Finished unit tests for awssig2.js');
diff --git a/test/unit/awssig4_test.js b/test/unit/awssig4_test.js
deleted file mode 100644
index 1d8f9ca..0000000
--- a/test/unit/awssig4_test.js
+++ /dev/null
@@ -1,174 +0,0 @@
-#!env njs
-
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import awssig4 from "include/awssig4.js";
-import s3gateway from "include/s3gateway.js";
-import utils from "include/utils.js";
-
-
-function testBuildSigningKeyHashWithReferenceInputs() {
-    printHeader('testBuildSigningKeyHashWithReferenceInputs');
-    var kSecret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY';
-    var date = '20150830';
-    var service = 'iam';
-    var region = 'us-east-1';
-    var expected = 'c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9';
-    var signingKeyHash = awssig4._buildSigningKeyHash(kSecret, date, region, service).toString('hex');
-
-    if (signingKeyHash !== expected) {
-        throw 'Signing key hash was not created correctly.\n' +
-        'Actual:   [' + signingKeyHash + ']\n' +
-        'Expected: [' + expected + ']';
-    }
-}
-
-function testBuildSigningKeyHashWithTestSuiteInputs() {
-    printHeader('testBuildSigningKeyHashWithTestSuiteInputs');
-    var kSecret = 'pvgoBEA1z7zZKqN9RoKVksKh31AtNou+pspn+iyb';
-    var date = '20200811';
-    var service = 's3';
-    var region = 'us-west-2';
-    var expected = 'a48701bfe803103e89051f55af2297dd76783bbceb5eb416dab71e0eadcbc4f6';
-    var signingKeyHash = awssig4._buildSigningKeyHash(kSecret, date, region, service).toString('hex');
-
-    if (signingKeyHash !== expected) {
-        throw 'Signing key hash was not created correctly.\n' +
-        'Actual:   [' + signingKeyHash + ']\n' +
-        'Expected: [' + expected + ']';
-    }
-}
-
-function _runSignatureV4(r) {
-    r.log = function(msg) {
-        console.log(msg);
-    }
-    var timestamp = new Date('2020-08-11T19:42:14Z');
-    var eightDigitDate = utils.getEightDigitDate(timestamp);
-    var amzDatetime = utils.getAmzDatetime(timestamp, eightDigitDate);
-    var bucket = 'ez-test-bucket-1'
-    var secret = 'pvgoBEA1z7zZKqN9RoKVksKh31AtNou+pspn+iyb'
-    var creds = {secretAccessKey: secret, sessionToken: null};
-    var region = 'us-west-2';
-    var service = 's3';
-    var server = 's3-us-west-2.amazonaws.com';
-
-    const req = {
-        uri : r.variables.uri_path,
-        queryParams : '',
-        host: bucket.concat('.', server)
-    }
-    const canonicalRequest = awssig4._buildCanonicalRequest(
-        r.method, req.uri, req.queryParams, req.host, amzDatetime, creds.sessionToken);
-
-    var expected = 'cf4dd9e1d28c74e2284f938011efc8230d0c20704f56f67e4a3bfc2212026bec';
-    var signature = awssig4._buildSignatureV4(
-        r, amzDatetime, eightDigitDate, creds, region, service, canonicalRequest);
-    
-    if (signature !== expected) {
-        throw 'V4 signature hash was not created correctly.\n' +
-        'Actual:   [' + signature + ']\n' +
-        'Expected: [' + expected + ']';
-    }
-}
-
-function testSignatureV4() {
-    printHeader('testSignatureV4');
-    // Note: since this is a read-only gateway, host, query parameters and all
-    // client headers will be ignored.
-    var r = {
-        "remoteAddress" : "172.17.0.1",
-        "headersIn" : {
-            "Connection" : "keep-alive",
-            "Accept-Encoding" : "gzip, deflate",
-            "Accept-Language" : "en-US,en;q=0.7,ja;q=0.3",
-            "Host" : "localhost:8999",
-            "User-Agent" : "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
-            "DNT" : "1",
-            "Cache-Control" : "max-age=0",
-            "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
-            "Upgrade-Insecure-Requests" : "1"
-        },
-        "uri" : "/a/c/ramen.jpg",
-        "method" : "GET",
-        "httpVersion" : "1.1",
-        "headersOut" : {},
-        "args" : {
-            "foo" : "bar"
-        },
-        "variables" : {
-            "uri_path": "/a/c/ramen.jpg"
-        },
-        "status" : 0
-    };
-
-    _runSignatureV4(r);
-}
-
-function testSignatureV4Cache() {
-    printHeader('testSignatureV4Cache');
-    // Note: since this is a read-only gateway, host, query parameters and all
-    // client headers will be ignored.
-    var r = {
-        "remoteAddress" : "172.17.0.1",
-        "headersIn" : {
-            "Connection" : "keep-alive",
-            "Accept-Encoding" : "gzip, deflate",
-            "Accept-Language" : "en-US,en;q=0.7,ja;q=0.3",
-            "Host" : "localhost:8999",
-            "User-Agent" : "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
-            "DNT" : "1",
-            "Cache-Control" : "max-age=0",
-            "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
-            "Upgrade-Insecure-Requests" : "1"
-        },
-        "uri" : "/a/c/ramen.jpg",
-        "method" : "GET",
-        "httpVersion" : "1.1",
-        "headersOut" : {},
-        "args" : {
-            "foo" : "bar"
-        },
-        "variables": {
-            "cache_signing_key_enabled": 1,
-            "uri_path": "/a/c/ramen.jpg"
-        },
-        "status" : 0
-    };
-
-    _runSignatureV4(r);
-
-    if (!"signing_key_hash" in r.variables) {
-        throw "Hash key not written to r.variables.signing_key_hash";
-    }
-
-    _runSignatureV4(r);
-}
-
-async function test() {
-    testBuildSigningKeyHashWithReferenceInputs();
-    testBuildSigningKeyHashWithTestSuiteInputs();
-    testSignatureV4();
-    testSignatureV4Cache();
-}
-
-function printHeader(testName) {
-    console.log(`\n## ${testName}`);
-}
-
-test();
-console.log('Finished unit tests for awssig4.js');
diff --git a/test/unit/s3gateway_test.js b/test/unit/s3gateway_test.js
deleted file mode 100755
index 8c7e6f0..0000000
--- a/test/unit/s3gateway_test.js
+++ /dev/null
@@ -1,217 +0,0 @@
-#!env njs
-
-/*
- *  Copyright 2020 F5 Networks
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import awssig4 from "include/awssig4.js";
-import s3gateway from "include/s3gateway.js";
-
-var fakeRequest = {
-    "remoteAddress" : "172.17.0.1",
-    "headersIn" : {
-        "Connection" : "keep-alive",
-        "Accept-Encoding" : "gzip, deflate",
-        "Accept-Language" : "en-US,en;q=0.7,ja;q=0.3",
-        "Host" : "localhost:8999",
-        "User-Agent" : "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0",
-        "DNT" : "1",
-        "Cache-Control" : "max-age=0",
-        "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
-        "Upgrade-Insecure-Requests" : "1"
-    },
-    "uri" : "/a/c/ramen.jpg",
-    "method" : "GET",
-    "httpVersion" : "1.1",
-    "headersOut" : {},
-    "args" : {
-        "foo" : "bar"
-    },
-    "status" : 0
-};
-
-fakeRequest.log = function(msg) {
-    console.log(msg);
-}
-
-function testEncodeURIComponent() {
-    printHeader('testEncodeURIComponent');
-    function testPureAsciiAlphaNum() {
-        console.log('  ## testPureAsciiAlphaNum');
-        let alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
-        let encoded = s3gateway._encodeURIComponent(alphaNum);
-        if (alphaNum !== alphaNum) {
-            throw 'Incorrect encoding applied to string.\n' +
-            `Actual:   [${encoded}]\n` +
-            `Expected: [${expected}]`;
-        }
-    }
-    function testUnicodeText() {
-        console.log('  ## testUnicodeText');
-        let unicode = 'これは　This is ASCII системы  חן ';
-        let expected = '%E3%81%93%E3%82%8C%E3%81%AF%E3%80%80This%20is%20ASCII%20%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%20%20%D7%97%D7%9F%20';
-        let encoded = s3gateway._encodeURIComponent(unicode);
-        if (expected !== encoded) {
-            throw 'Incorrect encoding applied to string.\n' +
-            `Actual:   [${encoded}]\n` +
-            `Expected: [${expected}]`;
-        }
-    }
-    function testDiceyCharactersInText() {
-        console.log('  ## testDiceyCharactersInText');
-
-        let diceyCharacters = '%@!*()=+$#^&|\\/';
-        for (let i = 0; i < diceyCharacters.length; i++) {
-            let char = diceyCharacters[i];
-            let encoded = s3gateway._encodeURIComponent(char);
-            let expected = `%${char.charCodeAt(0).toString(16).toUpperCase()}`;
-            if (encoded !== expected) {
-                throw 'Incorrect encoding applied to string.\n' +
-                `Actual:   [${encoded}]\n` +
-                `Expected: [${expected}]`;
-            }
-        }
-    }
-
-    testPureAsciiAlphaNum();
-    testUnicodeText();
-    testDiceyCharactersInText();
-}
-
-function testSplitCachedValues() {
-    printHeader('testSplitCachedValues');
-    var eightDigitDate = "20200811"
-    var kSigningHash = "{\"type\":\"Buffer\",\"data\":[164,135,1,191,232,3,16,62,137,5,31,85,175,34,151,221,118,120,59,188,235,94,180,22,218,183,30,14,173,203,196,246]}"
-    var cached = eightDigitDate + ":" + kSigningHash;
-    var fields = awssig4._splitCachedValues(cached);
-
-    if (fields.length !== 2) {
-        throw 'Unexpected array length returned.\n' +
-        'Actual:   [' + fields.length + ']\n' +
-        'Expected: [2]';
-    }
-
-    if (fields[0] !== eightDigitDate) {
-        throw 'Eight digit date field not extracted correctly.\n' +
-        'Actual:   [' + fields[0] + ']\n' +
-        'Expected: [' + eightDigitDate + ']';
-    }
-
-    if (fields[1] !== kSigningHash) {
-        throw 'kSigningHash field not extracted correctly.\n' +
-        'Actual:   [' + fields[1] + ']\n' +
-        'Expected: [' + kSigningHash + ']';
-    }
-}
-
-function testEditHeaders() {
-    printHeader('testEditHeaders');
-
-    const r = {
-        "headersOut": {
-            "Accept-Ranges": "bytes",
-            "Content-Length": 42,
-            "Content-Security-Policy": "block-all-mixed-content",
-            "Content-Type": "text/plain",
-            "X-Amz-Bucket-Region": "us-east-1",
-            "X-Amz-Request-Id": "166539E18A46500A",
-            "X-Xss-Protection": "1; mode=block"
-        },
-        "variables": {
-            "uri_path": "/a/c/ramen.jpg"
-        },
-    }
-
-    r.log = function(msg) {
-        console.log(msg);
-    }
-
-    s3gateway.editHeaders(r);
-
-    for (const key in r.headersOut) {
-        if (key.toLowerCase().indexOf("x-amz", 0) >= 0) {
-            throw "x-amz header not stripped from headers correctly";
-        }
-    }
-}
-
-function testEditHeadersHeadDirectory() {
-    printHeader('testEditHeadersHeadDirectory');
-    let r = {
-        "method": "HEAD",
-        "headersOut" : {
-            "Content-Security-Policy": "block-all-mixed-content",
-                "Content-Type": "application/xml",
-                "Server": "AmazonS3",
-                "X-Amz-Bucket-Region": "us-east-1",
-                "X-Amz-Request-Id": "166539E18A46500A",
-                "X-Xss-Protection": "1; mode=block"
-        },
-    "variables": {
-            "uri_path": "/a/c/"
-        },
-    }
-
-    r.log = function(msg) {
-        console.log(msg);
-    }
-
-    s3gateway.editHeaders(r);
-
-    if (r.headersOut.length > 0) {
-        throw "all headers were not stripped from request";
-    }
-}
-
-function testIsHeaderToBeStripped() {
-    printHeader('testIsHeaderToBeStripped');
-    // if (s3gateway._isHeaderToBeStripped('cache-control', [])) {
-    //     throw "valid header should not be stripped";
-    // }
-    // if (!s3gateway._isHeaderToBeStripped('x-amz-request-id', [])) {
-    //     throw "x-amz header should always be stripped";
-    // }
-    if (!s3gateway._isHeaderToBeStripped('x-goog-storage-class',
-        ['x-goog'])) {
-        throw "x-goog-storage-class header should be stripped";
-    }
-}
-
-function testEscapeURIPathPreservesDoubleSlashes() {
-    printHeader('testEscapeURIPathPreservesDoubleSlashes');
-    var doubleSlashed = '/testbucketer2/foo3//bar3/somedir/license';
-    var actual = s3gateway._escapeURIPath(doubleSlashed);
-    var expected = '/testbucketer2/foo3//bar3/somedir/license';
-
-    if (actual !== expected) {
-        throw 'URI Path escaping is stripping slashes'
-    }
-}
-
-function printHeader(testName) {
-    console.log(`\n## ${testName}`);
-}
-
-async function test() {
-    testEncodeURIComponent();
-    testSplitCachedValues();
-    testIsHeaderToBeStripped();
-    testEditHeaders();
-    testEditHeadersHeadDirectory();
-    testEscapeURIPathPreservesDoubleSlashes();
-}
-
-test();
-console.log('Finished unit tests for s3gateway.js');
diff --git a/test/unit/utils_test.js b/test/unit/utils_test.js
deleted file mode 100644
index 7abcbea..0000000
--- a/test/unit/utils_test.js
+++ /dev/null
@@ -1,137 +0,0 @@
-#!env njs
-
-/*
- *  Copyright 2023 F5, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-import utils from "include/utils.js";
-
-function testParseArray() {
-    printHeader('testParseArray');
-
-    function testParseNull() {
-        console.log('  ## testParseNull');
-        const actual = utils.parseArray(null);
-        if (!Array.isArray(actual) || actual.length > 0) {
-            throw 'Null not parsed into an empty array';
-        }
-    }
-    function testParseEmptyString() {
-        console.log('  ## testParseEmptyString');
-        const actual = utils.parseArray('');
-        if (!Array.isArray(actual) || actual.length > 0) {
-            throw 'Empty string not parsed into an empty array';
-        }
-    }
-    function testParseSingleValue() {
-        console.log('  ## testParseSingleValue');
-        const value = 'Single Value';
-        const actual = utils.parseArray(value);
-        if (!Array.isArray(actual) || actual.length !== 1) {
-            throw 'Single value not parsed into an array with a single element';
-        }
-        if (actual[0] !== value) {
-            throw `Unexpected array element: ${actual[0]}`
-        }
-    }
-    function testParseMultipleValues() {
-        console.log('  ## testParseMultipleValues');
-        const values = ['string 1', 'something else', 'Yet another value'];
-        const textValues = values.join(';');
-        const actual = utils.parseArray(textValues);
-        if (!Array.isArray(actual) || actual.length !== values.length) {
-            throw 'Multiple values not parsed into an array with the expected length';
-        }
-        for (let i = 0; i < values.length; i++) {
-            if (values[i] !== actual[i]) {
-                throw `Unexpected array element [${i}]: ${actual[i]}`
-            }
-        }
-    }
-
-    function testParseMultipleValuesTrailingDelimiter() {
-        console.log('  ## testParseMultipleValuesTrailingDelimiter');
-        const values = ['string 1', 'something else', 'Yet another value'];
-        const textValues = values.join(';');
-        const actual = utils.parseArray(textValues + ';');
-        if (!Array.isArray(actual) || actual.length !== values.length) {
-            throw 'Multiple values not parsed into an array with the expected length';
-        }
-        for (let i = 0; i < values.length; i++) {
-            if (values[i] !== actual[i]) {
-                throw `Unexpected array element [${i}]: ${actual[i]}`
-            }
-        }
-    }
-
-    testParseNull();
-    testParseEmptyString();
-    testParseSingleValue();
-    testParseMultipleValues();
-    testParseMultipleValuesTrailingDelimiter();
-}
-
-function testAmzDatetime() {
-    printHeader('testAmzDatetime');
-    var timestamp = new Date('2020-08-03T02:01:09.004Z');
-    var eightDigitDate = utils.getEightDigitDate(timestamp);
-    var amzDatetime = utils.getAmzDatetime(timestamp, eightDigitDate);
-    var expected = '20200803T020109Z';
-
-    if (amzDatetime !== expected) {
-        throw 'Amazon date time was not created correctly.\n' +
-        'Actual:   [' + amzDatetime + ']\n' +
-        'Expected: [' + expected + ']';
-    }
-}
-
-function testEightDigitDate() {
-    printHeader('testEightDigitDate');
-    var timestamp = new Date('2020-08-03T02:01:09.004Z');
-    var eightDigitDate = utils.getEightDigitDate(timestamp);
-    var expected = '20200803';
-
-    if (eightDigitDate !== expected) {
-        throw 'Eight digit date was not created correctly.\n' +
-        'Actual:   ' + eightDigitDate + '\n' +
-        'Expected: ' + expected;
-    }
-}
-
-function testPad() {
-    printHeader('testPad');
-    var padSingleDigit = utils.padWithLeadingZeros(3, 2);
-    var expected = '03';
-
-    if (padSingleDigit !== expected) {
-        throw 'Single digit 3 was not padded with leading zero.\n' +
-        'Actual:   ' + padSingleDigit + '\n' +
-        'Expected: ' + expected;
-    }
-}
-
-async function test() {
-    testAmzDatetime();
-    testEightDigitDate();
-    testPad();
-    testParseArray();
-}
-    
-function printHeader(testName) {
-    console.log(`\n## ${testName}`);
-}
-
-test();
-console.log('Finished unit tests for utils.js');
diff --git a/test/data/bucket-1/statichost/noindexdir/noindex.html b/tests/integration-test/.gitkeep
similarity index 100%
rename from test/data/bucket-1/statichost/noindexdir/noindex.html
rename to tests/integration-test/.gitkeep
diff --git a/tests/unit-test/.gitkeep b/tests/unit-test/.gitkeep
new file mode 100644
index 0000000..e69de29
