I'm using gqlgen for my service and apollo client and graphql-ws for my front end and I'm trying to use a subscription and it perfectly works in my playground but when i try to connect the client to it I receive this error:
WebSocket connection to 'ws://localhost:8080/' failed:
and in my container log I receive:
unable to upgrade *http.response to websocket websocket: request origin not allowed by Upgrader.CheckOrigin: http: superfluous response.WriteHeader call from github.com/99designs/gqlgen/graphql/handler/transport.SendError (error.go:15)
here is my golang code:
if err := godotenv.Load(); err != nil {
log.Fatal("Error loading environment variables file")
}
port := helpers.Env("PORT")
if port == "" {
port = defaultPort
}
router := chi.NewRouter()
router.Use(cors.New(cors.Options{
AllowedOrigins: strings.Split(helpers.Env("ALLOWED_ORIGINS"), ","),
AllowCredentials: true,
Debug: helpers.Env("DEBUG") == "true",
AllowedHeaders: []string{"*"},
}).Handler)
srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &resolvers.Resolver{}}))
srv.AddTransport(transport.POST{})
upgrader := &transport.Websocket{
Upgrader: websocket.Upgrader{
HandshakeTimeout: 1 * time.Minute,
CheckOrigin: func(r *http.Request) bool {
return true
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
},
KeepAlivePingInterval: 10 * time.Second,
}
srv.AddTransport(upgrader)
srv.Use(extension.Introspection{})
if helpers.Env("MODE") == "PRODUCTION" {
cache, err := apq.NewCache(24 * time.Hour)
if err != nil {
log.Fatalf("cannot create APQ redis cache: %v", err)
}
srv.Use(extension.AutomaticPersistedQuery{Cache: cache})
}
go initWorkers()
go runAsynqmon()
router.Use(getHeadersMiddleware())
router.Handle("/", srv)
if helpers.Env("MODE") == "DEVELOPMENT" {
router.Handle("/playground", playground.Handler("GraphQL playground", "/"))
log.Printf("connect to http://localhost:%s/playground for GraphQL playground", port)
}
log.Fatal(http.ListenAndServe(":"+port, router))
and here is my client code:
import { setContext } from '@apollo/client/link/context'
import { onError } from '@apollo/client/link/error'
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
import { getMainDefinition } from '@apollo/client/utilities'
import { createUploadLink } from 'apollo-upload-client'
import { createClient } from 'graphql-ws'
import { logout } from '../helpers/logout'
import { getTokenFromStorage } from '../helpers/userData'
import { lang } from '../localization'
const authLink = setContext((_, { headers }) => {
const token = getTokenFromStorage()
return {
headers: {
authorization: token ? `Bearer ${token}` : undefined,
'Accept-Language': lang,
...headers
}
}
})
const httpLink = createUploadLink({
uri: process.env.REACT_APP_GRAPH_BFF || 'http://localhost:8080'
})
const wsLink = new GraphQLWsLink(
createClient({
url: 'ws://localhost:8080/'
})
)
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
httpLink
)
const logoutLink = onError(({ response }) => {
if (
response?.errors &&
response.errors.length > 0 &&
response.errors.some((errorItem) =>
errorItem.message.toLowerCase().includes('unauthenticated')
)
) {
logout()
}
})
const chainList = [logoutLink, authLink, splitLink]
const linkChain = from(chainList)
const apolloClient = new ApolloClient({
cache: new InMemoryCache({
addTypename: false
}),
link: linkChain
})
export default apolloClient
I thought CheckOrigin in upgrader would fix this but it didn't work any idea how to fix this?