duanou1904 2019-03-08 19:25
浏览 33
已采纳

如何在Revel控制器中获取http.ResponseWriter和http.Request

I am trying to implement an oauth server and the package I am using needs the complete http.ResponseWriter and http.Request types.

c.Response does not contain all the methods that http.ResponseWriter does and c.Request gives error incompatible type.

How do I get http.ResponseWriter and http.Request in a Revel controller?

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)
    }
}
  • 写回答

1条回答 默认 最新

  • dsjgk330337 2019-03-08 20:37
    关注

    Warning

    I am generally not fond of frameworks like Revel in Go, for reasons that I hope demonstrate themselves on this page. My first recommendation would be that you examine closely what you are actually getting out of Revel that merits the use of such a heavy abstraction layer, and if it's really that valuable, you may want to ask questions going in the other direction, such as how one might make OauthSrv work within Revel's customized ecosystem.

    Using a Revel controller as a ResponseWriter

    For something to be an http.ResponseWriter, it just needs to have these methods.

    Header

    You need a method named Header() that returns an http.Header, which you can build out of any map[string][]string. Revel provides similar functionality, but through several layers of abstraction. You will need to unravel them:

    1. c.Response is a *Response, so it has a field named Out containing an OutResponse.
    2. An OutResponse has a Header() method—but it doesn't return an http.Header. Instead, it returns a *RevelHeader.
    3. A *RevelHeader has a GetAll(key string) []string method—which is very similar to the API already provided by the built-in map type, but isn't exactly the same. So, you will need to copy the returned values into a new map every time Header() is called, in order to fully satisfy the function signature requirements.
    4. Also, GetAll() requires you to know the key name you are interested in, and *RevelHeader on its own does not provide a way to look up which keys are available. For now we can rely on the fact that the current implementation only has one field, a ServerHeader that does provide a GetKeys() []string method.

    Putting all this together, we can build our Header method:

    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 and WriteHeader

    You would use similar anti-patterns to expose rrw.Write([]byte) (int, error) so that it calls through to c.Response.Out.Write(data []byte) (int, error), and rrw.WriteHeader(int) error so that it calls c.Response.WriteHeader(int, string). Depending on what is considered appropriate for the framework, either panic on errors or fail silently, since their API doesn't expect WriteHeader errors to be handle-able.

    Getting an http.Request from Revel

    Unfortunately, the http.Request type is a struct, so you can't just simulate it. You basically have two options: reconstruct it using the net/http package from all the properties you are able to access, or hope that the *revel.Request you have is secretly an http.Request under the hood. In the latter case, you can use a type assertion:

    revelReq, ok := c.Request.In.(*revel.GoRequest)
    if !ok {
      // handle this somehow
    }
    r := revelReq.Original
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog