如何在 Revel 控制器中获取 http.ResponseWriter 和 http.Request
How to get http.ResponseWriter and http.Request in Revel controller
我正在尝试实现一个 oauth 服务器,我使用的包需要完整的 http.ResponseWriter 和 http.Request 类型。
c.Response 不包含 http.ResponseWriter 包含的所有方法,并且 c.Request 给出错误类型不兼容。
如何在 Revel 控制器中获得 http.ResponseWriter 和 http.Request?
type client struct {
ClientId string
ClientSecret string
}
type App struct {
*revel.Controller
}
func (c App) TokenRequest() {
r := c.Request
w := c.Response
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
var cli client
err = json.Unmarshal(body, &cli)
if err != nil {
panic(err)
}
log.Println(cli.ClientId)
err = OauthSrv.HandleTokenRequest(w, r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
警告
我通常不喜欢 Revel in Go 之类的框架,原因我希望在此页面上展示。我的第一个建议是你仔细检查你从 Revel 中实际得到了什么值得使用如此重的抽象层,如果它真的那么有价值,你可能想问另一个方向的问题,比如如何可能会使 OauthSrv
在 Revel 的定制生态系统中工作。
将 Revel 控制器用作 ResponseWriter
要成为 http.ResponseWriter
,它只需要 these methods。
页眉
您需要一个名为 Header()
的方法,它 return 是一个 http.Header
,您可以从任何 map[string][]string
构建它。 Revel 提供类似的功能,但通过多个抽象层。您需要解开它们:
c.Response
是一个 *Response
,因此它有一个名为 Out
的字段,其中包含一个 OutResponse
.
OutResponse
有一个 Header()
方法——但 return 没有 http.Header
。相反,它 return 是 *RevelHeader
。
- A
*RevelHeader
有一个 GetAll(key string) []string
方法——这与内置 map
类型已经提供的 API 非常相似,但不完全相同相同。因此,每次调用 Header()
时,您都需要将 returned 值复制到新映射中,以完全满足函数签名要求。
- 此外,
GetAll()
要求您知道您感兴趣的键名,*RevelHeader
本身不提供查找可用键的方法。 目前我们可以依赖这样一个事实,即the current implementation只有一个字段,一个ServerHeader
,确实提供了一个GetKeys() []string
方法。
将所有这些放在一起,我们可以构建我们的 Header
方法:
func (rrw RevelResponseWrapper) Header() http.Header {
revelHeader := rrw.Response.Out.Header()
keys := revelHeader.Server.GetKeys()
headerMap := make(map[string][]string)
for _, key := range keys {
headerMap[key] = revelHeader.GetAll(key)
}
return http.Header(headerMap)
}
Write 和 WriteHeader
您将使用类似的反模式公开 rrw.Write([]byte) (int, error)
,以便它调用 c.Response.Out.Write(data []byte) (int, error)
,并使用 rrw.WriteHeader(int) error
,以便它调用 c.Response.WriteHeader(int, string)
。根据认为适合框架的内容,错误恐慌或静默失败,因为他们的 API 不期望 WriteHeader
错误是可处理的。
从 Revel
获得 http.Request
不幸的是,http.Request
类型是一个结构,因此您不能只模拟它。您基本上有两个选择:使用您能够访问的所有属性的 net/http
包重建它,或者希望您拥有的 *revel.Request
是秘密的 http.Request
。在后一种情况下,您可以使用类型断言:
revelReq, ok := c.Request.In.(*revel.GoRequest)
if !ok {
// handle this somehow
}
r := revelReq.Original
我正在尝试实现一个 oauth 服务器,我使用的包需要完整的 http.ResponseWriter 和 http.Request 类型。
c.Response 不包含 http.ResponseWriter 包含的所有方法,并且 c.Request 给出错误类型不兼容。
如何在 Revel 控制器中获得 http.ResponseWriter 和 http.Request?
type client struct {
ClientId string
ClientSecret string
}
type App struct {
*revel.Controller
}
func (c App) TokenRequest() {
r := c.Request
w := c.Response
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
log.Println(string(body))
var cli client
err = json.Unmarshal(body, &cli)
if err != nil {
panic(err)
}
log.Println(cli.ClientId)
err = OauthSrv.HandleTokenRequest(w, r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
警告
我通常不喜欢 Revel in Go 之类的框架,原因我希望在此页面上展示。我的第一个建议是你仔细检查你从 Revel 中实际得到了什么值得使用如此重的抽象层,如果它真的那么有价值,你可能想问另一个方向的问题,比如如何可能会使 OauthSrv
在 Revel 的定制生态系统中工作。
将 Revel 控制器用作 ResponseWriter
要成为 http.ResponseWriter
,它只需要 these methods。
页眉
您需要一个名为 Header()
的方法,它 return 是一个 http.Header
,您可以从任何 map[string][]string
构建它。 Revel 提供类似的功能,但通过多个抽象层。您需要解开它们:
c.Response
是一个*Response
,因此它有一个名为Out
的字段,其中包含一个OutResponse
.OutResponse
有一个Header()
方法——但 return 没有http.Header
。相反,它 return 是*RevelHeader
。- A
*RevelHeader
有一个GetAll(key string) []string
方法——这与内置map
类型已经提供的 API 非常相似,但不完全相同相同。因此,每次调用Header()
时,您都需要将 returned 值复制到新映射中,以完全满足函数签名要求。 - 此外,
GetAll()
要求您知道您感兴趣的键名,*RevelHeader
本身不提供查找可用键的方法。 目前我们可以依赖这样一个事实,即the current implementation只有一个字段,一个ServerHeader
,确实提供了一个GetKeys() []string
方法。
将所有这些放在一起,我们可以构建我们的 Header
方法:
func (rrw RevelResponseWrapper) Header() http.Header {
revelHeader := rrw.Response.Out.Header()
keys := revelHeader.Server.GetKeys()
headerMap := make(map[string][]string)
for _, key := range keys {
headerMap[key] = revelHeader.GetAll(key)
}
return http.Header(headerMap)
}
Write 和 WriteHeader
您将使用类似的反模式公开 rrw.Write([]byte) (int, error)
,以便它调用 c.Response.Out.Write(data []byte) (int, error)
,并使用 rrw.WriteHeader(int) error
,以便它调用 c.Response.WriteHeader(int, string)
。根据认为适合框架的内容,错误恐慌或静默失败,因为他们的 API 不期望 WriteHeader
错误是可处理的。
从 Revel
获得 http.Request不幸的是,http.Request
类型是一个结构,因此您不能只模拟它。您基本上有两个选择:使用您能够访问的所有属性的 net/http
包重建它,或者希望您拥有的 *revel.Request
是秘密的 http.Request
。在后一种情况下,您可以使用类型断言:
revelReq, ok := c.Request.In.(*revel.GoRequest)
if !ok {
// handle this somehow
}
r := revelReq.Original