http - 调用堆栈上的错误处理-HTTP请求处理程序

标签 http go

在下面的代码中:

func (p *ProductHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // handle the request for a list of products
    if r.Method == http.MethodGet {
        p.getProductHandler(w, r)
        return
    }

    if r.Method == http.MethodPost {
        p.addProductHandler(w, r)
        return
    }

    if r.Method == http.MethodPut {
        id := findID(w, r)
        p.updateProductHandler(id, w, r)
        return
    }
    // catch all
    // if no method is satisfied return an error
    w.WriteHeader(http.StatusMethodNotAllowed)
}

// getProducts returns the products from the data store
func (p *ProductHandler) getProductHandler(w http.ResponseWriter, r *http.Request) {
    p.l.Println("Handle GET Products")

    // fetch the products from the datastore
    productList := data.GetProducts()

    // serialize the list to JSON
    err := productList.WriteJSON(w)
    if err != nil {
        http.Error(w, "Unable to marshal json", http.StatusInternalServerError)
        return
    }
}

func (p *ProductHandler) addProductHandler(w http.ResponseWriter, r *http.Request) {
    p.l.Println("Handle POST products")

    // Read the item from the incoming request
    productItem := &data.Product{}

    err := productItem.ReadJSON(r.Body)
    if err != nil {
        http.Error(w, "Unable to unmarshal JSON", http.StatusBadRequest)
        return
    }

    p.l.Printf("Product item: %#v\n", productItem)
    data.AddProductItem(productItem)
}

func (p *ProductHandler) updateProductHandler(id int, w http.ResponseWriter, r *http.Request) {
    // whatever
    return
}

func findID(w http.ResponseWriter, r *http.Request) int {
    // expect the id in the URI
    dfa := regexp.MustCompile(`/([0-9]+)`)
    matches := dfa.FindAllStringSubmatch(r.URL.Path, -1) // returns [][]string
    if len(matches) != 1 {
        http.Error(w, "Invalid URI", http.StatusBadRequest)
        return
    }
    if len(matches[0]) != 2 {
        http.Error(w, "Invlaid URI", http.StatusBadRequest)
        return
    }

    idString := matches[0][1]
    id, err := strconv.Atoi(idString)
    if err != nil {
        http.Error(w, "Invlaid URI", http.StatusBadRequest)
        return
    }
    return id
}

发生错误时,我们在处理http.Error()POST以及GET的处理程序中使用return
但是对于PUT请求,调用堆栈堆栈是ServeHTTP-> findID(),然后是ServeHTTP()-> updateProductHandler()findID()中需要进行错误处理,但由于findID()返回int,因此无法立即返回。

对调用堆栈执行错误处理的设计模式是什么?使用github.com/pkg/errors包装错误....

最佳答案

func (p *ProductHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // handle the request for a list of products
    if r.Method == http.MethodGet {
        p.getProductHandler(w, r)
        return
    }

    if r.Method == http.MethodPost {
        p.addProductHandler(w, r)
        return
    }

    if r.Method == http.MethodPut {
        id, err := findID(r.URL.Path)
        if err == nil {
            p.updateProductHandler(id, w, r)
        } else {
            http.Error(w, err.Error(), http.StatusBadRequest)
        }
        return
    }
    // catch all
    // if no method is satisfied return an error
    w.WriteHeader(http.StatusMethodNotAllowed)
    w.Header().Add("Allow", "GET, POST, PUT")
}

func findID(path string) (int, error) {
    // expect the id in the URI
    dfa := regexp.MustCompile(`/([0-9]+)`)
    matches := dfa.FindAllStringSubmatch(path, -1) // returns [][]string
    if len(matches) != 1 {
        return 0, fmt.Errorf("Invalid URI %s", path)
    }
    if len(matches[0]) != 2 {
        return 0, fmt.Errorf("Invalid URI %s", path)
    }

    idString := matches[0][1]
    id, err := strconv.Atoi(idString)
    if err != nil {
        return 0, fmt.Errorf("Invalid URI %s", path)
    }
    return id, nil
}

关于http - 调用堆栈上的错误处理-HTTP请求处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62441777/

相关文章:

scala - 使用 Dispatch 执行简单的 HTTP GET

node.js - 如何在 node.js 程序中查看整个请求和响应对象?

amazon-web-services - 使用 Golang 从 Lambda 调用 AppSync Mutation

pointers - 调用结构函数给出 "cannot refer to unexported field or method"

javascript - 为什么服务器回调会被多次触发

apache - 让 Apache 将 http 请求路由到 IIS

powershell - 通过 Docker API 在运行的容器中执行 powershell 命令

go - 将 map 初始化为 Go 结构中的字段

http - 如何使用Rcords向队列传递参数

http - 如何倒带 io.ReadCloser