Skip to content

Commit

Permalink
Updated message format and streamlined code
Browse files Browse the repository at this point in the history
  • Loading branch information
wshaddix committed Feb 27, 2018
1 parent 8ea3441 commit 2f7fe7e
Show file tree
Hide file tree
Showing 29 changed files with 188 additions and 779 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@

**1.0.1**

* added logging to the request handler so that it's obvious when traffic is coming into the http-nats-proxy
* added logging to the request handler so that it's obvious when traffic is coming into the http-nats-proxy


**1.0.2**

* now checking the state of the NATS connection to ensure it's in a `CONNECTED` state before trying to send messages.
* reduced the `PingInterval` of the NATS connection to help with reconnections when the NATS server becomes unavailable
* now logging when NATS connection events happen

**1.0.3**

* changing the format of the message that the proxy sends to microservices and the pipeline steps to make them more intuitive. Specifically changed `Cookies, ExtendedProperties, QueryParams, RequestHeaders` and `ResponseHeaders` from name/value collections to `Dictionary<string, object>` so they serialize into a more intuitive json string.
59 changes: 29 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,35 @@ When an http request is received, the http-nats-proxy will extract the headers,

```
{
"headers": [
{"key": '', "value": ''}.
{"key": '', "value": ''}
],
"cookies": [
{"key": '', "value": ''}.
{"key": '', "value": ''}
],
"queryParams": [
{"key": '', "value": ''}.
{"key": '', "value": ''}
],
"body": '',
"responseStatusCode": -1,
"response": '',
"errorMessage", ''
"requestHeaders": {
"key1": "value1",
"key2": "value2"
},
"cookies": {
"key1": "value1",
"key2": "value2"
},
"queryParams": {
"key1": "value1",
"key2": "value2"
},
"extendedProperties": { <--- can be set by microservices and pipeline steps
"key1": "value1",
"key2": "value2"
},
"responseHeaders": { <--- can be set by microservices and pipeline steps
"key1": "value1",
"key2": "value2"
},
"body": "",
"response": "", <--- can be set by microservices and pipeline steps
"responseStatusCode": -1, <--- can be set by microservices and pipeline steps
"shouldTerminateRequest": true|false, <--- can be set by microservices and pipeline steps
"response": "", <--- can be set by microservices and pipeline steps
"errorMessage", "" <--- can be set by microservices and pipeline steps
}
```

Each of the http request headers, cookies and query parameters will be represented as a key/value pair. The body will be represented as a string.

### 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:
Expand Down Expand Up @@ -106,7 +114,9 @@ cd src
docker-compose up
```

This will run the http-nats-proxy in a container alongside a NATS server and a test microservice. 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:
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/test/v1/customer
Expand All @@ -126,17 +136,6 @@ docker build -t http-nats-proxy .
```

## Debugging your microservices
It can be useful to have NATS and the http-nats-proxy running while you are coding and debugging your microservices. In order to assist with this scenario there is a docker compose file that will run NATS and the http-nats-proxy where you can test out your microservice easily. The steps to do this are:

1. From the `src` directory run
```
docker-compose -f docker-compose-nats-only.yml up
```

2. Code your microservice and have it connect to nats at `nats://localhost:4222`
3. Once your microservice is ready to test, send in http requests through CURL, Postman or whatever means you want to the http-nats-proxy at `http://localhost:5000`

## 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.
45 changes: 0 additions & 45 deletions src/AuthenticationPipelineStep/MessageHelper.cs

This file was deleted.

63 changes: 0 additions & 63 deletions src/AuthenticationPipelineStep/NatsMessage.cs

This file was deleted.

29 changes: 21 additions & 8 deletions src/AuthenticationPipelineStep/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using NATS.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AuthenticationPipelineStep
Expand All @@ -11,30 +14,35 @@ internal class Program
// we use a mre to keep the console application running while it's waiting on messages from NATS in the background
private static readonly ManualResetEvent ManualResetEvent = new ManualResetEvent(false);

private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};

private static IConnection _connection;

private static void EnsureAuthHeaderPresent(object sender, MsgHandlerEventArgs e)
{
// deserialize the NATS message
var msg = MessageHelper.GetNatsMessage(e.Message);
var msg = JsonConvert.DeserializeObject<JObject>(Encoding.UTF8.GetString(e.Message.Data));

// if the msg doesn't include an authentication header we need to return a redirect to the auth url
var authHeader = msg.RequestHeaders.FirstOrDefault(h => h.Key.Equals("Authorization"));
var authHeader = msg.SelectToken("requestHeaders.authorization");

if (null == authHeader.Value)
if (null == authHeader)
{
Console.WriteLine($"No Authorization header found. Returning a 301 redirect to http://google.com");
msg.ResponseStatusCode = 301;
msg.ResponseHeaders.Add(new KeyValuePair<string, string>("Location", "https://google.com"));
msg.ShouldTerminateRequest = true;
msg["responseStatusCode"] = 301;
msg["responseHeaders"]["Location"] = "https://google.com";
msg["shouldTerminateRequest"] = true;
}
else
{
Console.WriteLine($"Authorization header was already on the message so nothing to do.");
}

// send the NATS message back to the caller
_connection.Publish(e.Message.Reply, MessageHelper.PackageResponse(msg));
_connection.Publish(e.Message.Reply, PackageResponse(msg));
}

private static void Main(string[] args)
Expand All @@ -59,5 +67,10 @@ private static void Main(string[] args)
Console.WriteLine($"Authentication Pipeline Step Connected to NATS at: {natsUrl}\r\nWaiting for messages...");
ManualResetEvent.WaitOne();
}

private static byte[] PackageResponse(object data)
{
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data, SerializerSettings));
}
}
}
12 changes: 0 additions & 12 deletions src/LoggingMicroservice/.dockerignore

This file was deleted.

31 changes: 0 additions & 31 deletions src/LoggingMicroservice/Dockerfile

This file was deleted.

45 changes: 0 additions & 45 deletions src/LoggingMicroservice/MessageHelper.cs

This file was deleted.

Loading

0 comments on commit 2f7fe7e

Please sign in to comment.