Home  >  Article  >  Backend Development  >  CORS grpc gateway GoLang

CORS grpc gateway GoLang

WBOY
WBOYforward
2024-02-12 12:54:091112browse

CORS grpc 网关 GoLang

php Xiaobian Strawberry introduces you to the CORS gRPC gateway GoLang. CORS, short for Cross-Origin Resource Sharing, is a mechanism used to make cross-domain requests in browsers. gRPC is a high-performance, open source remote procedure call (RPC) framework that can be used to build distributed systems. GoLang is a powerful programming language with high concurrency and simplicity. CORS gRPC Gateway GoLang combines CORS and gRPC to implement the gateway through the Go language to implement cross-domain requests. In this article, we will introduce in detail the principles and usage of CORS gRPC gateway GoLang to help you better understand and apply this technology.

Question content

I have a vue.js 3 front end, and I call the golang backend through grpc-gateway. I've been doing this for a while, but I see the light at the end of the tunnel.

I'm currently facing a cors problem. However, I'm reading conflicting information on how to deal with it. Therefore, I wanted to post something that I hope will be helpful to everyone.

Here is the code for how I initialize the mux server for grpc (gateway)

func runhttpserver(server *http.server, httpendpoint, grpcendpoint, swaggerpath string) (err error) {
    server.addr = httpendpoint

    ctx, cancel := context.withcancel(context.background())

    defer cancel()

    // register groc server endpoint
    mux := runtime.newservemux(
        runtime.witherrorhandler(func(ctx context.context,
            mux *runtime.servemux,
            marshaler runtime.marshaler,
            w http.responsewriter, r *http.request,
            err error,
        ) {
            s, ok := status.fromerror(err)
            if ok {
                if s.code() == codes.unavailable {
                    err = status.error(codes.unavailable, errunavailable)
                }
            }

            runtime.defaulthttperrorhandler(ctx, mux, marshaler, w, r, err)

        }),
    )

    opts := []grpc.dialoption{
        grpc.withtransportcredentials(insecure.newcredentials()),
        grpc.withchainunaryinterceptor(),
    }

    if err = api.registerapiservicehandlerfromendpoint(ctx, mux, grpcendpoint, opts); err != nil {
        return
    }

    swmux := http.newservemux()
    swmux.handle("/", mux)
    serveswagger(swmux, swaggerpath)

    server.handler = swmux

    return server.listenandserve()

}

Here is where I think I should add the cors configuration, but I'm not sure that's how I set it up in the server.go file..

var httpserver http.server

// run http server with grpc gateway
g.go(func() error {
    fmt.println("starting http sever (port {}) and grpc gateway (port {})",
        strconv.itoa(cfg.server.httpport),
        strconv.itoa(cfg.server.grpcport),
    )

    return rest.runhttpserver(
        &httpserver,
        ":"+strconv.itoa(cfg.server.httpport),
        ":"+strconv.itoa(cfg.server.grpcport),
        "/webapi",
    )
})

Console Error:

access to xmlhttprequest at 'http://localhost:8080/v1/test' from origin 'http://localhost:9000' has been blocked by cors policy: response to preflight request doesn't pass access control check: no 'access-control-allow-origin'

I don’t know where to add something like this

func enablecors(w *http.responsewriter) {
    (*w).header().set("access-control-allow-origin", "*")
}

I feel like there should be something built into the golang grpc gateway, but I can't find anything?

Any suggestions would be greatly appreciated.

-----Update 1-----

I've tried it

func enablecors(h http.handler) http.handler {
    return http.handlerfunc(func(w http.responsewriter, r *http.request) {
        w.header().set("access-control-allow-origin", "http://localhost:9000")
        w.header().set("access-control-allow-methods", "get, put, post, delete, head, options")
        h.servehttp(w, r)
    })
}

and

func enablecors(h http.handler) http.handler {
    return http.handlerfunc(func(w http.responsewriter, r *http.request) {
        w.header().set("access-control-allow-origin", "*")
        w.header().set("access-control-allow-methods", "get, put, post, delete, head, options")
        h.servehttp(w, r)
    })
}

and

func enablecors(h http.handler) http.handler {
    return http.handlerfunc(func(w http.responsewriter, r *http.request) {
        w.header().set("access-control-allow-origin", "http://localhost")
        w.header().set("access-control-allow-methods", "get, put, post, delete, head, options")
        h.servehttp(w, r)
    })
}

combine

func serveSwagger(mux *http.ServeMux, swaggerPath string) {
    fileServer := http.FileServer(http.Dir(swaggerPath))
    prefix := "/swagger-ui"
    mux.Handle(prefix, http.StripPrefix(prefix, fileServer))
}

Still having the same problem.. very frustrating

Workaround

Based on the latest error you provided in the comments:

Access to xmlhttprequest at 'localhost:8080/v1/test' from origin 'localhost:9000' has been blocked by cors policy: The response to the preflight request failed an access control check: it has no http normal status.

Your browser is sending a preflight request (options http method) to determine if the required cross-origin request can be made.

The server is responding with a non-2xx response.

I suspect this is because your enablecors function is propagating the request to the grpc-gateway handler, which is not happy with the options http method and returns an error status, possibly yes:

< http/1.1 501 not implemented
< content-type: application/json
< vary: origin
< date: fri, 25 nov 2022 11:17:52 gmt
< content-length: 55
< 
{"code":12,"message":"method not allowed","details":[]}

So to avoid this, you want to not propagate the request further when making a preflight request, e.g.

func enablecors(h http.handler) http.handler {
    return http.handlerfunc(func(w http.responsewriter, r *http.request) {
        w.header().set("access-control-allow-origin", "http://localhost:9000")
        w.header().set("access-control-allow-methods", "get, put, post, delete, head, options")
        if r.method == http.methodoptions {
            w.writeheader(http.statusnocontent)
            return
        }
        h.servehttp(w, r)
    })
}

But, the above may still not be a reasonable implementation of cors handling. You should use an existing package for this, such as github.com/rs/cors, which will handle this in a sensible way and handle any potential pitfalls etc.

So import github.com/rs/cors and then do the following:

server.Handler = cors.AllowAll().Handler(swMux)

should get you started letting everything pass. This library will allow you to tailor specific origins, http methods, etc. to your needs.

The above is the detailed content of CORS grpc gateway GoLang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete