<p>рдЕрдкреЛрд▓реЛ-рд▓рд┐рдВрдХ-рдбрдмреНрд▓реНрдпреВрдПрд╕: рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реЗрдЯрдЕрдк рдХреЗ рдмрд╛рдж рдХрдиреЗрдХреНрд╢рди рдкреИрд░рд╛рдореНрд╕ (рдФрд░ рдЯреЛрдХрди) рдХреИрд╕реЗ рдмрджрд▓реЗрдВ?</p>

рдХреЛ рдирд┐рд░реНрдорд┐рдд 31 рдЕрдХреНрддреВре░ 2017  ┬╖  28рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: apollographql/apollo-link

рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╢реБрд░реВ рдореЗрдВ WsLink рдмрдирд╛рддреЗ рд╕рдордп connectionParams рдореЗрдВ рдЯреЛрдХрди рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд░реВрдк рдореЗрдВ websockets рдкрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред

рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЯреЛрдХрди рдХреЛ рдмрд╛рдж рдореЗрдВ рдХреИрд╕реЗ рдмрджрд▓рд╛ рдЬрд╛рдП рдФрд░ рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧ рдЖрдЙрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╕реЗ рд▓реЙрдЧ рдЗрди рдХрд░рддрд╛ рд╣реИ рддреЛ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ (рд╕рдВрднрд╡рддрдГ рдПрдХ рдЕрд▓рдЧ рдЯреЛрдХрди рдХреЗ рд╕рд╛рде)

рдореИрдВрдиреЗ рдЗрд╕ рддрд░рд╣ рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд┐рдпрд╛:

export const changeSubscriptionToken = token => {
  if (wsLink.subscriptionClient.connectionParams.authToken === token) {
    return
  }

  wsLink.subscriptionClient.connectionParams.authToken = token
  wsLink.subscriptionClient.close()
  wsLink.subscriptionClient.connect()
}

рд▓реЗрдХрд┐рди рдпрд╣ рдереЛрдбрд╝реЗ рд╣реИрдХреА рд▓рдЧрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ wsLink.subscriptionClient рдХреЛ рдирд┐рдЬреА рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдмрд╛рд╣рд░ рд╕реЗ рдкрд╣реБрдВрдЪ рдпреЛрдЧреНрдп рдирд╣реАрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЪреВрдВрдХрд┐ рдирдпрд╛ WebSocketLink рдЕрднреА рднреА subscriptions-transport-ws рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЕрдкрдиреЗ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ WebSocketLink рдХреЗ рдмрдЬрд╛рдп рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдореИрдВ рдЙрд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреИрд╕рд╛ рдореИрдВрдиреЗ v1 рдореЗрдВ рдХрд┐рдпрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ WebSocketLink API рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг рд╣реИрдХреА рдХреА рддрд░рд╣ рд▓рдЧрддрд╛ рд╣реИред

// create the web socket link
const wsLink = new WebSocketLink({
  uri: 'ws://example.com',
  options: {
    reconnect: true
  }
})
// create my middleware using the applyMiddleware method from subscriptions-transport-ws
const subscriptionMiddleware = {
  applyMiddleware (options, next) {
    options.auth = { ... }
    next()
  }
}
// add the middleware to the web socket link via the Subscription Transport client
wsLink.subscriptionClient.use([subscriptionMiddleware])

рдЖрдк рд╡рд┐рдХрд▓реНрдк рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛ рднреА рдорд╛рди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╡реЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ onOperation рдХреЙрд▓рдмреИрдХ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрддреЗ рд╣реИрдВред

рд╕рднреА 28 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЖрдк рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХрдиреЗрдХреНрд╢рдирдкрд░рдореНрд╕ рдореЗрдВ рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред

    const wsLink = new WebSocketLink({
      uri: config.subscriptionURL,
      options: {
        reconnect: true,
        connectionParams: () => ({
          authToken: reduxStore.getState().authentication.token,
        }),
      },
    });

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

рдУрд╣ рд░реБрдХреЛ, рдпрд╣ рдкрд╣рд▓реА рдмрд╛рд░ рдХреЗ рдмрд╛рдж рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ... рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рд╣реЛ рдЬреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдСрдмреНрдЬреЗрдХреНрдЯ рдбрд╛рд▓рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк onOperation рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рдпрд╣рд╛рдБ рдореЗрд░реЗ рдкрд╛рд╕ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рд╣реИ, рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдореИрдВ рдЗрд╕реЗ ApolloClient V1 рдХреЗ рд╕рд╛рде рдХрд░ рд░рд╣рд╛ рдерд╛, рдЙрд╕рдХреЗ рдмрд╛рдж рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛

рдкреЗрд▓реЛрдб рдкрд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЯреЛрдХрди рд╕рдВрд▓рдЧреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд▓рд┐рдВрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЬреЛрдбрд╝реЗрдВ

const authMiddleware = new ApolloLink((operation, forward) => {
    // Add the authorization to the headers for HTTP authentication
    operation.setContext({
      headers: {
        authorization: `Bearer ${authToken()}`,
      },
    });

    // Add onto payload for WebSocket authentication
    (operation as Operation & { authToken: string | undefined }).authToken = authToken();


    return (forward as any)(operation);
  });

const myLink = concat(myLink, wsLink);

рдлрд┐рд░ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдЖрдк рдЗрд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдСрдирдСрдкрд░реЗрд╢рди рд╣реБрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрджрд░реНрдн рдкрд░ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

function configureDecodeTokenSocketMiddleware(authURL: string) {
  return async function decodeTokenSocketMiddleware<ConnectionParams extends { authToken: string }>(connectionParams: ConnectionParams, operationParams: object) {
    let authPayload;
    try {
      if (typeof connectionParams.authToken === 'string') {
        authPayload = await verifyJWT(authURL, connectionParams.authToken);
      } else {
        throw new Error('Auth Token not available');
      }
    } catch(e) {
      authPayload = {};
    }
    return {
      ...operationParams,
      context: {
        authentication: authPayload,
      },
    };
  };
}

new SubscriptionServer({
      execute,
      subscribe,
      schema,
      onOperation: configureDecodeTokenSocketMiddleware(appConfig.authURL),
    }, {
      server: appConfig.server,
      path: `/${appConfig.subscriptionsEndpoint}`,
    });

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЖрдк рдЗрд╕ рд╕рдВрджреЗрд╢ рдХреЛ рдлрд┐рд░ рд╕реЗ рднреЗрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/client.ts#L507

      const payload: ConnectionParams = typeof this.connectionParams === 'function' ? this.connectionParams() : this.connectionParams;
      this.sendMessage(undefined, MessageTypes.GQL_CONNECTION_INIT, payload);

рдХреНрдпрд╛ рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдЕрдиреБрд╢рдВрд╕рд┐рдд рддрд░реАрдХрд╛ рд╣реИ?

рд╕рджрд╕реНрдпрддрд╛ рдЗрд╕ рдореБрджреНрджреЗ

рдЪреВрдВрдХрд┐ рдирдпрд╛ WebSocketLink рдЕрднреА рднреА subscriptions-transport-ws рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЕрдкрдиреЗ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ WebSocketLink рдХреЗ рдмрдЬрд╛рдп рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдореИрдВ рдЙрд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬреИрд╕рд╛ рдореИрдВрдиреЗ v1 рдореЗрдВ рдХрд┐рдпрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ WebSocketLink API рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг рд╣реИрдХреА рдХреА рддрд░рд╣ рд▓рдЧрддрд╛ рд╣реИред

// create the web socket link
const wsLink = new WebSocketLink({
  uri: 'ws://example.com',
  options: {
    reconnect: true
  }
})
// create my middleware using the applyMiddleware method from subscriptions-transport-ws
const subscriptionMiddleware = {
  applyMiddleware (options, next) {
    options.auth = { ... }
    next()
  }
}
// add the middleware to the web socket link via the Subscription Transport client
wsLink.subscriptionClient.use([subscriptionMiddleware])

рдЖрдк рд╡рд┐рдХрд▓реНрдк рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛ рднреА рдорд╛рди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╡реЗ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ onOperation рдХреЙрд▓рдмреИрдХ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрддреЗ рд╣реИрдВред

рдпрд╣ рд╕рдорд╕реНрдпрд╛ рднреА рд╣реЛ рд░рд╣реА рд╣реИ
@jbaxleyiii рдХреЛрдИ рд╡рд┐рдЪрд╛рд░?

рдореИрдВрдиреЗ рдХреБрдЫ рд╣рдлреНрддреЗ рдкрд╣рд▓реЗ рдПрдХ рд╕рдорд╛рдзрд╛рди рдмрдирд╛рдпрд╛ рд╣реИ (? рдпрд╣ рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрд╛рдЧ рд░рд╣рд╛ рд╣реИ):

рдореЗрд░реЗ app.module.ts рдореЗрдВ рдПрдХ рдореЙрдбреНрдпреВрд▓ GraphQLModule рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { Apollo, ApolloModule } from 'apollo-angular';
import { HttpLinkModule } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { WebSocketLink } from 'apollo-link-ws';
import { SubscriptionClient } from 'subscriptions-transport-ws';

@NgModule({
  exports: [
    ApolloModule,
    HttpClientModule,
    HttpLinkModule
  ]
})
export class GraphQLModule {
  public subscriptionClient: SubscriptionClient = null;

  constructor(apollo: Apollo) {
    const wssEndpoint = 'wss://your-domain.com/subscriptions';
    // It's required to define connectionParams as function, as otherwise the updated token is not transferred
    const connectionParams = () => {
      const token = sessionStorage.getItem('token');
      return token ? { 'Authorization': 'token ' + token } : {};
    };

    const wsLink = new WebSocketLink({
      uri: wssEndpoint,
      options: {
        connectionParams: connectionParams,
        reconnect: true
      }
    });
    this.subscriptionClient = (<any>wsLink).subscriptionClient;

    const cache = new InMemoryCache({});

    apollo.create({
      link: wsLink,
      cache: cache.restore(window[ '__APOLLO_CLIENT__' ]),
      connectToDevTools: true,
      queryDeduplication: true
    });
  }
}

рдореЗрд░реА рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╕реЗрд╡рд╛ рдореЗрдВ, рдореИрдВ рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ private graphQLModule: GraphQLModule рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред
рд▓реЙрдЧрд┐рди рдпрд╛ рд▓реЙрдЧрдЖрдЙрдЯ рдХреЗ рдмрд╛рдж рдореИрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ:

const client = this.graphQLModule.subscriptionClient;
// Close actual connection
client.close(true, true);
// todo: set/unset session token in sessionStorage
// Connect again
(<any>client).connect();

рдпрд╣ рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдРрдк рд╕реНрдЯрд╛рд░реНрдЯ рдкрд░ рдЦреЛрд▓рддрд╛ рд╣реИ рдФрд░ рд▓реЙрдЧрд┐рди/рд▓реЙрдЧрдЖрдЙрдЯ рдкрд░ рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИред

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдпрд╣ рдПрдХ рд╡рд╛рджрд╛ рд╡рд╛рдкрд╕реА рд╕рдорд╛рд░реЛрд╣ рдХрд╛ рднреА рд╕рдорд░реНрдерди рдХрд░реЗрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рд╣рдореЗрдВ рдЯреЛрдХрди рдХреЛ рдПрд╕рд┐рдВрдХ рдХрд░рдирд╛ рд╣реИ рддреЛ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

@ clayne11 рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХрд░рддрд╛ рд╣реИред рдореИрдВ рдХрдиреЗрдХреНрд╢рди рдкреИрд░рд╛рдореНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рдореВрд▓ рд╕реЗ AsyncStorage рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЬреЛ рдПрд╕рд┐рдВрдХ рдЬреЛрдбрд╝рд╛ рд╣реИ, рд╡рд╣ рд╕рд░реНрд╡рд░ рдкрд░ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рднреЗрдЬрддрд╛ рд░рд╣рддрд╛ рд╣реИред
рдореБрдЭреЗ рдЗрд╕рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реИ?

рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:
рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рд╣реИ рдЬреЛ рдЗрд╕реЗ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдорд╛рд╕реНрдЯрд░ рд╢рд╛рдЦрд╛ рдореЗрдВ рд╡рд┐рд▓рдп рдирд╣реАрдВ рд╣реБрдЖ рд╣реИ

@jonathanheilmann , рдЖрдкрдХрд╛ рд╕рдорд╛рдзрд╛рди @ helios1138 рдореВрд▓ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рдорд╛рди рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рджрд╕реНрдпрддрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП connect() API рдХреЛ рдирд┐рдЬреА рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВрдиреЗ subscriptionClient.close(false, false) рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬреЛ рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдПрдкреАрдЖрдИ рд╣реИ рдФрд░ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛, рдФрд░ рдпрд╣ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рджрд╕реНрдпрддрд╛ рдЕрднреА рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреА рд╣реИред рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдЬреЛ рдЕрднреА рдХрд╛рдо рдХрд░ рд░рд╣реА рд╣реИ рд╡рд╣ рд╣реИ:

subscriptionClient.close();
subscriptionClient.connect(); // this is a private API :-(

рдЗрд╕ рдкрд░ рдХреЛрдИ рд╕рд╛рдл рдирдП рд╡рд┐рдЪрд╛рд░? рдпрд╣рд╛рдВ рд╕рдорд╛рдзрд╛рди рдХрд░рдирд╛ рдкрд╕рдВрдж рд╣реИред рдореИрдВ рд▓реЛрдб рдкрд░ рдЕрдкрдирд╛ рдЕрдкреЛрд▓реЛ рд▓рд┐рдВрдХ рдмрдирд╛рддрд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдПрдХ рдмрд╛рд░ рдЬрдм рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рддрд╛ рд╣реИ рддреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреЗрдЬреЗ рдЬрд╛ рд░рд╣реЗ рдЯреЛрдХрди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВред

рдпрд╣ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо рдЖрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ: https://github.com/apollographql/apolo-server/issues/1505ред

рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди рдкрд░ context рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВред

рдЗрд╕рд╕реЗ рдореБрдЭреЗ рдорджрдж рдорд┐рд▓реА
https://github.com/apolographql/apolo-link/issues/446#issuecomment -410073779

рдХреНрдпрд╛ рдХреЛрдИ рдкреБрд╖реНрдЯрд┐ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдмрд╛рд░ рд╡реЗрдмрд╕реЙрдХреЗрдЯ рдЪреИрдирд▓ (рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╣реЗрдбрд░ = рдЯреЛрдХрди рдПрдПрдП рдХреЗ рд╕рд╛рде) рдЦреЛрд▓рд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╡реЗрдмрд╕реЙрдХреЗрдЯ рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдж рдХреЗ рдЕрдиреБрд░реЛрдз рдХреЛ рд╣рдореЗрд╢рд╛ рдПрдПрдП рдЯреЛрдХрди рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╣рдЪрд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ред

рдпрд╛ рдХреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдкрд░ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╢реАрд░реНрд╖рд▓реЗрдЦ рднреЗрдЬрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ (рджреВрд╕рд░реЗ рдбрдмреНрд▓реВрдПрд╕ рдЪреИрдирд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛)?

рдореИрдВ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдбрдмреНрд▓реНрдпреВрдПрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рд╕реНрддрд░ рдХреЗ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдкрд░ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред

рдЖрдкрдХреЗ рдЙрддреНрддрд░ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!

рдпрд╣рд╛рдБ рдореЗрд░рд╛ рдХреЛрдб рдЕрдм рддрдХ рд╣реИ (рдПрдХ рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ):

const wsClient = new SubscriptionClient(
  graphqlEndpoint,
  {
    reconnect: true,
    connectionParams: () => ({
      headers: {
        'Authorization': 'mytokenAAA',
      },
    }),
  },
  ws,
);
const link = new WebSocketLink(wsClient);

makePromise(execute(link, options)); // that's using token AAA
// how to make another query (execute) using token BBB without creating another link ?

@sulliwane @RyannGalea @jonathanheilmann @ helios1138 рдЯреЛрдХрди/рдХрдиреЗрдХреНрд╢рди рдкреИрд░рд╛рдо рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕реЗ SubscriptionClient рдХреЗ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореЗрд░рд╛ рд╕рд╛рд░ рдпрд╣рд╛рдБ рджреЗрдЦреЗрдВ: https://gist.github.com/cowlicks/71e766164647f224bf15f086ea34fa52

const subscriptionMiddleware = {
  applyMiddleware: function(options, next) {
    // Get the current context
    const context = options.getContext();
    // set it on the `options` which will be passed to the websocket with Apollo 
    // Server it becomes: `ApolloServer({contetx: ({payload}) => (returns options)
    options.authorization = context.authorization;
    next()
  },
};

const server = new ApolloServer({
  context: ({connection, payload, req}) => {
    // whatever you return here can be accessed from the middleware of the SubscriptionMiddleware with
    // applyMiddleware: (options, next) => options.getContext()
    return {authorization: payload.authorization};
  },
});

const link = new WebSocketLink({
    uri: WS_URL,
    webSocketImpl: WebSocket,
    options: {
        reconnect: true,
    }
});

link.subscriptionClient.use([subscriptionMiddleware]);

рдореБрдЭреЗ рдорд┐рд▓рд╛ рдПрдХрдорд╛рддреНрд░ рд╕рдорд╛рдзрд╛рди рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрдВрдж рдХрд░рдирд╛ рд╣реИ ...

рдореИрдВрдиреЗ 1.5 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдПрдХ рд╕рдорд╛рдзрд╛рди рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдерд╛: рдЕрдкреЛрд▓реЛрдЧреНрд░рд╛рдлрдХреНрд▓/рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░#1505ред AFAIK рдпрд╣ рдЕрднреА рднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

@ clayne11 рдЖрдкрдХрд╛ рд╕рдорд╛рдзрд╛рди рдПрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рддрд╛рддреНрдкрд░реНрдп рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдореИрдВ рдХреЛрдгреАрдп рдФрд░ рдпреЛрдЧ-рдЧреНрд░рд╛рдлрдХрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рдЕрдЬреНрдЮрд╛рдд рдХрд╛рд░рдг рд╕реЗ рдореИрдВ рд╕рдВрджрд░реНрдн рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯреЛрдХрди рдирд╣реАрдВ рднреЗрдЬ рд╕рдХрддрд╛ред

рд╕рд░реНрд╡рд░ рдореЗрдВ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдореЗрдВ рдЯреЛрдХрди рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ?
рдореИрдВ рдпреЛрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЗрд╕ рддрд░рд╣ рдореИрдВ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЯреЛрдХрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ

const server = new GraphQLServer({
  typeDefs: './src/schema.graphql',
  middlewares: [permissions],
  resolvers,
  context: ({  connection, ...request }) => {
    if(connection) {
          wsToken: connection.context.authToken
      }
    }
    return ({...request, prisma });
  }
});


const options = {
  port: process.env.PORT || 4000,
  tracing: true,
  subscriptions: {
    path: "/",
    onConnect: async (connectionParams, webSocket) => {
     if (connectionParams.authToken) {
     // I can access this through context
       return {
         authToken: connectionParams.authToken
       };
     }
    }
  }
};


server.express.use(async (req, res, next) => {
  /*
     I want to access authToken here
  */
  next();
});


server.start(options, ({port}) => {
  console.log(`Server is runnning on http://localhost:${port}`);
});

рд╕реЙрдХреЗрдЯ рдмрдВрдж рдХрд┐рдП рдмрд┐рдирд╛ рдореБрдЭреЗ рдЕрдкреЛрд▓реЛ рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдорд┐рд▓рддрд╛ рд╣реИ (рднрд▓реЗ рд╣реА рдпрд╣ рд╕реНрд╡рдпрдВ рдХреЛ рд╕рд╣реА рдХрд░рддрд╛ рд╣реИ, рд╣рдо рдЙрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЖрджрд░реНрд╢ рд╕реЗ рдХрдо рдЯреЛрд╕реНрдЯ рдЕрдзрд┐рд╕реВрдЪрдирд╛рдУрдВ рдХреЗ рд╕рдореВрд╣ рдореЗрдВ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ) рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдЯреЛрдХрди рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╡реЗрдмрд╕реЛрдХреЗрдЯ рдмрдВрдж рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдлрд┐рд░ reconnect: true рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рдлрд┐рд░ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ ... рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдирдВрдд рд▓реВрдк рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рд╕реЛрдЪрд╛ рдХрд┐ рд╕реЙрдХреЗрдЯ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: SubscriptionClient.close() рдХреЗ рдмрдЬрд╛рдп SubscriptionClient.close() SubscriptionClient.client.close() рдкрд░ рдХреЙрд▓ рдХрд░рдХреЗ рдлрд┐рдХреНрд╕реНрдб

рдХреНрдпрд╛ рдПрдХ рдкреВрд░реНрдг рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдХрд┐ 5 рдФрд░ 23 рдкрд╕рдВрдж рдХреЗ рд╕рд╛рде 100 рдмрд┐рдЦрд░реЗ рд╣реБрдП рдЕрд░реНрдз-рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдмрдЬрд╛рдп рдирдП рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рдХреИрд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдП?

рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреА рд╕рджрд╕реНрдпрддрд╛рдПрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ apolloServer.installSubscriptionHandlers(server);
рдФрд░ рдореИрдВ рдЕрдкреЛрд▓реЛрд╕рд░реНрд╡рд░ рдмрдирд╛рддрд╛ рд╣реВрдБ
const apolloServer = new ApolloServer({ schema, introspection: true, subscriptions: { onConnect: (connectionParams, webSocket, context) => { }, onDisconnect: (webSocket, context) => {}, ...there is no OnOperation: () => {}!!! },

рдХреНрдпрд╛ рдСрдкрд░реЗрд╢рди рдкрд░ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдХреЛрдИ рдФрд░ рддрд░реАрдХрд╛ рд╣реИ? рдпрд╛ рдореБрдЭреЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ SubscriptionServer рдмрдирд╛рдирд╛ рд╣реИ рдФрд░ apolloServer.installSubscriptionHandlers(server) рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИ?

рдореИрдВрдиреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛ред рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧ рдЗрди рдирд╣реАрдВ рд╣реИ, рддреЛ рдХреНрд▓рд╛рдЗрдВрдЯ new WebSocket рд▓рд┐рдВрдХ рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рдХрд░рддрд╛ рд╣реИред рдиреАрдЪреЗ рджрд┐рдпрд╛ рдЧрдпрд╛ generateApolloClient рдлрд╝рдВрдХреНрд╢рди SubscriptionClient рдХреЛ рднреА рдЙрдЬрд╛рдЧрд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдХрдиреЗрдХреНрдЯ рд╣реЛрдиреЗ рдкрд░ рдкреНрд░реЗрд╖рдг рдХреЙрд▓ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░реЗрдбрдХреНрд╕ рд╕реНрдЯреЛрд░ рдХреЛ рдмрддрд╛рдПрдВ рдХрд┐ рд╡реЗрдмрд╕реНрдХреЗрдЯ рдХрдиреЗрдХреНрдЯ рд╣реИ)ред

/**
 * Http link
 */
const httpLink = new HttpLink({
  uri: '/graphql'
});

/**
 * Perform actions before each http request
 */
const middlewareLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      authorization: localStorage.getItem('token')
    }
  });
  return forward(operation);
});

const cache = new InMemoryCache();

type ApolloSubscriptionClient<TLoggedIn extends boolean> = TLoggedIn extends true ? SubscriptionClient : undefined;

/**
 * Function to create our apollo client. After login we want to add subscriptions
 * with websocket, so we'll need to recreate the entire client depending on the
 * user being logged in or logged out.
 */
export const generateApolloClient = <TLoggedIn extends boolean>(
  loggedIn: TLoggedIn
): [ApolloClient<NormalizedCacheObject>, ApolloSubscriptionClient<TLoggedIn>] => {
  let link = middlewareLink.concat(httpLink);

  // Only apply our subscription client when the user is logged in
  let subscriptionClient: SubscriptionClient | undefined;
  if (loggedIn) {
    subscriptionClient = new SubscriptionClient('ws://localhost:4001/graphql/ws', {
      reconnect: true,
      connectionParams: () => ({ authorization: localStorage.getItem('token') })
    });

    const wsLink = new WebSocketLink(subscriptionClient);

    link = split(
      ({ query }) => {
        const definition = getMainDefinition(query);
        return (
          definition.kind === 'OperationDefinition' &&
          definition.operation === 'subscription'
        );
      },
      wsLink,
      link
    );
  }

  const apolloClient = new ApolloClient({ link, cache });

  return [apolloClient, subscriptionClient as ApolloSubscriptionClient<TLoggedIn>];
};

рдпрд╣рд╛рдВ ApolloProvider рдШрдЯрдХ рдореЗрдВ рдХреЛрдб рд╣реИ рдЬреЛ generateApolloClient рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:

const GraphqlProvider: React.FC = ({ children }) => {
  const dispatch = useAppDispatch();
  const loggedIn = useUserLoggedIn();
  const [client, setClient] = useState(generateApolloClient(false)[0]);

  useEffect(() => {
    if (loggedIn) {
      const [apolloClient, subscriptionClient] = generateApolloClient(loggedIn);
      subscriptionClient.onConnected(() => {
        dispatch(setSubscriptionConnected(true));
      })
      setClient(apolloClient);
    }
  }, [dispatch, loggedIn]);

  return <ApolloProvider client={client}>{children}</ApolloProvider>;
};

рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЬрдм рднреА рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧ рдЖрдЙрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╕реЗ рд╡рд╛рдкрд╕ рдЖрддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ рдирдпрд╛ рдЯреЛрдХрди рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдереЛрдбрд╝рд╛ рдЕрддрд┐рд░рд┐рдХреНрдд рдХрд╛рдо рд╣реИред рд╡рд┐рдЪрд╛рд░?

@ dorsett85 рдЙрддреНрддрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд░рд┐рдПрдХреНрдЯ/рдиреЗрдХреНрд╕реНрдЯрдЬреЗрдПрд╕ рдРрдкреНрд╕ рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд░реАрдлреНрд░реЗрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕рдВрджрд░реНрдн рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

----------- рдкреНрд░рд╕рдВрдЧ рдПрдкреАрдЖрдИ

export const ApolloClientContext = createContext(undefined);
export const ApolloClientContextProvider: React.FC<{}> = ({ children }) => {
  const [apolloClient, setApolloClient] = useState(client);

  return (
    <ApolloClientContext.Provider value={[apolloClient, setApolloClient]}>{children}</ApolloClientContext.Provider>
  );
};

--------- рдЕрдкреЛрд▓реЛ рдкреНрд░рджрд╛рддрд╛

   <ApolloClientContextProvider>
      <ApolloClientContext.Consumer>
        {([apolloClient, setApolloClient]) => {
          return (
            <ApolloProvider client={apolloClient}>
              <Component {...pageProps} />
            </ApolloProvider>
          );
        }}
      </ApolloClientContext.Consumer>
    </ApolloClientContextProvider>

-------- рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЗ рд╕рд╛рде рдирдП рдХреНрд▓рд╛рдЗрдВрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

export const generateApolloClientWithAuth = (token): ApolloClient<any> => {
 const httpLink = createHttpLink({
  uri: 'http://localhost:5000/graphql',
  fetch,
  credentials: 'include'
});
  const wsLink = process.browser
    ? new WebSocketLink({
        uri: `ws://localhost:5000/graphql`,
        options: {
          reconnect: true,
          connectionParams() {
            console.log('-token', token);
            return {
              authorization: token ? `Bearer ${token}` : ''
            };
          }
        }
      })
    : null;
  const splitLink = process.browser
    ? split(
        ({ query }) => {
          const definition = getMainDefinition(query);
          return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
        },
        wsLink,
        httpLink
      )
    : httpLink;
  return new ApolloClient({
    ssrMode: true,
    link: splitLink,
    connectToDevTools: process.env.NODE_ENV === 'development',
    cache: new InMemoryCache().restore({})
  });
};

----------рд▓реЙрдЧрд┐рди рдШрдЯрдХ

const [apolloClient, setApolloClient] = useContext(ApolloClientContext);

----------- рд▓реЙрдЧрд┐рди рдХрд░рдиреЗ рдкрд░
setApolloClient(generateApolloClientWithAuth(token));

рдорд╣рддреНрд╡рдкреВрд░реНрдг рдиреЛрдЯ: рдмрд╢рд░реНрддреЗ рдЕрдкреЛрд▓реЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб SSR рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реЛ

@kamilkisiela рдХреНрдпрд╛ рд╣рдо рд╕рд┐рд░реНрдл wsLink.subscriptionClient рд╕рджрд╕реНрдп рдХреЛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╕рджрд╕реНрдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд╣реИ рдирд╛?

рдЕрдВрддрд┐рдо рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП get рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

const wsLink = new WebSocketLink({
  uri: CLIENT_CONFIG.websocketUrl,
  options: {
    lazy: true,
    reconnect: true,
    connectionParams: {
      get authorization() {
        return user.getAuthorization();
      },
    },
    connectionCallback: (error) => {
      //@ts-ignore
      if (error?.message === "Authentication Failure!") {
        //@ts-ignore
        //wsLink.subscriptionClient.close(false, false);
      }
    },
  },
});

рдХреНрдпрд╛ рдХреЛрдИ рдореБрдЭ рдкрд░ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░реЗрдЧрд╛ рдЕрдЧрд░ рдореИрдВ рдХрд╣реВрдВ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

const wsLink = process.browser
    ? new WebSocketLink({
        uri: webSocketUri,
        options: {
          reconnect: true,
          connectionParams: () => ({
            token: cookie.get('token'),
          }),
        },
      })
    : null;

рдЕрд░реНрдерд╛рдд
рдмрд╕ рдмрджрд▓ рджреЛ:

connectionParams: {
            token: cookie.get('token'),
},

рдкреНрд░рддрд┐:

connectionParams: () => ({
            token: cookie.get('token'),
}),
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

techyrajeev picture techyrajeev  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

j3ddesign picture j3ddesign  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

tim-soft picture tim-soft  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Morantron picture Morantron  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

MoonTahoe picture MoonTahoe  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ