go - 如何在 Revel Controller 中获取 http.ResponseWriter 和 http.Request

标签 go revel

我正在尝试实现一个 oauth 服务器,我正在使用的包需要完整的 http.ResponseWriter 和 http.Request 类型。

c.Response 不包含 http.ResponseWriter 包含的所有方法,并且 c.Request 给出错误类型不兼容。

如何在 Revel Controller 中获取 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 中实际得到了什么值得使用如此重的抽象层,如果它真的那么有值(value),你可能想问另一个方向的问题,比如如何可能会使 OauthSrv 在 Revel 的定制生态系统中工作。

将 Revel Controller 用作 ResponseWriter

要成为 http.ResponseWriter,它只需要有 these methods .

标题

您需要一个名为 Header() 的方法,它返回一个 http.Header,您可以从任何 map[string][]string< 构建它。 Revel 提供类似的功能,但通过多个抽象层。你需要解开它们:

  1. c.Response 是一个 *Response,因此它有一个名为 Out 的字段,其中包含一个 OutResponse
  2. 一个 OutResponse 有一个 Header() 方法——但它不返回一个 http.Header。相反,它返回一个 *RevelHeader
  3. *RevelHeader 有一个 GetAll(key string) []string 方法——这与内置的 map 已经提供的 API 非常相似 类型,但并不完全相同。因此,每次调用Header()时,您都需要将返回值复制到新映射中,以充分满足函数签名要求。
  4. 此外,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)
}

写入和WriteHeader

您将使用类似的反模式来公开 rrw.Write([]byte) (int, error) 以便它调用 c.Response.Out.Write(data []byte) (int, error)rrw.WriteHeader(int) error 以便它调用 c.Response.WriteHeader(int, string) .根据认为适合框架的内容,错误 panic 或静默失败,因为它们的 API 不期望可以处理 WriteHeader 错误。

从 Revel 获取 http.Request

不幸的是,http.Request 类型是一个结构,所以您不能只模拟它。您基本上有两个选择:使用您能够访问的所有属性的 net/http 包重建它,或者希望您拥有的 *revel.Request 是 secret 的引擎盖下的 http.Request。在后一种情况下,您可以使用类型断言:

revelReq, ok := c.Request.In.(*revel.GoRequest)
if !ok {
  // handle this somehow
}
r := revelReq.Original

关于go - 如何在 Revel Controller 中获取 http.ResponseWriter 和 http.Request,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55069725/

相关文章:

google-app-engine - Go Appengine 托管 VM 问题 : unknown flag -trimpath

go - 如何在 revel Controller 中添加新字段

使用 IntelliJ 进行调试

go - revel 调试 - 如何

go - 解码base64并将其编码为十六进制

go - 创建通用函数以从 map 中提取值

function - Go语言中如何调用另一个函数内的函数?

sql - 戈朗 pq : syntax error when executing sql

if-statement - golang 中的复杂条件语句

json - 在 revel 中解析 json 日期时间