Как конвертировать подписку Apollo с аутентификацией, используя Apollo Client 2.x из 1.x - PullRequest
0 голосов
/ 04 февраля 2019

Я пытаюсь преобразовать подписку клиента Apollo 1.x в 2.x, но все еще не работает

Существующий код.

subscription-transport-ws: 0.8.3 apollo-клиент: 1.9.3

import { ApolloAuthProvider } from '../auth'
import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws'
import ApolloClient, { createNetworkInterface } from 'apollo-client'


networkInterface.use([{
  applyMiddleware (req, next) {
    if (!req.options.headers) {
      req.options.headers = {}  
    }
    req.options.headers.authorization = 'Basic xxxx'
    next()
  }
}])


const wsClient = new 
SubscriptionClient(ApolloAuthProvider.APISocketEndPoint, {
  reconnect: true,
  connectionParams: {
    'Authorization' : 'Basic xxxx'
  }
})

const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
  networkInterface,
  wsClient
)

export default (store) => (
  new ApolloClient({
    networkInterface: networkInterfaceWithSubscriptions
  })
)

Новый код:

import { ApolloClient } from 'apollo-client'
import { setContext } from 'apollo-link-context'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloAuthProvider } from '../auth'
import { ApolloLink } from 'apollo-link'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { getMainDefinition } from 'apollo-utilities'
import { WebSocketLink } from 'apollo-link-ws'


const getHttpClientConfig = () => {
  let config = {
    uri: ApolloAuthProvider.APIEndPoint
  }

  if (ApolloAuthProvider.isNeedAuthentication()) {
    config.credentials = 'include'
    config.headers = ApolloAuthProvider.getHeader()
  }
  return config
}


const httpLink = new createHttpLink(getHttpClientConfig())

const wsClient = new 
SubscriptionClient(ApolloAuthProvider.APISocketEndPoint, {
  reconnect: true,
  connectionParams: {
    'Authorization' : 'Basic xxxx'
  }
})

const webSocketLink = new WebSocketLink(wsClient)

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

const router = ApolloLink.from([
  requestLink({
    queryOrMutationLink: httpLink,
    subscriptionLink: webSocketLink,
  }),
])



export default (store) => (
  new ApolloClient({
    link: router,
    cache: new InMemoryCache()
  })
)

ожидается: нормально работает фактический результат: client.js: 426 Соединение WebSocket с 'wss: //' не удалось: HTTPАутентификация не удалась;действительные учетные данные недоступны

1 Ответ

0 голосов
/ 10 февраля 2019

Я думаю, что проблема может быть связана с объектом Config, который вы передаете SubscriptionClient

Ниже приведен код, который работает для меня.Это не совсем то же самое, что и у вас (он выбирает токен на предъявителя из локального хранилища вместо базовой аутентификации), но я думаю, что он должен указать вам правильное направление.

import { ApolloClient } from 'apollo-client';
import { setContext } from 'apollo-link-context';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { WebSocketLink } from 'apollo-link-ws';
import { GRAPHCOOL_HTTP_ENDPOINT, GRAPHCOOL_WS_ENDPOINT, JWT_LOCAL_STORAGE_KEY } from './constants';
import { getMainDefinition } from 'apollo-utilities';
import { split } from 'apollo-link';

const httpLink = createHttpLink({
  uri: GRAPHCOOL_HTTP_ENDPOINT
});

const authLink = setContext((_, { headers }) => {
  // Get the authentication token from local storage if it exists
  const token = localStorage.getItem(JWT_LOCAL_STORAGE_KEY);
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ""
    }
  };
});

const wsLink = () => {
  // Get the authentication token from local storage if it exists
  const token = localStorage.getItem(JWT_LOCAL_STORAGE_KEY);
  return new WebSocketLink({
    uri: GRAPHCOOL_WS_ENDPOINT,
    options: {
      reconnect: true,
      timeout: 30000,
      connectionParams: {
        Authorization: `Bearer ${token}`,
        authToken: token
      }
    }
  });
};

// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === "OperationDefinition" && operation === "subscription";
  },
  wsLink(),
  authLink.concat(httpLink)
);

export const client = new ApolloClient({
  link: link,
  cache: new InMemoryCache()
});
...