davidmrz
davidmrz

Reputation: 431

Testing NGINX configuration

I have a reverse proxy server with NGINX and I want to test its configuration automatically.

What I want to achieve in the end is to have a command that I can run, it starts the NGINX with the configuration, run several http requests, and then track and gather whether the right proxied server was called.

I've been thinking on setting up an environment with docker-compose and use curl/wget with the list of urls I want to test. The thing that I don't know is how to mock certain domains and track the forwarded requests.

Is there a tool to do that or should I write a server manually?

Upvotes: 3

Views: 4727

Answers (1)

davidmrz
davidmrz

Reputation: 431

After experimenting a bit I managed to create this solution.

Use Docker Compose, Wiremock and Newman. The idea is to setup NGINX proxying requests to Wiremock (where you can control if the request matched the right structure), then with Newman, you can run a Postman collection that automatically checks that the stubbed responses are the right ones.

Example

Create all these files in a folder, get the testing environment by running

docker-compose up -d nginx wiremock

and then, to run the test suite

docker-compose run --rm newman

It should print the results of the collection.

Files

docker-compose.yml

version: "3"

services:
  nginx:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./config:/etc/nginx

  wiremock:
    image: wiremock/wiremock:2.32.0
    command: [ "--port", "80", "--verbose" ]
    ports:
      - "8080:80"
    volumes:
      - ./wiremock:/home/wiremock
    networks:
      default:
        aliases:
          - backend-service-1
          - backend-service-2

  newman:
    image: postman/newman
    volumes:
      - ./newman:/etc/newman
    command: [ "run", "example.postman_collection.json" ]

config/nginx.conf

events {
  worker_connections  1024;
}

http {
    resolver 127.0.0.11; # docker internal resolver

    server {
        listen 80 default_server;

        location /some/path/ {
            proxy_set_header X-Forwarded-Host $host;
            proxy_pass http://backend-service-1/some/path;
        }

        location /other/path/ {
            proxy_set_header X-Forwarded-Host $host;
            proxy_pass http://backend-service-2/other/path;
        }
    }
}

wiremock/mappings/some-path.json

{
  "request": {
    "method": "GET",
    "url": "/some/path",
    "headers": {
      "Host": {
        "equalTo": "backend-service-1",
        "caseInsensitive": true
      }
    }
  },
  "response": {
    "status": 200,
    "body": "{\"host\": \"from-1\"}",
    "headers": {
      "Content-Type": "application/json"
    }
  }
}

wiremock/mappings/other-path.json

{
  "request": {
    "method": "GET",
    "url": "/other/path",
    "headers": {
      "Host": {
        "equalTo": "backend-service-2",
        "caseInsensitive": true
      }
    }
  },
  "response": {
    "status": 200,
    "body": "{\"host\": \"from-2\"}",
    "headers": {
      "Content-Type": "application/json"
    }
  }
}

newman/example.postman_collection.json

{
    "info": {
        "name": "example",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "item": [
        {
            "name": "some path",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "exec": [
                            "pm.test(\"request backend service 1\", function () {",
                            "    pm.response.to.have.status(200);",
                            "",
                            "    var jsonData = pm.response.json();",
                            "    pm.expect(jsonData.host).to.eql(\"from-1\");",
                            "});",
                            ""
                        ],
                        "type": "text/javascript"
                    }
                }
            ],
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "http://nginx/some/path/",
                    "protocol": "http",
                    "host": [
                        "nginx"
                    ],
                    "path": [
                        "some",
                        "path",
                        ""
                    ]
                }
            },
            "response": []
        },
        {
            "name": "other path",
            "event": [
                {
                    "listen": "test",
                    "script": {
                        "exec": [
                            "pm.test(\"request backend service 2\", function () {",
                            "    pm.response.to.have.status(200);",
                            "",
                            "    var jsonData = pm.response.json();",
                            "    pm.expect(jsonData.host).to.eql(\"from-2\");",
                            "});",
                            ""
                        ],
                        "type": "text/javascript"
                    }
                }
            ],
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "http://nginx/other/path/",
                    "protocol": "http",
                    "host": [
                        "nginx"
                    ],
                    "path": [
                        "other",
                        "path",
                        ""
                    ]
                }
            },
            "response": []
        }
    ]
}

Upvotes: 4

Related Questions