Proxying
• Mark Eschbach
After the disappointment of ningx requiring a commerical level again, I was wondering what it would take to build a transparent proxy myself. Lyft’s envoy sounds likes an interesting product, however the lack of operational documentation is a bit of a bummer. Effectively the end goals would:
- Dynamically reconfigurable, without any downtime
- Provide an edge which is zone and region aware.
- Performant
Seems as though the community has chosen C++ or Go for this. Probably smart, however this morning I’ll be writing in nodejs because I want to prove the concept. Definitely will not reach the same level of concurrence but in truth I don’t have a C10K.
The supproted intake protocols should include:
- HTTP/1.1
- HTTP/2
- Websocket
Yes, I know a Websocket is a regression in HTTP to a framed TCP protocol. However I think it’s awesome. My goals for this morning are:
- Intake HTTP/1.1 from multiple sites
- Translate to the appropriate target, including standard headers
- Add and remove HTTP/1.1 processes on the fly.
Persistance, the other protocols, etc. are all bonus material. My inital plan will be to build a proxy targeting a test service which returns true or false. First resource will just detect if the a request went through.
And the first challenge for the listening service: finding out which port it actually bound to. Bingo. Much easier than trying to read through the docks.
So my initial design of a series of processes which will come up will make testing initial very difficult. I’ve opted to suck everything into the testing file for speed of development. I ran into an issue of synchronizing on listening. Apparently NodeJS now properly supports promises natively, at least as of v7.2.0
. And then I forgot how to use native JS promises. Lucky for me MDN has a great reference.
After building out the initial test structure I have three conclusions: My inpexierence with the JS promises are a problem for speed of construction; the promises don’t propagate errors without a great deal of boiler plate; and they cumbersome compared to other promise libraries I’ve worked with. I think for the duration of this experiment I’ll be dropping back to q
.
Oh right, q
doesn’t easily lend itself to building on other NodeJS calling convetions. Once I dropped in chai-as-promised
things worked out well and the expected exception was reported.
The initial library I chose for the HTTP client apparently doesn’t POST
very well :-/. Time to go out and checkout nano
. Well, they seem to use it well but I’m not entirely sure how they do it. Looks like they use the ‘body’ property. Turns out request.body
no longer contains the raw underlying request body. The Express team recommends using something like. I feel like they had some decent parsers defaulted in the 3 series, however it escapes me right now. That may be because I typically used connect
for everything too. body-parser
it is!