Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
uses: rutajdash/[email protected]
with:
config_path: ${{ github.workspace }}/internal/nginx/modules/.prettierrc
file_pattern: ${{ github.workspace }}/internal/nginx/modules/*.js
file_pattern: ${{ github.workspace }}/internal/nginx/modules/**/*.js
prettier_version: 2.6.2
- name: Prettier Output
if: ${{ failure() }}
Expand Down Expand Up @@ -119,9 +119,9 @@ jobs:
- name: Setup Node.js Environment
uses: actions/setup-node@v3
with:
node_version: 18
node-version: 18
- run: npm install mocha@^8.2 esm chai
- run: npx mocha -r esm ${{ github.workspace }}/internal/nginx/modules/httpmatches_test.js
- run: npx mocha -r esm ${{ github.workspace }}/internal/nginx/modules/test/httpmatches.test.js

binary:
name: Build Binary
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ cover.html

# Binary and Artifacts
build/.out

# Node modules
internal/nginx/modules/node_modules

# JS test coverage
internal/nginx/modules/coverage
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ fmt: ## Run go fmt against code.

.PHONY: njs-fmt
njs-fmt: ## Run prettier against the njs httpmatches module.
docker run --rm \
-v $(PWD)/internal/nginx/modules/:/njs-modules/ \
docker run --rm -w /modules \
-v $(PWD)/internal/nginx/modules/:/modules/ \
node:18 \
npx [email protected] --write njs-modules/ --config=njs-modules/.prettierrc
/bin/bash -c "npm install && npm run format"

.PHONY: vet
vet: ## Run go vet against code.
Expand All @@ -86,10 +86,10 @@ unit-test: ## Run unit tests for the go code
go tool cover -html=cover.out -o cover.html

njs-unit-test: ## Run unit tests for the njs httpmatches module.
docker run --rm -w /src \
-v $(PWD)/internal/nginx/modules/:/src/njs-modules/ \
docker run --rm -w /modules \
-v $(PWD)/internal/nginx/modules:/modules/ \
node:18 \
/bin/bash -c "npm install mocha@^8.2 esm chai && npx mocha -r esm njs-modules/httpmatches_test.js"
/bin/bash -c "npm install && npm test && npm run clean"

.PHONY: dev-all
dev-all: deps fmt njs-fmt vet lint unit-test njs-unit-test
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ You can deploy NGINX Kubernetes Gateway on an existing Kubernetes 1.16+ cluster.
1. Create the njs-modules configmap:

```
kubectl create configmap njs-modules --from-file=internal/nginx/modules/httpmatches.js -n nginx-gateway
kubectl create configmap njs-modules --from-file=internal/nginx/modules/src/httpmatches.js -n nginx-gateway
```

1. Deploy the NGINX Kubernetes Gateway:
Expand Down
85 changes: 54 additions & 31 deletions examples/advanced-routing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
In this example we will deploy NGINX Kubernetes Gateway and configure advanced routing rules for a simple cafe application.
We will use `HTTPRoute` resources to route traffic to the cafe application based on a combination of the request method, headers, and query parameters.

The cafe application consists of four services: `coffee-v1-svc`, `coffee-v2-svc`, `tea-svc`, and `tea-post-svc`. In the next section we will create the following routing rules for the cafe application:
- For the path `/coffee` route requests with the header `version` set to `v2` or with the query param `TEST` set to `v2` to `coffee-v2-svc`, and all other requests to `coffee-v1-svc`.
- For the path `/tea` route POST requests to `tea-post-svc`, and all other requests, such as `GET` requests, to `tea-svc`.

## Running the Example

## 1. Deploy NGINX Kubernetes Gateway
Expand Down Expand Up @@ -33,9 +37,11 @@ We will use `HTTPRoute` resources to route traffic to the cafe application based

```
kubectl -n default get pods
NAME READY STATUS RESTARTS AGE
coffee-6f4b79b975-2sb28 1/1 Running 0 12s
tea-6fb46d899f-fm7zr 1/1 Running 0 12s
NAME READY STATUS RESTARTS AGE
coffee-v1-75869cf7ff-vlfpq 1/1 Running 0 17m
coffee-v2-67499ff985-2k6cc 1/1 Running 0 17m
tea-6fb46d899f-hjzwr 1/1 Running 0 17m
tea-post-648dfcdd6c-2rlqb 1/1 Running 0 17m
```

## 3. Configure Routing
Expand All @@ -48,51 +54,68 @@ We will use `HTTPRoute` resources to route traffic to the cafe application based

## 4. Test the Application

We will use `curl` to send requests to the `coffee` and `tea` services.
We will use `curl` to send requests to the `/coffee` and `/tea` endpoints of the cafe application.

### 4.1 Access coffee

Send a `POST` request to the path `/coffee` with the headers `X-Demo-Header:Demo-X1` and `version:v1`:
Send a request with the header `version:v2` and confirm that the response comes from `coffee-v2-svc`:

```
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -X POST -H "X-Demo-Header:Demo-X1" -H "version:v1"
Server address: 10.12.0.18:80
Server name: coffee-7586895968-r26zn
```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "version:v2"
Server address: 10.116.2.67:8080
Server name: coffee-v2-67499ff985-gw6vt
...
```

Header keys are case-insensitive, so we can also access coffee with the following request:
Send a request with the query parameter `TEST=v2` and confirm that the response comes from `coffee-v2-svc`:

```
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -X POST -H "X-DEMO-HEADER:Demo-X1" -H "Version:v1"
Server address: 10.12.0.18:80
Server name: coffee-7586895968-r26zn
```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee?TEST=v2
Server address: 10.116.2.67:8080
Server name: coffee-v2-67499ff985-gw6vt
...
```

Only `POST` requests to the path `/coffee` with the headers `X-Demo-Header:Demo-X1` and `version:v1` will be able to access coffee.
For example, try sending the following `GET` request:
```
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "X-Demo-Header:Demo-X1" -H "version:v1"
```
Send a request without the header or the query parameter and confirm the response comes from `coffee-v1-svc`:

NGINX Kubernetes Gateway returns a 405 since the request method does not match the method defined in the routing rule for `/coffee`.
```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee
Server address: 10.116.2.70:8080
Server name: coffee-v1-75869cf7ff-vlfpq
...
```

### 4.2 Access tea

Send a request to the path `/tea` with the query parameter `Great=Example`:
Send a POST request and confirm that the response comes from `tea-post-svc`:

```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X POST
Server address: 10.116.2.72:8080
Server name: tea-post-648dfcdd6c-2rlqb
...
```
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea?Great=Example
Server address: 10.12.0.19:80
Server name: tea-7cd44fcb4d-xfw2x
```

Query parameters are case-sensitive, so the case must match what you specify in the `HTTPRoute` resource.

Only requests to the path `/tea` with the query parameter `Great=Example` will be able to access tea.
For example, try sending the following request:
Send a GET request and confirm that the response comes from `tea-svc`:

```
```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea
Server address: 10.116.3.30:8080
Server name: tea-6fb46d899f-hjzwr
...
```

NGINX Kubernetes Gateway returns a 404 since the request does not satisfy the routing rule configured for `/tea`.
The `/tea` endpoint has routing rules configured for GET and POST requests. If you send a request with a different method, NGINX Kubernetes Gateway will return a 404.

Send a PUT request and confirm the 404 Not Found response:

```bash
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X PUT
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.21.3</center>
</body>
</html>
```
50 changes: 25 additions & 25 deletions examples/advanced-routing/cafe-routes.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
name: cafe
spec:
parentRefs:
- name: gateway
namespace: nginx-gateway
sectionName: http
hostnames:
- "cafe.example.com"
rules:
- backendRefs:
- name: main
port: 80
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
name: coffee
spec:
Expand All @@ -30,14 +14,24 @@ spec:
- path:
type: PathPrefix
value: /coffee
method: POST
backendRefs:
- name: coffee-v1-svc
port: 80
- matches:
- path:
type: PathPrefix
value: /coffee
headers:
- name: X-Demo-Header # header names are case-insensitive
value: Demo-X1 # header values are case-sensitive
- name: version
value: v1
value: v2
- path:
type: PathPrefix
value: /coffee
queryParams:
- name: TEST
value: v2
backendRefs:
- name: coffee
- name: coffee-v2-svc
port: 80
---
apiVersion: gateway.networking.k8s.io/v1alpha2
Expand All @@ -56,9 +50,15 @@ spec:
- path:
type: PathPrefix
value: /tea
queryParams:
- name: Great # query params and values are case-sensitive
value: Example
method: POST
backendRefs:
- name: tea-post-svc
port: 80
- matches:
- path:
type: PathPrefix
value: /tea
method: GET
backendRefs:
- name: tea
- name: tea-svc
port: 80
80 changes: 73 additions & 7 deletions examples/advanced-routing/cafe.yaml
Original file line number Diff line number Diff line change
@@ -1,35 +1,101 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee
name: coffee-v1
spec:
replicas: 1
selector:
matchLabels:
app: coffee
app: coffee-v1
template:
metadata:
labels:
app: coffee
app: coffee-v1
spec:
containers:
- name: coffee
- name: coffee-v1
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee
name: coffee-v1-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee
app: coffee-v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee-v2
spec:
replicas: 1
selector:
matchLabels:
app: coffee-v2
template:
metadata:
labels:
app: coffee-v2
spec:
containers:
- name: coffee-v2
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee-v2-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee-v2
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tea-post
spec:
replicas: 1
selector:
matchLabels:
app: tea-post
template:
metadata:
labels:
app: tea-post
spec:
containers:
- name: tea-post
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tea-post-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: tea-post
---
apiVersion: apps/v1
kind: Deployment
Expand All @@ -54,7 +120,7 @@ spec:
apiVersion: v1
kind: Service
metadata:
name: tea
name: tea-svc
spec:
ports:
- port: 80
Expand Down
Loading