gpt4 book ai didi

go - 在 handlefunc 之外安全终止请求

转载 作者:数据小太阳 更新时间:2023-10-29 03:07:16 27 4
gpt4 key购买 nike

如何在不在 handlefunc 中显式返回的情况下安全地终止调度程序 (handlefunc) 之外的请求?在下面的代码中,我最终在响应中同时看到“Bad request”和“Not found”,但我希望 f() 中止请求——这样我就不必用错误检查和返回。

package main

import (
"net/http"
)

func f(w http.ResponseWriter, r *http.Request, k string) string{
if v, ok := r.Form[k]; !ok{
http.Error(w, "Bad request", http.StatusBadRequest)
return ""
}else{
return v[0]
}
}

func main(){
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
foo := f(w, r, "foo") //make sure foo is passed, if not abort with "bad request" without requiring an explicit return here
bar := f(w, r, "bar") //make sure bar is passed, if not abort with "bad request" without requiring an explicit return here
//lookup in db...
//abort with a 404 if not found in db
http.NotFound(w, r)
})

http.ListenAndServe(":6000", nil)
}

以上是重构以下内容的尝试:

func main(){
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
if foo,ok:=r.Form["foo"];!ok{
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
if bar,ok:=r.Form["bar"];!ok{
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
//lookup in db...
//abort with a 404 if not found in db
http.NotFound(w, r)
})

http.ListenAndServe(":6000", nil)
}

最佳答案

我不认为尝试从一个函数中中止是你想要在这里做的。相反,减少验证的重复性。您可以使用 func Require(form url.Values, required ...string) error 编写类似 package validate 的代码,并且在您的处理程序中,if err : = validate.Require(r.Form, "foo", "bar");错误!= nil { ... }

或者您可以做一个更通用的验证器:也许将字段名称的 map 与验证类型(数字、字符串等)相结合,然后返回另一个 map nil 如果没有错误,{"fieldName": error} 否则。

Redditors talked some about this还有一个写了a library that uses struct tags to validate . new form rendering/validation toolkit 中还有另一个基于结构的验证实现. (我都没有尝试过。)Redditors 提出了一个棘手的问题,即当您的应用程序变得更加复杂时,在获得“框架”之前您可以抽象验证多少,而我没有一个简单的答案。


有些情况下确实会发生意外,服务器只能向用户提供不透明的“500 Internal Server Error”响应,但问题在您的 HandlerFunc 的深处显现。典型的例子是像 nil 指针取消引用这样的编程错误。 The advice from the Go team是在“错误不可恢复”时使用panic。 (像 negroni.Recovery 这样的工具可以帮助记录 panic 等)

不必要的 panic 是蹩脚的,因为:

  • panic 更容易完全忘记必要的错误处理,因为它暗示事情可以panic显式 他们可以犯错
  • panic/recover 错误处理代码丑陋且难以维护
  • panic 引入与标准 err 返回的不一致
  • panic使用堆栈展开,这比正常的控制流慢得多

我做了一个快速的 grep 并且基本上所有对标准库和其他官方存储库中的 panic 的调用都是为了捕获编程/内部错误,而不是在意外的外部崩溃输入错误或 I/O 错误等情况。诸如未找到文件/对象或无效用户输入之类的事情通常可以比通过崩溃请求更优雅地处理(至少有可能返回特定错误),并且它们并不是真正出乎意料(这是互联网;你会得到无效的输入和对不存在的事物的请求)。所以 panic 不是正常的请求中止——它是为了当“不可能发生”的事情发生并且请求无法继续时崩溃。


同样,在这里,我将在处理程序函数中使用标准的 if block 处理无效输入,但重新安排您的验证,以便每个必需的参数不需要大量代码。

关于go - 在 handlefunc 之外安全终止请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26867307/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com