Menu
Introduction
Automatic import for version 1.0.4-2.el72. Golang New - 3 examples found. These are the top rated real world Golang examples of github.com/golang-commonmark/markdown.New extracted from open source projects. Process markdown into manpages /mirror/download.fedora.redhat.com/pub/fedora/epel/7/x8664/Packages/g/golang-github-cpuguy83-go-md2man-1.0.4-5.el7.x8664.rpm.
I was struggling to find a good (or just simple) reverse proxy solution written in Go, so I decided to take what I had learnt from a work colleague of mine and put together a simple example for others to build upon if they needed a quick reference point. 1pass download.
In this example I have an origin server written in Python (for no other reason than to have a clearer distinction between the proxy and the origin) and which supports the endpoints
/
, /foo
and /bar/*
(where the wildcard glob means we support multiple variants of that, such as /bar/baz
).Each origin handler will print the http request headers, followed by sending a response body that correlates to the handler name (so for example, the
FooHandler
class will respond with FOO!
, while the BarHandler
class will response with BAR!
).But before we get into it.. time for some self-promotion ?
Example Python Origin Code
Here is our Python code using the Tornado web framework.
Example Golang Proxy Code
There are two versions of the code, a simple version and a more advanced version that aims to handle more specific use cases.
The simple version uses just the Go standard library, whereas the advanced version uses the standard library as well as a few a few external packages such as httprouter and logrus for routing and logging respectively.
One difference between them that’s worth mentioning is that in the simple version we use the
httputil.ReverseProxy
http handler directly, whereas in the advanced version we use httputil.NewSingleHostReverseProxy
to construct this for us. The advanced version also tries to normalise the paths by stripping trailing slashes and joining them up with the base path (if there was one, although ironically I don’t define one in the advanced example).Simple
Advanced
Demonstration
In order to run this example you should follow these instructions:
- run the tornado application (e.g.
python tornado-origin.py
) - run the go application (e.g.
go run main.go
) - make http requests (shown below)
You should see output from the Python server that looks something like this:
Golang Markdown Editor
Explanation
OK, so let’s step through the
main
function of the advanced example code to see what’s going on.The core reverse proxy code and its concepts are effectively the same between the advanced and simple versions.
First we set up our basic logging configuration:
Next we create a new httprouter instance, we define the origin host (
http://localhost:9000/
) and the ‘pattern’ we want httprouter to look out for (/*catchall
, which is a special syntax that represents a catchall wildcard/glob):Next we create a new reverse proxy instance, passing it the origin host (
http://localhost:9000/
):Followed by configuring the ‘director’ for the reverse proxy. The director is simply a function that modifies the received incoming request, while the response from the origin is copied back to the original client.
In this example, we attach a few common proxy related headers to the incoming request and then modify its Scheme/Host to reflect the origin we wish to proxy it onto.
Next, we change the request path to the origin. What we do is ensure the path we request from the origin is whatever the base origin path is + the requested path (i.e. not just directing the request to the root/entrypoint of the origin).
In our example, our origin’s path is just
/
whereas the client will be requesting things like /foo
and /bar/baz
, so these would be appended to the origin’s defined /
. But we also make sure that when joining the origin’s path with the incoming request path, that we avoid double slashes in the middle.Lastly, we ensure that any trailing slash is removed as well:
Finally, we setup the handler for the
/*catchall
httprouter path. In this case we don’t do anything other than call the reverse proxy’s ServeHTTP
method and pass it the original ResponseWriter
and http Request
. We then kick start the httprouter using ListenAndServe
:Among the best mixologists in the world is Colin Peter Field. Ranked as one of the best bartenders in the world by Forbes and Travel + Leisure magazines, Field is a successful mixologist who managed to master the art behind cocktail, drinks, and everything alcohol. Among the best mixologists in the world is Colin Peter Field. Ranked as one of the best bartenders in the world by Forbes and Travel + Leisure magazines, Field is a successful mixologist who managed to master the art behind cocktail, drinks, and everything.
One of the names that always ring a bell in the world of mixology is Israel Diaz @israwolfdiaz. With over 18 years of experience in the industry, Diaz finally opened his bar, the Alquimista Cocktail Room, which features delectable dishes and handmade concoctions.
Handling Errors
In order to handle errors the reverse proxy needs to construct a new response object, which means if you wanted the error response you generate to have all the same response headers as were provided by the upstream service, then you’d have to programmatically add those to the new response object.
Let’s see how we can handle errors in the basic sense, just to get an idea for how the code looks. Now we don’t need to use another programming language to do this, we can do it all in Go (we could have done this earlier instead of using Python, but I wanted to highlight how you could use another language if you wanted).
Here we can see that our
httputil.ReverseProxy#ModifyResponse
function is hardcoded to return an error type, which then causes the httputil.ReverseProxy#ErrorHandler
function to be called.From there we use the
http.ResponseWriter
to create a new response. In this case we do nothing other than print the original error, but you could do pretty much anything you like at this point.Golang Markdown Renderer
Free 90 ball bingo caller. If you needed the original response object that came from the upstream then you’d need to make sure the error you returned from
ModifyResponse
was a custom error type so that you attach a field such as OriginalResponse
to it and thus assign it the original http.Response
that was available to you within ModifyResponse
.NGINX-Lite (not-really)
Below is an example that demonstrates using httpbin as our origin.
Specifically we use its
/anything
endpoint, which allows you to provide any value as the final path segment. So for example, /anything/foo
or /anything/beep
, both work with the httpbin.org
service.Now let’s elaborate on this example a little bit and ensure that our reverse proxy has a client timeout specified (see this article for details as to why you would want to do this).
We also use
gorilla/mux
as it supports utilising regular expression path matching (we could do this ourselves, but using a library in this case helps to keep the code we have to write down).One last thing you’ll notice is that we’re using a configuration object that allows us to configure override behaviour. For example, if our request includes a HTTP header of
X-BF-Testing
and its value is integralist
, then we’ll proxy the request to a different endpoint.You can do more complex things if necessary, but this gives you a good idea of how to replicate something like NGINX with very little code (obviously to replicate something like NGINX is waaay beyond the scope of this post) ?
Conclusion
That’s all there is to it.
Golang Markdown Server
You could also wrap the function passed to
router.Handle
in a middleware function so that you’re able to do extra processing. A common example of this is to authenticate the incoming request before it is proxied to the origin (meaning you can reject the request if necessary).