An open API service indexing awesome lists of open source software.

https://github.com/wshaddix/http-nats-proxy

A proxy service that translates http requests to nats messages
https://github.com/wshaddix/http-nats-proxy

docker http-nats-proxy microservice nats nats-messaging nats-server natsio proxy-service reverse-proxy

Last synced: 2 months ago
JSON representation

A proxy service that translates http requests to nats messages

Awesome Lists containing this project

README

          

# http-nats-proxy

A proxy service that converts http requests to [NATS](https://nats.io) messages.

## Purpose

This proxy service is designed to be ran in a docker container and will translate all of your http based api calls (REST
endpoints). It will translate the http route to a [NATS](https://nats.io) message and will send the message as a request
into the NATS messaging system. Once a reply has been returned it is written back to the http response. The primary use
case for this service is when you have an ecosystem of microservices that communicate via NATS but you want http REST
api clients to be able to communicate to those services as a typical http REST api client.

## Features

### Routing

When an http request is received the http-nats-proxy will take the request path and replace every forward slash ('/')
with a period ('.'). It will then prefix that with the http verb that was used (get, put, post, delete, head, etc.).
Finally it will convert the entire string to lowercase. This becomes your NATS subject where the message will be sent.
For example, the http request of `GET http://localhost:5000/test/v1/customer?id=1234&show-history=true` will result in a
NATS message subject of `get.test.v1.customer`

### HTTP Request Format Translation

When an http request is received, the http-nats-proxy will extract the headers, cookies, query string parameters and the
body of the request and create a NATS message. The NATS message that goes into the messaging system will be a json
serialized object that has the following structure:

```
{
"cookies": {
"key1": "value1",
"key2": "value2"
},
"errorMessage", "", <--- can be set by microservices and pipeline steps
"extendedProperties": { <--- can be set by microservices and pipeline steps
"key1": "value1",
"key2": "value2"
},
"queryParams": {
"key1": "value1",
"key2": "value2"
},
"requestBody": "",
"requestHeaders": {
"key1": "value1",
"key2": "value2"
},
"responseBody": "", <--- can be set by microservices and pipeline steps
"responseHeaders": { <--- can be set by microservices and pipeline steps
"key1": "value1",
"key2": "value2"
},
"responseStatusCode": -1, <--- can be set by microservices and pipeline steps
"shouldTerminateRequest": true|false <--- can be set by microservices and pipeline steps
}
```

### Pipelines

Every http(s) request that comes into the http-nats-proxy can go through a series of steps before being delivered to the
final destination (your microservice). Those steps are defined in a yaml based configuration file and the location of
the file is passed to the https-nats-proxy via the `HTTP_NATS_PROXY_REQUEST_PIPELINE_CONFIG_FILE` environment variable.
Each step defined in the pipeline configuration file contains the following properties:

**subject:** The NATS subject name where the request will be delivered for this particular step in the pipeline. In
order to notify the http-nats-proxy to send the message to your microservice use `*` for the subject name.

**pattern:** Either `publish` or `request`, this tells the http-nats-proxy whether it should do a fire and forget
message exchange pattern or if it should use the request/reply pattern. If you are not going to change or cancel the
http request then you should use `publish`. If your pipeline step will potentially modify the request or cancel the
request you should use `request`

**direction:** Either `incoming, outgoing` or `both`. This tells the http-nats-proxy when to call your pipeline step.
`incoming` is when the message is inbound, `outgoing` is after the message has reached the end of the pipeline and the
response is being returned. `both` will call you pipeline step twice, once when the request is inbound and a second time
when the response is outbound.

**order:** A numeric value that is the order that your step should be called in relation to other steps in the pipeline

### Observers

There are times when you want to get a copy of the request/response message after it has completed running through all
of the pipeline steps. Examples of this would be when you wanted to log the request/response or capture metrics about
how long each request took to process, etc. In these cases, the metadata about the request is not available during the
execution of the pipeline steps. For these scenarios you can use Observers. Observers are notified via a NATS publish
message after all of the pipeline steps have executed and metadata has been stored for the request/response pair. It is
a "copy" of the final state of the http request.

#### Example pipeline-config.yaml file

```
steps:
- subject: trace.header
pattern: request
direction: incoming
order: 1

- subject: authentication
pattern: request
direction: incoming
order: 2

- subject: '*'
pattern: request
direction: incoming
order: 3
observers:
- subject: 'pipeline.logging'
- subject: 'pipeline.metrics'
```

## Configuration

All configuration of the http-nats-proxy is done via environment variables.

| Environment Variable | Default Value | Description |
| -------------------------------------------- | ------------------------------- | ------------------------------------------------------------ |
| HTTP_NATS_PROXY_HOST_PORT | 5000 | The port that the http-nats-proxy will listen for incoming http requests on |
| HTTP_NATS_PROXY_NAT_URL | nats://localhost:4222 | The NATS url where the http-nats-proxy will send the NATS message to |
| HTTP_NATS_PROXY_WAIT_TIMEOUT_SECONDS | 10 | The number of seconds that the http-nats-proxy will wait for a response from the microservice backend before it returns a Timeout Error to the http client |
| HTTP_NATS_PROXY_HEAD_STATUS_CODE | 200 | The http status code that will be used for a successful HEAD request |
| HTTP_NATS_PROXY_PUT_STATUS_CODE | 201 | The http status code that will be used for a successful PUT request |
| HTTP_NATS_PROXY_GET_STATUS_CODE | 200 | The http status code that will be used for a successful GET request |
| HTTP_NATS_PROXY_PATCH_STATUS_CODE | 201 | The http status code that will be used for a successful PATCH request |
| HTTP_NATS_PROXY_POST_STATUS_CODE | 201 | The http status code that will be used for a successful POST request |
| HTTP_NATS_PROXY_DELETE_STATUS_CODE | 204 | The http status code that will be used for a successful DELETE request |
| HTTP_NATS_PROXY_CONTENT_TYPE | application/json; charset=utf-8 | The http response Content-Type header value. This should be set to whatever messaging format your microservice api supports (xml, json, etc) |
| HTTP_NATS_PROXY_REQUEST_PIPELINE_CONFIG_FILE | | The full file path and name of the configuration file that specifies your request pipeline |
| LOGGING_LEVEL | Verbose | Verbose
Debug
Information
Warning
Error
Fatal |
| LOGGING_PROPERTIES | | A comma separated list of name/value pairs that will be set as properties on the Serilog log messages |

## Running the Demo

In order to see the http-nats-proxy in action along with a test microservice, logging and metrics you can run the docker
compose file in your environment.

```
cd src
docker-compose up
```

This will run the NATS server in a container.

Next start the project from Visual Studio and make sure that each project in the solution is set to run on startup (
multi-project start-up configuration). The http-nats-proxy will listen for http requests on port 5000 of your host
machine. You can then send http requests to the proxy and have them processed by the test microservice. The test
microservice that comes with this repo will respond to the following http routes:

```
GET http://localhost:5000/healthcheck
GET http://localhost:5000/customers?id=
```

Additionally, if configured for metrics, logging and tracing you will see the output of those microservices as well in
your terminal. This is for demo purposes only. There is a 1/2 second delay in the logging and metrics microservices just
to simulate work.

## Creating your own docker image

The http-nats-proxy has a `Dockerfile` where you can build your own docker images by running:

```
cd src
docker build -t http-nats-proxy .

```

## Responsibilities of your microservices

In order to control what gets returned from the http-nats-proxy, your microservice has to set the `response` property of
the NATS message that you receive when you subscribe to a NATS subject. You should return the *entire* NATS message. You
may optionally set the `responseStatusCode` and the `errorMessage` properties if an error occurs while you are
processing the message. The nats-http-proxy will honor the `responseStatusCode` if it is set and will also format and
return an error response if the `errorMessage` property has been set.