This is a creation in Article, where the information may have evolved or changed.
Go Language Classic library usage analysis, not to be continued, welcome to sweep code attention flysnow_org
to the public number or website http://www.flysnow.org/, the first time to see the following series. If you feel helpful, share it with your friends and thank you for your support.
When we write a Web service-side program, we may be able to do some or all of the HTTP request unified processing, such as we record each access request, the submitted form form mapping, and so on, to achieve these purposes, it is more elegant approach is the HTTP middleware.
Middleware, as the name implies, is emphasized in the middle, he is a business unrelated, in the normal business handler processing before and after the independent logic processing fragments. The general invocation order is as follows:
1 |
Servemux routing distribution, calling middleware 1-> calling middleware 2......-> calling real business processing logic |
Because the middleware is very independent, it can be removed when we do not use it, when needed, plus, does not modify the real business Processing logic code, it is very simple and convenient.
Here I choose Gorilla handlers this middleware library demonstrates how to use and define a middleware, which is mainly about the use of gorilla handlers, the next one will talk about the implementation of each middleware in gorilla handlers principle.
Installation
Gorilla handlers is a very simple, but very representative middleware library, so take him to analyze, easier to understand handler middleware. Before we use it, we need to install it and the middleware library is already hosted on GitHub, so we can use go get directly.
1 |
$ go Get github.com/gorilla/handlers |
After installation, we use the following code in the code to import and use.
1 |
Import "Github.com/gorilla/handlers" |
Gorilla handlers provides several kinds of middleware in the form of functions, such as Combinedlogginghandler, Compresshandler, Contenttypehandler, Logginghandler, etc. Let's introduce them here.
Logginghandler
We should have used Nginx,nginx's access log, similar to the following:
1 |
[05/aug/2017:21:06:24 +0800] "Get/favicon.ico http/1.1" 200 11 |
From which we can see what resources are accessed, what protocols are used, the HTTP status returned, and the size of the request, this kind of log style, and Apache Common log format is very much like, Logginghandler middleware is to help us do this thing.
It can record the request log and output to an IO. In writer.
123456789101112131415161718 |
func main() {http. Handle ("/", Uselogginghandler (Handler ())) HTTP. Listenandserve (": 1234",Nil)} func handler() http. Handler {returnhttp. Handlerfunc (MyHandler)} func myhandler(rw http. Responsewriter, R *http. Request) {rw. Writeheader (http. Statusok) io. WriteString (RW,"Hello World")} func uselogginghandler(next http. Handler) http. Handler {returnHandlers. Logginghandler (OS. Stdout,next)} |
I'm here for IO. Writer is a os.stdout, which is the standard console output, so when we visit http://localhost:1234/
, we can see the output of the request log information printed by the console.
12 |
"get/http/1.1" "Get/favicon.ico http/1.1" 200 11 |
From handlers.LoggingHandler
the parameters of the function we can see that it accepts a handler and then returns a handler, which is actually a wrapper over the existing handler, which is the middleware.
The output parameter type here is io.Writer
, so we can output the file and so implement any type of the interface.
Go Language Classic library usage analysis, not to be continued, welcome to sweep code attention flysnow_org
to the public number or website http://www.flysnow.org/, the first time to see the following series. If you feel helpful, share it with your friends and thank you for your support.
Combinedlogginghandler
There is also a log format, the log format output of the log information more detailed, more comprehensive, such as the inclusion of UA and other information, this format is known as Apache Combined log format.
Combinedlogginghandler is to provide us with the output of a middleware of this format, using the same way as Logginghandler.
123 |
func Usecombinedlogginghandler (next http.) Handler)http. Handler {return handlers.combinedlogginghandler (OS. Stdout,next)} |
Look at the log information for this middleware output
1 |
"Get/favicon.ico http/1.1" "http://localhost:1234/" "mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) applewebkit/537.36 (khtml, like Gecko) chrome/60.0.3112.78 safari/537.36 " |
Ua+host, the log information is more comprehensive.
Compresshandler
This is a compressed response middleware that supports gzip and deflate compression. If the client's request header is included Accept-Encoding
, and the value is gzip or deflate, the middleware will compress the returned response, so it can reduce the size of the response, reduce the response time, and use Access is simple, here is a simple example.
123456789101112131415161718 |
func main() {http. Handle ("/gzip", Usecompresshandler (Handler ())) HTTP. Listenandserve (": 1234",Nil)} func handler() http. Handler {returnhttp. Handlerfunc (MyHandler)} func myhandler(rw http. Responsewriter, R *http. Request) {rw. Writeheader (http. Statusok) RW. Header (). Set ("Content-type","Text/plain") Io. WriteString (RW,"Hello World")} func usecompresshandler(next http. Handler) http. Handler {returnHandlers.compresshandler (Next)} |
It is especially important to note that the content type of the response we return is specifically specified, otherwise it will be automatically resolved to gzip, and it will be downloaded as a GZ file. Here I force the text type to be specified so that you can see what is returned Hello World
.
The middleware also has a function compresshandlerlevel can specify the level of compression, the level is gzip. The value between Bestspeed and Gzip.bestcompression, if you do not want to use the default compression level, you can use this function to specify.
Remember that Nginx can turn on gzip acceleration, which is almost the same implementation.
Contenttypehandler
This is also a very interesting middleware, his role is to handle only the supported content types, if not supported, then return 415 status code. The middleware is only valid for the Put,post,patch method, other methods are not processed, it is equivalent to not using this middleware.
123 |
func Usecontenttypehandler (next http.) Handler)http. Handler {return handlers. Contenttypehandler (Next,"application/x-www-form-urlencoded")} |
The last parameter is a mutable parameter, and we can specify multiple contexttype types that are supported by us and not supported by other types. If the content type of the request we submitted using the put, POST, and patch methods is not within the scope of the content type we support, a 415 error is returned.
Canonicalhost
This is a redirected middleware, he can redirect a request to another domain name, and will take the original request path and query.
123456789101112131415161718 |
func main() {http. Handle ("/flysnow", Usecanonicalhost (Handler ())) HTTP. Listenandserve (": 1234",Nil)} func handler() http. Handler {returnhttp. Handlerfunc (MyHandler)} func myhandler(rw http. Responsewriter, R *http. Request) {rw. Writeheader (http. Statusok) RW. Header (). Set ("Content-type","Text/plain") Io. WriteString (RW,"Hello World")} func usecanonicalhost(next http. Handler) http. Handler {returnHandlers. Canonicalhost ("http://www.flysnow.org/", HTTP. Statusfound) (Next)} |
The above example, when we enter the browser in the http://localhost:1234/flysnow
access, will automatically jump to http://www.flysnow.org/flysnow
.
Summary
Some of the other less commonly used in the middle of the same way, you can look at the document under test. Go HTTP middleware, a bit like the HTTP interceptor, through a layer of packaging, we can form a middleware processing chain, so that we deal with the universality of the problem we need to deal with, if the middleware does not want to remove, do not have to make any changes to the business code.
The demo in the example, is a URL corresponding to a middleware processing, this is mainly for the demonstration aspect. What if we use a middleware relative to all of our requests? Certainly can't use the way in our example, because this will write a lot.
In this way, we can use the HTTP MUX route, because a route is also a handler, only with this route application middleware, you can intercept processing all requests.
The next article begins to share the implementation principles and source code Analysis of these common middleware.
Go Language Classic library usage analysis, not to be continued, welcome to sweep code attention flysnow_org
to the public number or website http://www.flysnow.org/, the first time to see the following series. If you feel helpful, share it with your friends and thank you for your support.