2012-10-12 01:44

Goor中带有Gorilla / rpc的JSON RPC请求


I'm trying to use the Gorilla/rpc package to set up a RPC to receive a request and reply with a response (obviously).

First I'm trying with the example provided with Gorilla/rpc

Here's my code:

type HelloArgs struct {
    Who string

type HelloReply struct {
    Message string

type HelloService struct{}

func (h *HelloService) Say(r *http.Request, args *HelloArgs, reply *HelloReply) error {
    reply.Message = "Hello, " + args.Who + "!"
    return nil

func main() {
    r := mux.NewRouter()

    jsonRPC := rpc.NewServer()
    jsonCodec := json.NewCodec()
    jsonRPC.RegisterCodec(jsonCodec, "application/json")
    jsonRPC.RegisterCodec(jsonCodec, "application/json; charset=UTF-8") // For firefox 11 and other browsers which append the charset=UTF-8
    jsonRPC.RegisterService(new(HelloService), "")
    r.Handle("/api", jsonRPC)

    http.ListenAndServe(":"+port, nil)

I have a couple of issues:

  1. I'm not sure how I would set a Access-Control-Allow-Origin header like I normally would on a http.ResponseWriter (with a regular webserver) for cross domain requests, as this doesn't take a http.ResponseWriter as an argument.

  2. What would I actually send to access the HelloService.Say method? I've tried { method: "HelloService.Say", params:[{Who: "Me"}]} but I get 405 (Method Not Allowed) (not sure if this is because I can't make x-domain requests though?)

Any insight greatly appreciated.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答


  • dttl3933 dttl3933 9年前

    EDITED: to fix bad use of 'type synonyms'

    For number 1:

    Gorilla/rpc/json's CodecRequest.WriteResponse (which implements Gorilla/rpc's CodecRequest) is the one place where the code touches an http.ResponseWriter.

    This means that we have to have our own implementation of CodecRequest which sets the CORS header.

    Every CodecRequest used by the server is actually generated by a Codec; Codecs are factories for making CodecRequests, to put it another way.

    This means that we have to create a Codec to generate our CodecRequests that will set CORS headers.

    The great thing about Go is that it's really easy to compose this extra behavior!

    Try this:

    package cors_codec
    import (
    //interface: ain't nobody dope like me I feel so fresh and clean
    func CodecWithCors([]string corsDomains, unpimped rpc.Codec) rpc.Codec {
        return corsCodecRequest{corsDomains, unpimped}
    type corsCodecRequest struct {
        corsDomains []string
        underlyingCodecRequest rpc.CodecRequest
    //override exactly one method of the underlying anonymous field and delegate to it.
    func (ccr corsCodecRequest) WriteResponse(w http.ResponseWriter, reply interface{}, methodErr error) error {
        w.Header().add("Access-Control-Allow-Origin", strings.join(ccr.corsDomains, " "))
        return ccr.underlyingCodecRequest.WriteResponse(w, reply, error)
    type corsCodec struct {
        corsDomains []string
        underlyingCodec rpc.Codec
    //override exactly one method of the underlying anonymous field and delegate to it.
    func (cc corsCodec) NewRequest(req *http.Request) rpc.CodecRequest {
      return corsCodecRequest{cc.corsDomains, cc.underlyingCodec.NewRequest(req)}

    That was a fun exercise!

    点赞 评论 复制链接分享