go - 停止HTTP调用并使用一系列处理程序返回错误;可能吗?

标签 go handler middleware

使用以下代码(摘自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))
}

关于go - 停止HTTP调用并使用一系列处理程序返回错误;可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62701908/

相关文章:

golang组合生成出错

android - 处理程序帖子在 Kotlin Android 中不起作用

java - 致命异常 : Timer-0 java. lang.NullPointerException

android延迟使用处理程序

meteor iron-router 并获取 accounts-entry 包的所有路由的名称

php - 在 Laravel 5 中缓存整个 HTML 响应

python - 如何在没有 sudo 的情况下发送自定义 'TCP' 数据包 - 没有三向握手

go - 是否可以使用bufio.Writer进行使用/写入?

express - 为什么 Apollo Server 不是 Express 的中间件,而是接受 Express 作为中间件的服务器?

json - 动态 JSON 结构,API 结果 golang