How to write Go middleware

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. Writing go middleware looks pretty straightforward, but in some cases we may have some problems. Let's take a look at some examples. # # Read request All middleware in our example will receive an ' HTTP. Handler ' as a parameter, and returns an ' HTTP. Handler '. This makes it easy to link middleware together. All of our middleware will follow this basic pattern: "' gofunc X (H http. Handler) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {//Something here...//Here are some additional information H. Servehttp (W, R)})} "assumes that we want to redirect all requests to a trailing slash (for example, '/messages/'), which is equivalent to redirecting to their" non-trailing-slash "(such as '/messages '). We can write this: "' gofunc trailingslashredirect (H http. Handler) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {if r.url. Path! = "/" && R.url. Path[len (R.url. Path)-1] = = '/' {http. Redirect (W, R, R.url. Path[:len (R.url. Path)-1], HTTP. statusmovedpermanently) Return}h.servehttp (W, R)}} "is so simple. # # Modification Request Suppose we want to add a header message to the request, or modify it. ' HTTP. Handler ' documentation is as follows: > In addition to reading the principal, the handler should not modify the provided request. Go Label library in [Pass ' HTTP. The Request ' object is copied ' HTTP ' before the response chain. Request '] (https://golang.org/src/net/http/server.go#L1981), we should do the same. Suppose we want to set a ' Request-id ' header information for each request for internal tracking. Create a shallow copy of ' *request ',and modify the header before the agent. "' Gofunc RequestID (H http. Handler) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {r2: = new (http. Request) *r2 = *rr2. Header.set ("X-request-id", uuid. NewV4 (). String ()) h.servehttp (W, r2)})} ' # # Write response header information if you want to set the response header information, you can write them and then proxy the request. "' Gofunc Server (H http. Handler, servername string) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {W.header (). Set ("Server", ServerName) H.servehttp (W, R)})} ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This can be problematic if you do not want to expose the server header information for the internal software, or if you want to remove the head before sending a response to the client. To deal with this problem, I have to implement the ' Responsewriter ' interface myself. In most cases, we will proxy it to the potential ' responsewriter ', but if the user tries to write a response, we will secretly add the header information. "' Gotype serverwriter struct {w http. Responsewritername stringwroteheaders Bool}func (S *serverwriter) Header () http. Header {return S.w.header ()}func (S *serverwriter) writeheader (code int) http. Header {if S.wroteheader = = false {S.w.header (). Set ("Server", s.name) S.wroteheader = True}s.w.writeheader (code)}func (S *serVerwriter) Write (b []byte) (int, error) {if S.wroteheader = = false {//We hit this case if user never calls Writeheader (d Efault 200)//If the user never calls ' Writeheader ', we will encounter this situation. S.w.header (). Set ("Server", s.name) S.wroteheader = True}return S.w.write (b)} "to use it for our middleware, we will write:" ' gofunc Server (H http. Handler, servername string) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {SW: = &serverwriter{w:w,name:servername,}h.servehttp (SW, R)})} ' # # If the user never calls ' Write ' or ' writeheader '? if The user does not call the ' Write ' or ' writeheader ' method, such as an empty response with a status code of 200, or a response to an optional request, and none of our interception functions will be executed. So, given this situation, we should add at least one check after the ' servehttp ' call. "' Gofunc Server (H http. Handler, servername string) http. Handler {return HTTP. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {SW: = &serverwriter{w:w,name:servername,}h.servehttp (SW, R) If Sw.wroteheaders = = false {S.w.header (). Set ("Server", s.name) S.wroteheader = True}})} "# # Other ' Responsewriter ' interface Responsewriter interface only need to implement three methods. But in fact, it can also respond to other interfaces, such as ' HTTP. Pusher '. In addition, your middleware may accidentally disable HTTP/2 support, which is not good. "' go//Push implements the HTTP. Pusher interface.//Push implements HTTP. Pusher interface func (S *serverwriter) Push (target string, opts *http. Pushoptions) Error {if pusher, OK: = S.W. (http. Pusher); OK {return pusher. Push (target, opts)}return http. errnotsupported}//Flush implements the HTTP. Flusher interface.//Flush implements HTTP. Flusher interface func (S *serverwriter) Flush () {f, OK: = S.W. (http. Flusher) If OK {F.flush ()}} "# # That's how you good luck! What middleware are you writing, and how do they work?

Via:https://kev.inburke.com/kevin/how-to-write-go-middleware/

Author: Kevin Burke Translator: Sergeychang proofreading: Rxcai

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

802 reads ∙1 Likes
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.