I want to use a custom Handler( Specifically want to use a chi router) in gRPC. I have tried to search on the internet but don’t found help to set a custom handler in the gRPC server.
Below is the code for my chi handler and I want to set it in gRPC server.
func (app *Config) routes() http.Handler {
mux := chi.NewRouter()
// specify who is allowed to connect
mux.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"https://*", "http://*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{"Link"},
AllowCredentials: true,
MaxAge: 300,
}))
mux.Use(middleware.Heartbeat("/ping"))
mux.Get("/", app.RequestCome)
mux.Post("/authenticate", app.Authenticate)
return mux
}
Thanks
Related
I just recently started coding in go and thus I am not so skilled yet.
I have a use case where I want to implement a reverse proxy as a gin route.
So my route looks like this:
server.router.POST("/console", server.proxyConsoleUrl)
And my handler function something like this:
func (server *Server) proxyConsoleUrl(ctx *gin.Context) {
director := func(req *http.Request) {
r := ctx.Request
// This is not working, scheme wss is not supported
req.URL.Scheme = "wss"
req.URL.Host = "192.168.******:8006"
// The path which gets proxied should be overriden
req.URL.RawPath = "/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something"
req.Header["my-header"] = []string{r.Header.Get("my-header")}
// Golang camelcases headers
delete(req.Header, "My-Header")
// This header has to be added to every request which gets proxied
req.Header["Authorization"] = []string{"MYCUSTOMHEADER"}
}
proxy := &httputil.ReverseProxy{Director: director, Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}
proxy.ServeHTTP(ctx.Writer, ctx.Request)
}
So my first problem is, that httputil.ReverseProxy doesn't support web socket as far as I know and noticed when running my code:
httputil: unsupported protocol scheme "wss"
The Second problem is, that I want to override the backend url as well as add custom headers which are added by the proxy.
Maybe someone has an idea hot to implement this, if it's even possible. -Thanks in advance
WebSocket support was added to httputil.ReverseProxy in Go version 1.12.
Use the result of url.Parse("https://192.168.******:8006/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something") to set the target URL. This fixes the following issues:
The WebSocket protocol uses "http" or "https" on the wire, not "wss".
RawPath is ignored when RawPath is a not a valid escaping of Path. See EscapedPath for the details. Because the RawPath in the question includes a query string, it will never be a valid escaping of Path. The client's path is alway used as is. Ditto for the client's query string.
Create the proxy once and reuse it. The important point is to create an reuse a single transport per the Transport documentation. Reusing the proxy accomplishes that goal.
func createProxy() *httputil.ReverseProxy {
target, _ := url.Parse("https://192.168.******:8006/api2/json/nodes/something/qemu/123/vncwebsocket?port=5900&vncticket=something")
director := func(req *http.Request) {
req.URL = target
req.Header["my-header"] = []string{req.Header.Get("my-header")}
delete(req.Header, "My-Header")
req.Header["Authorization"] = []string{"MYCUSTOMHEADER"}
}
return &httputil.ReverseProxy{Director: director, Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}
}
var proxy = createProxy()
func (server *Server) proxyConsoleUrl(ctx *gin.Context) {
proxy.ServeHTTP(ctx.Writer, ctx.Request)
}
I have a React app using fetch calling to a go mux api.
I am well aware of the question here: Making golang Gorilla CORS handler work
but this does not work for me. I have tried everything in that post and still no success. Looks like go is not even running any middleware or route handler function for me.
Here is the first way I tried fixing it. This uses gorilla/handlers
package main
import (
"fmt"
"net/http"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
)
func commonMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("MIDDLEWARE CALLED")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
next.ServeHTTP(w, r)
})
}
func ApiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("ROUTE CALLED")
fmt.Fprintf(w, `{"works:"true}`)
}
func main() {
var router *mux.Router = mux.NewRouter()
router.Use(commonMiddleware)
router.HandleFunc("/api", ApiHandler).Methods("POST")
headersOk := handlers.AllowedHeaders([]string{"Access-Control-Allow-Origin", "Accept", "Accept-Language", "Content-Type", "Content-Language", "Origin"})
originsOk := handlers.AllowedOrigins([]string{"http://localhost:*", "*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
http.ListenAndServe(":8000", handlers.CORS(headersOk, originsOk, methodsOk)(router))
}
This uses rs/cors
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/cors"
)
func commonMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("MIDDLEWARE CALLED")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
next.ServeHTTP(w, r)
})
}
func ApiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("ROUTE CALLED")
fmt.Fprintf(w, `{"works:"true}`)
}
func main() {
var router *mux.Router = mux.NewRouter()
router.Use(commonMiddleware)
router.HandleFunc("/api", ApiHandler).Methods("POST")
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowCredentials: true,
})
handler := c.Handler(router)
http.ListenAndServe(":8000", handler)
}
However, in both cases CORS errors still appear in the browser. I am running the react server on port 5000 and the go server is on port 8000.
fetch("http://localhost:8000/api", {
method: 'POST',
headers: {
// "Access-Control-Allow-Origin": "*",
'Content-Type': 'application/json'
},
body: JSON.stringify({
example: 1
})
})
Error in Chrome:
Access to fetch at 'http://localhost:8000/validate/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Neither solution works. In fact "MIDDLEWARE CALLED" and "ROUTE CALLED" in go never print out. The api works just fine in Postman so I know the router works fine and the issue really is CORS. So it appears that the route never gets called.
This is stunning, could it have something to do with preflight. How do I disable all cors issues?
If you want to allow all origin, the other way you can do it is
c := cors.New(cors.Options{
AllowOriginFunc: func(r string) bool {
return true
}
})
I had a similar problem. The issue was in my antivirus software. Disabiling it fixed the issue.
GOAL:
Svelte app running on port 5000 wants to query data from gqlgen GraphQL server running on port 8080, both on localhost. I tried to query a public graphql API such as https://api.react-finland.fi/graphql just to test if my Svelte app (port:5000) is working well and it is. So I think the problem lies with my Go graphql server (port:8080).
SYSTEM
go version
go version go1.15 linux/amd64
go 1.15
require (
github.com/99designs/gqlgen v0.12.1
github.com/go-chi/chi v4.1.2+incompatible
github.com/gorilla/websocket v1.4.2
github.com/rs/cors v1.7.0
github.com/vektah/gqlparser/v2 v2.0.1
)
HAVE TRIED
According to the official site, I have tried their approach.
And here is my code:
func main() {
port := os.Getenv("PORT")
if port == "" {
port = defaultPort
}
router := chi.NewRouter()
// Add CORS middleware around every request
// See https://github.com/rs/cors for full option listing
router.Use(cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:5000", "http://localhost:8080"},
AllowOriginFunc: func(origin string) bool { return true },
AllowedMethods: []string{},
AllowedHeaders: []string{},
AllowCredentials: true,
Debug: true,
}).Handler)
srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}))
srv.AddTransport(&transport.Websocket{
Upgrader: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// Check against your desired domains here
return r.Host == "localhost:8080"
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
},
})
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
http.Handle("/query", srv)
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
err := http.ListenAndServe(":8080", router)
if err != nil {
panic(err)
}
}
RESULT
I got those errors:
Access to fetch at 'http://localhost:8080/' from origin 'http://localhost:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
HOW TO SOLVE?
I've read quite some documentation and googled around... but couldn't figure out exactly how to and I don't know how to debug to find solution. I just learnt GO for two days so far. Can someone help? Thanks!
Hi now someone helped me find out the major problems I have:
1.Yes, we can use just one in the line where I wrote :
AllowedOrigins: []string{"http://localhost:5000", "http://localhost:8080"},
AllowOriginFunc: func(origin string) bool { return true },
In fact the second one will overwrite the first one, so can choose just one.
2.In this part
log.Fatal(http.ListenAndServe(":"+port, nil))
err := http.ListenAndServe(":8080", router)
if err != nil {
panic(err)
}
I have written the http:ListenAndServe twice, so it didn't get to the second one. I deleted the log.Fatal(http.ListenAndServe(":"+port, nil))
3.Since we passed the middleware to router for http request, we need to use that instead of http.handle. So those two lines were wrong:
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
http.Handle("/query", srv)
The right way to do it should be :
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
router.Handle("/query", srv)
In fact that was shown in the official approach... but somehow after I tried several different solutions I got lost in the rabbit holes and didn't see those obvious errors! >.<
After the above changes now it works finally! Thanks for your help!
I made a backend in go and deployed it using Google Cloud Run. Now I am trying to ping it from my website hosted locally, but then I get a CORS error like
type: "cors"
url: "https://abc.a.run.app/do-a"
redirected: false
status: 500
ok: false
statusText: ""
headers: Headers {}
body: (...)
bodyUsed: false
These are the headers I set in my http handler function in go.
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
My handler function is routed like
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.HandleFunc("/do-a", endpoints.DoA)
err := http.ListenAndServe(":"+port, nil)
handle(err)
}
Please check this example from the official documentation:
// Package http provides a set of HTTP Cloud Functions samples.
package http
import (
"fmt"
"net/http"
)
// CORSEnabledFunctionAuth is an example of setting CORS headers with
// authentication enabled.
// For more information about CORS and CORS preflight requests, see
// https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request.
func CORSEnabledFunctionAuth(w http.ResponseWriter, r *http.Request) {
// Set CORS headers for the preflight request
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "Authorization")
w.Header().Set("Access-Control-Allow-Methods", "POST")
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
w.Header().Set("Access-Control-Max-Age", "3600")
w.WriteHeader(http.StatusNoContent)
return
}
// Set CORS headers for the main request.
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
fmt.Fprint(w, "Hello World!")
}
From the code you posted I can not tell if you check for the preflight request and set the Access-Control-Allow-Methods header.
I am using golang iris framework for adding users through rest calls. This is my code
package main
import (
"fmt"
"github.com/iris-contrib/middleware/cors"
"github.com/kataras/iris"
)
type User struct {
Name string
}
func main() {
app := iris.New()
crs := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "DELETE"},
AllowCredentials: true,
})
app.Use(crs)
//
app.Post("/send", func(ctx iris.Context) {
// deployment Object
name := User{}
ctx.ReadJSON(&name)
fmt.Println(name)
})
app.Run(iris.Addr("localhost:8080"))
}
It is working fine. But I am getting cors error in front ajax calls. I have added cors options. But still I am getting the below error.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the
remote resource at http://localhost:8080/send. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). (unknown)
I couldn't find what is the error. Please anyone help to solve this issue.
Thanks in advance.
You have to allow the OPTIONS HTTP Method for your Party/Group or the whole app using the .AllowMethods(iris.MethodOptions) function. The https://github.com/kataras/iris/blob/master/_examples/experimental-handlers/cors/simple/main.go example shows you the way already.
package main
import (
"fmt"
"github.com/iris-contrib/middleware/cors"
"github.com/kataras/iris/v12"
)
type User struct {
Name string
}
func main() {
app := iris.New()
crs := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "DELETE"},
AllowCredentials: true,
})
app.Use(crs)
//
app.AllowMethods(iris.MethodOptions) // <- HERE
app.Post("/send", func(ctx iris.Context) {
// deployment Object
name := User{}
ctx.ReadJSON(&name)
fmt.Println(name)
})
app.Run(iris.Addr(":8080"))
}