Home > Backend Development > Golang > CORS grpc gateway GoLang

CORS grpc gateway GoLang

WBOY
Release: 2024-02-12 12:54:09
forward
1144 people have browsed it

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()

}
Copy after login

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",
    )
})
Copy after login

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'
Copy after login

I don’t know where to add something like this

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

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)
    })
}
Copy after login

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)
    })
}
Copy after login

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)
    })
}
Copy after login

combine

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

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":[]}
Copy after login

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)
    })
}
Copy after login

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)
Copy after login

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!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template