- Building Microservices with Go
- Nic Jackson
- 520字
- 2021-07-15 17:28:04
Creating handlers
We will now finish off our examples here by showing how you can create a Handler rather than just using HandleFunc. We are going to split the code that performs the request validation for our helloworld endpoint and the code that returns the response out into separate handlers to illustrate how it is possible to chain handlers.
Example 1.8 chapter1/reading_writing_json_7.go:
31 type validationHandler struct {
32 next http.Handler
33 }
34
35 func newValidationHandler(next http.Handler) http.Handler {
36 return validationHandler{next: next}
37 }
The first thing we need to do when creating our own Handler is to define a struct field that will implement the methods in the Handlers interface. Since in this example, we are going to be chaining handlers together, the first handler, which is our validation handler, needs to have a reference to the next in the chain as it has the responsibility for calling ServeHTTP or returning a response.
For convenience, we have added a function that returns us a new handler; however, we could have just set the next field. This method, however, is better form as it makes our code a little easier to read and when we need to pass complex dependencies to the handler using a function to create, it keeps things a little neater:
37 func (h validationHandler) ServeHTTP(rw http.ResponseWriter, r
*http.Request) {
38 var request helloWorldRequest
39 decoder := json.NewDecoder(r.Body)
40
41 err := decoder.Decode(&request)
42 if err != nil {
43 http.Error(rw, "Bad request", http.StatusBadRequest)
44 return
45 }
46
47 h.next.ServeHTTP(rw, r)
48 }
The previous code block illustrates how we would implement the ServeHTTP method. The only interesting thing to note here is the statement that begins at line 44. If an error is returned from decoding the request, we write a 500 error to the response, the handler chain would stop here. Only when no error is returned do we call the next handler in the chain and we do this simply by invoking its ServeHTTP method. To pass the name decoded from the request, we are simply setting a variable:
53 type helloWorldHandler struct{}
54
55 func newHelloWorldHandler() http.Handler {
56 return helloWorldHandler{}
57 }
58
59 func (h helloWorldHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
60 response := helloWorldResponse{Message: "Hello " + name}
61
62 encoder := json.NewEncoder(rw)
63 encoder.Encode(response)
64 }
The helloWorldHandler type that writes the response does not look too different from when we were using a simple function. If you compare this to example 1.6, you will see that all we really have done is remove the request decoding.
Now the first thing I want to mention about this code is that it is purely to illustrate how you can do something, not that you should do something. In this simple case, splitting the request validation and response sending into two handlers adds a lot of needless complexity and it is not really making our code DRYer. The technique, however, is useful. When we examine authentication in a later chapter, you will see this pattern as it allows us to centralize our authentication logic and share it among handlers.
- AngularJS入門(mén)與進(jìn)階
- AngularJS Testing Cookbook
- Cocos2D-X權(quán)威指南(第2版)
- OpenCV實(shí)例精解
- 青少年美育趣味課堂:XMind思維導(dǎo)圖制作
- SEO智慧
- JavaScript動(dòng)態(tài)網(wǎng)頁(yè)開(kāi)發(fā)詳解
- TypeScript項(xiàng)目開(kāi)發(fā)實(shí)戰(zhàn)
- Quantum Computing and Blockchain in Business
- Node.js開(kāi)發(fā)指南
- Java Web應(yīng)用開(kāi)發(fā)給力起飛
- ASP.NET求職寶典
- Photoshop智能手機(jī)APP界面設(shè)計(jì)
- 實(shí)戰(zhàn)Python網(wǎng)絡(luò)爬蟲(chóng)
- Web前端測(cè)試與集成:Jasmine/Selenium/Protractor/Jenkins的最佳實(shí)踐