go - 使用一系列处理程序停止 HTTP 调用并返回错误;可能吗?
问题描述
使用以下代码(取自https://gist.github.com/miku/293f253b706c4de1b75c):
package main
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
)
type Payload struct {
Name string
Location string
}
func readSecond(w http.ResponseWriter, r *http.Request) {
log.Println("entering readSecond")
// r.Body is a io.ReadCloser, that's all we know
b, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
// closing a NopCloser won't hurt anybody
defer r.Body.Close()
log.Printf("request body: %s", string(b))
}
func readFirst(w http.ResponseWriter, r *http.Request) {
log.Println("entering readFirst")
// temporary buffer
b := bytes.NewBuffer(make([]byte, 0))
// TeeReader returns a Reader that writes to b what it reads from r.Body.
reader := io.TeeReader(r.Body, b)
// some business logic
var payload Payload
if err := json.NewDecoder(reader).Decode(&payload); err != nil {
log.Fatal(err)
}
// we are done with body
defer r.Body.Close()
log.Printf("deserialized payload from body: %v", payload)
// NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r.
r.Body = ioutil.NopCloser(b)
}
func handler(w http.ResponseWriter, r *http.Request) {
readFirst(w, r)
readSecond(w, r)
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
有没有办法阻止 readSecond()
(第二个处理程序)运行?
例子:
如果payload == ""
我想退出 HTTP 调用并返回错误。
有没有办法用这段代码做到这一点?
我知道我可以使用嵌套中间件来做到这一点。但是像这样的处理程序呢?
解决方案
使用方法和接收器有助于更好地控制错误。您不能在 http 的处理程序中定期返回错误。
package main
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
)
type Payload struct {
Name string
Location string
}
type Handle struct {
err error
}
func (h *Handle) readSecond(w http.ResponseWriter, r *http.Request) {
log.Println("entering readSecond")
// r.Body is a io.ReadCloser, that's all we know
b, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
// closing a NopCloser won't hurt anybody
defer r.Body.Close()
log.Printf("request body: %s", string(b))
}
func (h *Handle) readFirst(w http.ResponseWriter, r *http.Request) {
log.Println("entering readFirst")
h.err = nil
// temporary buffer
b := bytes.NewBuffer(make([]byte, 0))
// TeeReader returns a Reader that writes to b what it reads from r.Body.
reader := io.TeeReader(r.Body, b)
// some business logic
var payload Payload
if err := json.NewDecoder(reader).Decode(&payload); err != nil {
// log.Fatal("read first", err)
h.err = err
w.Write([]byte(err.Error()))
}
// we are done with body
defer r.Body.Close()
log.Printf("deserialized payload from body: %v", payload)
// NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r.
r.Body = ioutil.NopCloser(b)
}
func handler(w http.ResponseWriter, r *http.Request) {
var handle Handle
handle.readFirst(w, r)
if handle.err == nil {
handle.readSecond(w, r)
}
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
推荐阅读
- python - 使用 flask_sqlalchemy 创建多对多关系
- swiftui - SwiftUI DatePicker 没有像预期的那样
- javascript - JS:for循环中的当前节点
- excel - 具有列表框值过滤器的列表框标题
- redirect - 从无后缀 URL 到 *.html URL 的永久 301 重定向
- python - Celery/Django/Redis 相同的任务被多次执行
- pandas - pandas astype 转换不适用于 iloc[:.list]
- reactjs - 如何将一些道具传递给 reactjs 中的其他组件?
- postgresql - 如何计算postgres模式中每个表上每列的值的出现
- javascript - MomentJS,动态当前年份