Maison > développement back-end > Golang > le corps du texte

Impossible de connecter graphql-ws à gqlgen

WBOY
Libérer: 2024-02-06 09:54:12
avant
1067 Les gens l'ont consulté

无法将 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:
Copier après la connexion

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)
Copier après la connexion

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))
Copier après la connexion

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
Copier après la connexion

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{}}))
Copier après la connexion

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{}}))
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal