Apollo Websocket似乎从未连接

时间:2019-04-25 03:35:48

标签: django react-native apollo graphql-subscriptions

我正在开发带有身份验证和订阅的移动应用程序,前端使用apollo graphql,后端使用Django。 我无法使网络套接字正常工作。

用户可以登录(关闭应用程序并重新登录),还可以运行变体/查询,但是当它进行订阅时,websocket似乎无法连接。此外,在运行预订的subscribe()方法时,将触发onDisconnected监听器(?),onConnectedonReconnected从不执行,仅onReconnectingconnectionParams包含authToken: storage.getCookie()时触发(我认为这是错误的设置方式)。

实际上,使用消息传递功能时,将发送消息,但不会将当前用户添加为已发送消息的上下文的一部分,因此订阅将返回该消息,就好像该用户尚未发送消息一样(Django看到AnonymousUser,这是没有上下文用户获得的默认设置。

我觉得我已经刮擦了互联网,我正在寻求最后的解决方法/绝望。

任何小技巧/提示都可以帮助!

如果您需要更多信息,我很乐意与您分享。

我的Apollo链接具有以下配置(websocket和常规):

import { ApolloLink } from 'apollo-link'
import { ApolloClient } from 'apollo-boost'
import { createUploadLink } from 'apollo-upload-client'
import { WebSocketLink } from 'apollo-link-ws'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { setContext } from 'apollo-link-context'
import { getMainDefinition } from 'apollo-utilities'
import {
  InMemoryCache,
  IntrospectionFragmentMatcher,
} from 'apollo-cache-inmemory'

import introspectionQueryResultData from './fragmentTypes.json'
import * as storage from '../src/storage'
import { auth } from 'react-native-firebase'

const fragmentMatcher = new IntrospectionFragmentMatcher({
  introspectionQueryResultData,
})

let api = 'localhost:8000'

let domainApi = `https://${api}`
let domainWs = `wss://${api}`

if (api.startsWith('localhost')) {
  // In local env, use non-secure protocols
  domainApi = `http://${api}`
  domainWs = `ws://${api}`
}

const defaultOptions = {
  watchQuery: {
    fetchPolicy: 'cache-and-network',
    errorPolicy: 'all',
  },
  query: {
    fetchPolicy: 'cache-and-network',
    errorPolicy: 'all',
  },
  mutate: {
    errorPolicy: 'all',
  },
}

// Persisting sessions with react-native: https://build.affinity.co/persisting-sessions-with-react-native-4c46af3bfd83
// apollo-http-link: https://www.apollographql.com/docs/link/links/http.html
const authLink = setContext(request =>
  storage.getCookie().then(cookie => ({
    // Before the request is sent: set cookie header
    headers: {
      cookie,
    },
    credentials: 'omit', // set cookies manually
  }))
)

const setTokenLink = new ApolloLink((operation, forward) => {
  // Send the request to the server
  return forward(operation).map(response => {
    // After response is returned: store cookie in local storage
    const context = operation.getContext()
    const {
      response: { headers },
    } = context

    if (headers) {
      storage.setCookie(headers.get('set-cookie'))
    }

    return response
  })
})

const httpLink = createUploadLink({
  uri: `${domainApi}/graphql/`,
})

const wsClient = new SubscriptionClient(domainWs,
  storage.getCookie().then(cookie => ({
    lazy: true,
    reconnect: true,
    connectionParams: {
      // authorization: `Bearer ${cookie}`, //tried this but no avail
      authorization: cookie, // cookie = 'sessionid=abc11234.....'
      authToken: storage.getCookie() // (A) gets as far as trying to reconnect
    }
  }))
)

wsClient.onConnected(()=>{console.log("connected f client f onConnected")})
wsClient.onReconnected(()=>{console.log("connected f client freconnected")})
wsClient.onReconnecting(()=>{console.log("connected f client  f reconnecting")})
wsClient.onDisconnected(()=>{console.log("connected f client  f onDisconnected")})
wsClient.onError(()=>{console.log("connected f client  f onError")})

const wsLink = new WebSocketLink(wsClient)

const requestLink = ({ queryOrMutationLink, subscriptionLink }) =>
  ApolloLink.split(
    ({ query }) => {
      const { kind, operation } = getMainDefinition(query)
      return kind === 'OperationDefinition' && operation === 'subscription'
    },
    subscriptionLink,
    queryOrMutationLink
  )

const cache = new InMemoryCache({ fragmentMatcher })

export { wsClient }

export default new ApolloClient({
  link: requestLink({
    queryOrMutationLink: authLink.concat(setTokenLink.concat(httpLink)),
    subscriptionLink: wsLink,
  }),
  cache,
  defaultOptions,
})

这是cookie存储功能:

import AsyncStorage from '@react-native-community/async-storage'

const sessionIdRe = /sessionid=[^;]*/

export const HTTP_COOKIE = 'HTTP_COOKIE'

let cookieCache

export const getCookie = handleError(() =>
  cookieCache !== undefined
    ? Promise.resolve(cookieCache)
    : AsyncStorage.getItem(HTTP_COOKIE)
)

export const setCookie = handleError(cookie => {
  const match = sessionIdRe.exec(cookie)
  if (!match) {
    return Promise.resolve(null)
  }

  const sessionCookie = match[0]
  cookieCache = sessionCookie
  return AsyncStorage.setItem(HTTP_COOKIE, sessionCookie)
})

export const removeCookie = handleError(() =>
  AsyncStorage.removeItem(HTTP_COOKIE).then(() => (cookieCache = undefined))
)

function handleError(callback) {
  return async function() {
    try {
      const value = await callback.apply(this, arguments)
      if (value !== null) return value
    } catch (e) {}
  }
}

0 个答案:

没有答案