Maison  >  Article  >  développement back-end  >  Impossible de connecter graphql-ws à gqlgen

Impossible de connecter graphql-ws à gqlgen

WBOY
WBOYavant
2024-02-06 09:54:121040parcourir

无法将 graphql-ws 连接到 gqlgen

Contenu de la question

J'utilise gqlgen comme service avec apollo client et graphql-ws comme interface et j'essaie d'utiliser des abonnements et cela fonctionne parfaitement dans mon terrain de jeu mais quand j'essaye de y connecter le client , j'ai eu cette erreur :

websocket connection to 'ws://localhost:8080/' failed:

Dans mon journal de conteneur je reçois :

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)

Voici mon code golang :

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

Voici mon code client :

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

Je pensais que la mise à jour de checkorigin dans le programme résoudrait le problème, mais cela ne fonctionne pas Une idée de comment résoudre ce problème ?


Bonne réponse


C'est une excellente question. Cela signifie que vous êtes un programmeur talentueux... Répondez ci-dessous :

Vous devez modifier cette ligne :

srv := handler.newdefaultserver(generated.newexecutableschema(generated.config{resolvers: &resolvers.resolver{}}))

Parce que newdefaultserver utilise la même source, ce qui signifie que votre source et votre hôte doivent être les mêmes, ce qui signifie votre code : checkorigin : func(r *http.request) bool { Renvoie vrai }, Ca ne fonctionne pas. Vous devez remplacer newdefaultserver par new pour que votre code y soit modifié :

srv := handler.New(generated.NewExecutableSchema(generated.Config{Resolvers: &resolvers.Resolver{}}))

Et votre websocket fonctionne bien. Soyez prudent avec ce changement car newdefaultserver contient une configuration pour la mise à jour ou l'obtention ou d'autres choses. (voir emballage lui-même) Et vous devez l'écrire facilement dans votre code.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer