Apollo-link: рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдЕрдкреЛрд▓реЛ-рд▓рд┐рдВрдХ-рддреНрд░реБрдЯрд┐ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд╣реАрдВ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 2 рджрд┐рд╕ре░ 2017  ┬╖  35рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: apollographql/apollo-link

рд╡рд┐рд╖рдп рдХреЗ рд░реВрдк рдореЗрдВред рдзрдиреНрдпрд╡рд╛рдж

const errorLink = onError(({ networkError }) => {
  if (networkError.status === 401) {
    logout();
  }
})

screen shot 2017-12-03 at 4 49 20 am

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

рддреЛ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВ ...

StatusCode рдорд╛рди рдХреЛ networkError рдкрд░ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ networkError рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЛ рдпрд╣рд╛рдБ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛: https://github.com/apollographql/apollo-link/pull/530

рдЪреВрдВрдХрд┐ networkError рдЕрдм Error | ServerError | ServerParseError рдХрд╛ рдПрдХ рд╕рдВрдШ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЙрди рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдЬреЛ рд╕рдВрдШ рдореЗрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╣реИрдВред statusCode рдкреНрд░рдХрд╛рд░ Error рдкрд░ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред рд╣рдо рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рд╢рд┐рдХрд╛рдпрдд рдХреЗ рдмрд┐рдирд╛ networkError.statusCode рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗ; рд╣рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рдЕрдВрддрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк рдЧрд╛рд░реНрдб рдпрд╛ рдХреБрдЫ рдФрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИрдВрдбрдмреБрдХ рдореЗрдВ рдХрдИ рддрд░реАрдХреЗ рд╕реБрдЭрд╛рдП рдЧрдП рд╣реИрдВ: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type -guards-and-differentiating-types

рдЕрдкрдиреЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП in рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред

  onError: ({ networkError }: ErrorResponse) => {
    if (
      networkError &&
      'statusCode' in networkError &&
      networkError.statusCode === 401
    ) {
      // perform logout stuff
    }
  },

@JoviDeCroock рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░рдирд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ?

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

рдЬреИрд╕рд╛ рдХрд┐ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ "рд▓рд╛рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓" рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рдХреЛрдИ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдбрд╛рдЙрди рд╣реИ)ред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдХреЛрдИ рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб рдирд╣реАрдВ рджрд┐рдЦреЗрдЧрд╛ред рдЕрдЧрд░ рдореИрдВ рдЧрд▓рдд рд╣реВрдВ рдХреГрдкрдпрд╛ рдореБрдЭреЗ рд╕рд╣реАред

рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдРрд╕реА рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЯреЗрдХреНрд╕реНрдЯ рд╕рдВрджреЗрд╢ рд░рдЦрдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рд╣реИ - рдХреБрдЫ рдРрд╕рд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕реЗ рдЕрдзрд┐рдХ рдЖрд╕рд╛рдиреА рд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ (рдЬреИрд╕реЗ рддреНрд░реБрдЯрд┐ рдХреЛрдб)ред

рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдХреНрд░реЛрдо рдЗрдВрд╕реНрдкреЗрдХреНрдЯрд░ рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдЯреИрдЧ рдореЗрдВ рдЕрдиреБрд░реЛрдз рднреЗрдЬ рд░рд╣рд╛ рдерд╛ рдФрд░ (401) рдореЗрдВред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ #218 рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ (рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ ..)

рд╕рд╛рде рд╣реА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИред networkError.status рдпрд╛ networkError.statusCode рдЧрд╛рдпрдм рд╣реИрдВ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╕реНрддреБ рдЧрд╛рдпрдм рд╣реИред рдиреЗрдЯрд╡рд░реНрдХ рдкрд░рдд рдореЗрдВ HTTP рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рднреА рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдорд┐рд▓реА рд╣реИред рдЗрд╕реЗ рдирд╡реАрдирддрдо рд░рд┐рд▓реАрдЬрд╝ рдореЗрдВ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рднреА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдЖ рд░рд╣реА рд╣реИред

рдЗрд╕ @jbaxleyiii рдкрд░ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░?

рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдХрд░ рдЕрдлрд╝рд╕реЛрд╕ рд╣реБрдЖ рдХрд┐ @akrigline рдФрд░ @bogdansoare рдХреЛ рдЕрднреА рднреА рдЗрд╕рд╕реЗ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИ! рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рдЕрднреА #364 рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдБред рдЗрд╕ рдмреАрдЪ, рдХреНрдпрд╛ рдЖрдк рддреНрд░реБрдЯрд┐ рдХреЛ рдкреБрди: рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХреЛрдб рд╕реИрдВрдбрдмреЙрд╕ рдХреЛ рдмрдирд╛ рдпрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╛ рдЗрд╕рд╕реЗ рднреА рдмреЗрд╣рддрд░ рдПрдХ рдЕрд╕рдлрд▓ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде рдкреАрдЖрд░ рдЦреЛрд▓реЗрдВ?

рдХреЛрдИ рдЦрдмрд░?

рд╕рд╛рде рд╣реА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реЛрдиреЗ рдкрд░, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЦрд╛рд▓реА рд╣реИ рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдПрд░рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рдХреЛрдИ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ networkError рд╕рдВрдкрддреНрддрд┐ рднреА рдирд╣реАрдВ рдорд┐рд▓рддреА рд╣реИ:
screen shot 2018-05-07 at 13 01 56

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ #475

рдореИрдВрдиреЗ Error рдкреНрд░рдХрд╛рд░ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдХреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди рд╣реИ рдФрд░ рд╣рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕реБрдзрд╛рд░реЛрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреА рд╣реЛрдЧреАред @ рдЗрд╡рд╛рдВрд╕

рдпрд╣рд╛рдБ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИ!

рд╣рдордиреЗ рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬреЛ networkError рд▓рд┐рдЦрд╛ рдерд╛, рд╡рд╣ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдереАред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЗрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ statusCode рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдореЗрдВ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдмрдирд╛рдиреЗ рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред (_рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд░ рд╕рдВрдмрдВрдзреА рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рддреЛ рдЖрдк statusCode _ рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ)ред

screen shot 2018-05-07 at 20 38 09

рдЯрд╛рдЗрдкрдлреЗрд╕ рддреНрд░реБрдЯрд┐ рдЕрднреА рдмрд╛рдХреА рд╣реИ!

рдпрджрд┐ рдЖрдк рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ networkError рдореЗрдВ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:

export interface ErrorResponse {
  graphQLErrors?: GraphQLError[];
  networkError?: Error;
  response?: ExecutionResult;
  operation: Operation;
}

рдФрд░ Error рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

interface Error {
    name: string;
    message: string;
    stack?: string;
}

рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ statusCode рдпрд╣рд╛рдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ networkError.statusCode рдЬреИрд╕рд╛ рдХреБрдЫ рдирд╣реАрдВ рдХрд╣ рд╕рдХрддреЗред

рдореЗрд░рд╛ рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди

рд╣рдореЗрдВ networkError рдХреЛ any рд░реВрдк рдореЗрдВ рдбрд╛рд▓рдирд╛ рд╣реИ рдФрд░ рд╣рдо рдЗрд╕реЗ рдПрдХ рдЦрд╛рд▓реА object рд░реВрдк рдореЗрдВ рднреА рдмрдирд╛рддреЗ рд╣реИрдВред

const afterWareLink = onError(({operation, response, graphQLErrors = {}, networkError = {} as any}) => {
    const status: number = networkError && networkError.statusCode ? networkError.statusCode : null;
    debugHelper.error('apolloError', {
        operation,
        response,
        graphQLErrors,
        networkError,
        status,
    });

    // Do your job
    // if (status && HTTPExceptions[status])
    //     redirectService.redirectWithReload(`/error/${status}`);
});

рдЙрдкрд░реЛрдХреНрдд afterWareLink рдХреЛрдб рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╣рдореЗрдВ 400 рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреЗ рд╕рд╛рде рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рдФрд░ рдЕрдм рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗ:

screen shot 2018-05-07 at 20 28 03

рдпрд╣рд╛рдБ рдореЗрд░реА рдЕрдкреЛрд▓реЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░рд┐рднрд╛рд╖рд╛ рд╣реИ:

import {ApolloLink, from} from 'apollo-link';
import {application} from '../../constants/application';
import {ApolloClient} from 'apollo-client';
import {InMemoryCache} from 'apollo-cache-inmemory';
import {HttpLink} from 'apollo-link-http';
import {tokenStorage} from '../middleware';
import {debugHelper} from '../helpers/debugHelper';
import {onError} from 'apollo-link-error';
import {apolloCache} from './apolloCache';
import fetch from 'unfetch';

const API = new HttpLink({
    uri: application.API.URL,
    fetch: fetch
});

const cache = new InMemoryCache({
    dataIdFromObject: (object: any) => apolloCache.getID(object)
});

const afterWareLink = onError(({operation, response, graphQLErrors = {}, networkError = {} as any}) => {
    const status: number = networkError && networkError.statusCode ? networkError.statusCode : null;
    debugHelper.error('apolloError', {
        operation,
        response,
        graphQLErrors,
        networkError,
        status,
    });

    // Do your job
    // if (status && HTTPExceptions[status])
    //     redirectService.redirectWithReload(`/error/${status}`);
});

const middleWareLink = new ApolloLink((operation, forward) => {
    const token = tokenStorage.get();
    operation.setContext(context => ({
        ...context,
        headers: {
            ...context.headers,
            token: token ? token.token : '',
        },
    }));

    return forward(operation);
});

export const apolloClient = new ApolloClient({
    link: from([
        middleWareLink,
        afterWareLink,
        API
    ]),
    cache: cache,
});

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред

рдпрджрд┐ рдЖрдк рдиреЛрдб рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╕рдВрджрд░реНрдн рд╕реЗ рдЖрдкрдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ рддреЛ рдЖрдк рдЗрд╕реЗ рдЬреЛрдбрд╝рдХрд░ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ; рдЕрдкрдиреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ ctx.res.status(401); ред
рдЕрдм рдЕрдкреЛрд▓реЛ-рд▓рд┐рдВрдХ-рдПрд░рд░реНрд╕ рдФрд░ рдЕрдкреЛрд▓реЛ-рд▓рд┐рдВрдХ-рд░реАрдЯреНрд░реА рджреЛрдиреЛрдВ рдиреЗрдЯрд╡рд░реНрдХ рдПрд░рд░реНрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдПрд░рд░ рдХреЛ рдкрд┐рдХ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗред

рдпрд╣рд╛рдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдореИрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕реНрдЯрдо рд╕реНрдХреАрдорд╛ рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдорд╛рдгрд┐рдд рд╣реИ;

import { SchemaDirectiveVisitor } from "graphql-tools";
import { defaultFieldResolver } from "graphql";
import { createError } from "apollo-errors";

const AuthError = createError("AuthError", {
  message: "Not authorized"
});

export class IsAuthenticatedDirective extends SchemaDirectiveVisitor {
  visitObject(type) {
    this.ensureFieldsWrapped(type);
  }
  visitFieldDefinition(field, details) {
    this.ensureFieldsWrapped(details.objectType);
  }

  ensureFieldsWrapped(objectType) {
    if (objectType._authFieldsWrapped) return;
    objectType._authFieldsWrapped = true;

    const fields = objectType.getFields();
    Object.keys(fields).forEach(fieldName => {
      const field = fields[fieldName];
      const { resolve = defaultFieldResolver } = field;
      field.resolve = async function(...args) {
        const ctx = args[2];
        const result = await resolve.apply(this, args);
        if (ctx.req.user) {
          return result;
        } else {
          ctx.res.status(401);
          return null;
        }
      };
    });
  }
}

рддрдп рд╣реБрдЖ рдпрд╛ рдирд╣реАрдВ? рдореИрдВ рдЕрднреА рднреА рдиреЗрдЯрд╡рд░реНрдХ рдПрд░рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдХреЛрдб рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪ рд╕рдХрддрд╛ред

@artsiompeshko
рдореИрдВ рдЗрд╕реЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ:

const networkErrorLink = onError(({networkError, operation, forward}: ErrorResponse) => {
  if (networkError) {
    switch (networkError['statusCode']) {
      case 401:
      case 422:
        if (window.location.pathname !== '/login') {
          Logger.error('Unauthorized or stale Authorization Session. Reloading page...')
          window.history.go()
        }
        break
    }
  }
  return forward(operation)
})

рдЗрд╕ рдкрд░ рдХреЛрдИ рднреА рд╕рдорд╛рдЪрд╛рд░? рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ред рдореЗрд░реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдб рдореЗрдВ рдХреЛрдИ networkError.statusCode рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред

@goldenbearkin рд╢рд╛рдпрдж рд╣рдо рдЗрд╕реЗ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░ рд░рд╣реЗ рд╣реИрдВ?

рд╣рдореЗрдВ рддреНрд░реБрдЯрд┐ рдореЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреА рдЪрд╛рд╣рд┐рдП, рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рд╕реНрдерд┐рддрд┐ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдпрд╣ networkError рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ HttpErrorResponse рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рд╣реИ рдЬрд┐рд╕рдореЗрдВ status рд╕рдВрдкрддреНрддрд┐ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╣рдореЗрд╢рд╛ 0 рдЬрд╣рд╛рдВ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдореВрд▓ рд╕реНрдерд┐рддрд┐ рдХреЛрдб 401 рдпрд╛ 403 рд╣реЛрддрд╛ рд╣реИ

@lvlohammadi
рдХреНрдпрд╛ рдЧреНрд░рд╛рдлрд╝QLErrors рдХреЗ рд▓рд┐рдП рднреА рд╡рд╣реА рд╕рдорд╛рдзрд╛рди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдореИрдВ рдЖрдкрдХреЗ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдиреЗрдЯрд╡рд░реНрдХ рдПрд░рд░ рдХреЗ рд▓рд┐рдП рд╕реНрдерд┐рддрд┐ рдХреЛрдб рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ - 504 рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ред рд▓реЗрдХрд┐рди рдЬрдм рдкреНрд░рдорд╛рдгреАрдХрд░рдг рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдореБрдЭреЗ 401 рдХреЗ рдЧреНрд░рд╛рдлрд╝QLError рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреА рдЙрдореНрдореАрдж рд╣реИред рд▓реЗрдХрд┐рди рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ 'graphQLErrors = {} as any' рд╡рд┐рдХрд▓реНрдк рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдХреЛрдИ рдлрд╛рдпрджрд╛ рдирд╣реАрдВ рд╣реБрдЖред

рдпрд╣ рдЕрдЬреАрдм рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ statusCode рд╕рдВрдкрддреНрддрд┐ рд╣реИ networkError ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдРрд╕реА рдХреЛрдИ рд╕рдВрдкрддреНрддрд┐ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП TS рдпрд╣рд╛рдБ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред

const errorLink = onError(({ networkError, graphQLErrors, response }: ErrorResponse) => {
  if (graphQLErrors) {
    graphQLErrors.map(({ message, locations, path }: GraphQLError) => {
      showError(message);
    });
  }

  // @ts-ignore
  console.log('statusCode', networkError.statusCode); // outputs 401

  if (networkError) {
    showError(networkError.message);
  }
});

рд╕рд░реНрд╡рд░ рдкрд░ рдореИрдВ koa рдФрд░ koa-passport рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдпрд╣рд╛рдВ рдХреЛрдб рдХрд╛ рд╕рдВрдмрдВрдзрд┐рдд рднрд╛рдЧ рд╣реИ:

app.use(mount(graphQlPath, passport.authenticate('jwt', { session: false })));

рдЪреВрдВрдХрд┐ рдпрд╣ рдореБрджреНрджрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреБрд░рд╛рдирд╛ рд╣реИ, рдореИрдВ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдЕрднреА рднреА рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд┐рдд рд╣реИрдВ рддреЛ рдмреЗрдЭрд┐рдЭрдХ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓реЗрдВ рдФрд░ рдореИрдВ рдЖрдкрд╕реЗ рдЬрд▓реНрдж рд╕реЗ рдЬрд▓реНрдж рд╕рдВрдкрд░реНрдХ рдХрд░реВрдВрдЧрд╛ред

@JoviDeCroock рдЕрднреА рдЙрд╕ рдореБрджреНрджреЗ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ ... рддреЛ, рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рд╣реИ? рдореИрдВ рдиреЗрдЯрд╡рд░реНрдХ рдПрд░рд░ рд╕реЗ рддреНрд░реБрдЯрд┐ рд╕реНрдерд┐рддрд┐ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реВрдВ?

рдареАрдХ рд╣реИ, рддреЛ рдЖрдк рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рд╣реИ (рдХреЛрдИ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реИ?) рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЛрдб/рд╕реНрдерд┐рддрд┐ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИ?

рдХреНрдпрд╛ рдпрд╣ рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рддреНрд░реБрдЯрд┐ рд╣реИ рдпрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИ? рдХреНрдпрд╛ рдЖрдк рдЗрд╕реЗ рдкреБрди: рдкреЗрд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

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

рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рд╕рд░реНрд╡рд░ рд╕реЗ рд╕реНрдерд┐рддрд┐ рдХреИрд╕реЗ рднреЗрдЬ рд░рд╣рд╛ рд╣реВрдВред рдореИрдВ рдореВрд▓ рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рднреА рдЧреНрд░рд╛рдлрд╝рдХреНрдпреВрдПрд▓ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЛ рд╢реЙрд░реНрдЯрдХрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдмрд╕ рдЗрд╕рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ:
res.status(404).send("The resource you are looking for cannot be found")

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рдХреЗрд╡рд▓ TypeError: Failed To Fetch ред рдХреНрдпрд╛ рдпрд╣ рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рдХреЗ рдХрд╛рд░рдг рд╣реИ?

@JoviDeCroock рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореИрдВрдиреЗ 401 рдпрд╛ 403 рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдЧреНрд░рд╛рдлрд╝рдХрд▓ рдХреЛрдб рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдЧрдбрд╝рдмрдбрд╝ рдХрд┐рдпрд╛ред рд╣рдо рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдореИрдВрдиреЗ рдЬреЛ рдХрд┐рдпрд╛ рд╡рд╣ рд╣рд░ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ 401 рд╡рд╛рдкрд╕ рджреЗ рд░рд╣рд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рднреА OPTION рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ 401 рд╣реЛ рдЧрдИ, рдХреНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╢рд╛рдпрдж рдЗрд╕реА рд╡рдЬрд╣ рд╕реЗ рдореИрдВ рд╕реНрдЯреЗрдЯрд╕ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рджреЗрдЦ рдкрд╛ рд░рд╣рд╛ рдерд╛ред рдХреЛрдб рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб рджреЗрдЦ рдкрд╛ рд░рд╣рд╛ рд╣реВрдВ

рдЕрджреНрдпрддрди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж @ dimitriy-k рдпрд╣ рд╕реБрдирдХрд░ рдЦреБрд╢реА рд╣реБрдИ рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЧрдИ рд╣реИред

@AlbertoPL рдХреЗ рд▓рд┐рдП , рдореИрдВ рдЖрдЬ рд░рд╛рдд рдЖрдкрдХреА рд╕рдорд╕реНрдпрд╛ рдкрд░ рдзреНрдпрд╛рди рджреВрдВрдЧрд╛ред рдпрджрд┐ рдЖрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЯрд┐рдкреНрдкрдгреА рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред

@JoviDeCroock рдПрдХ рдирдЬрд╝рд░
res.status(426).send()

рдХреНрд░реЛрдо рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдЯреИрдм рдореЗрдВ рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ рдХрд┐ /graphql рдПрдВрдбрдкреЙрдЗрдВрдЯ 426 рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдФрд░ рдЙрдЪрд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ (рдЕрдкрдЧреНрд░реЗрдб рдЖрд╡рд╢реНрдпрдХ) рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗ рд░рд╣рд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рдЕрднреА рднреА рдХреЗрд╡рд▓ TypeError: Failed to Fetch рдЬрдм apollo-link-error рд╕реЗ onError рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдЧрд░ рдореБрдЭреЗ рд╕рд╣реА рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ (рдпрд╛ рд╕рдВрджреЗрд╢ рднреА рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛)ред

рдареАрдХ рд╣реИ, рдпрд╣ рдХреБрдЫ рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ рдЬрд╛рдирдХрд╛рд░реА рд╣реИред рд╣рдореЗрдВ рдЗрд╕реЗ рдХрд┐рд╕реА рднреА рддрд░рд╣ рдбреАрдмрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпрд╛ рдЖрдк рдЗрд╕реЗ рдорд╣рд╕реВрд╕ рдХрд░рддреЗ рд╣реИрдВ рдпрд╛?

рд╣рд╛рдБ, рдореИрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдБред рдореИрдВ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдорджрдж/рд╕реБрдЭрд╛рд╡реЛрдВ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддрд╛ рд╣реВрдВред

рддреЛ рдмрд╕ рдХреНрд░реЛрдо рдХреЗ рдбреАрдмрдЧрд░ рдореЗрдВ рдХреЛрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрджрдо рдЙрдард╛рддреЗ рд╣реБрдП, рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рджреЛрдиреЛрдВ apollo-link-batch-http рдФрд░ apollo-link-http рдлрд╝реЗрдЪрд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ (рдпрд╛ рддреЛ рдПрдХ рд▓рд┐рдВрдХ рд╡рд┐рдХрд▓реНрдк рдпрд╛ рдХреБрдЫ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдореИрдВрдиреЗ рджреЛрдиреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА):

fetcher(chosenURI, options)
    .then(function (response) {
        operations.forEach(function (operation) { return operation.setContext({ response: response }); });
        return response;
    }).then(parseAndCheckHttpResponse(operations))

рдпрд╣ рдХрд┐рд╕реА рднреА рддрддреНрдХрд╛рд▓реАрди рдмреНрд▓реЙрдХ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдХреИрдЪ рдмреНрд▓реЙрдХ рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИред рддрдм рддрдХ рддреНрд░реБрдЯрд┐ "рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓" рдкрд░ рд╕реЗрдЯ рд╣реЛ рдЪреБрдХреА рд╣реЛрддреА рд╣реИред рдХреЛрдИ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред

рд╣рдореЗрдВ рдЬрд╛рдВрдЪрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдпрд╣рд╛рдВ рдЧрд▓рдд рд╣реИ:

https://github.com/apollographql/apolo-link/blob/master/packages/apollo-link-http-common/src/index.ts#L118

рдореИрдВ рдЗрд╕ рд╕рдкреНрддрд╛рд╣ рдХреЗ рдЕрдВрдд рдореЗрдВ рдПрдХ рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдБрдЧрд╛, рдХрд╛рдо рдкрд░ рдПрдХ рдмрд╣реБрдд рд╡реНрдпрд╕реНрдд рдХрд╛рд░реНрдпрдХреНрд░рдо рдПрдЯреАрдПрдо рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдгред

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

рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рд░ рдмрд╛рд░ рдЬрдм рдореИрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдореИрдВ apollo-server рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдпрд╣ рдареАрдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдпрд╛ рдХреБрдЫ рдЕрд▓рдЧ рд╣реЛред рдЗрд╕рд▓рд┐рдП рдореЗрд░реЗ рд▓рд┐рдП рдмрд┐рдирд╛ рд╕рд░реНрд╡рд░ рдХреЗ рдкреНрд░рдЬрдирди рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдХрдард┐рди рд╣реИ

рдЕрдЧрд░ рдпрд╣ рдорджрдж рдХрд░реЗрдЧрд╛, рддреЛ рдпрд╣рд╛рдВ рд╣рдорд╛рд░рд╛ рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░ рд╣реИ (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ)ред CreateGraphQLSchema рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЕрдкреЛрд▓реЛ рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИ:

const { ApolloServer, gql } = require("apollo-server-express");

const collectFragments = container => {
  return container
    .$list()
    .map(component => container[component])
    .join("\n");
};

const mergeObjects = container => {
  const types = container.$list().map(k => container[k]);
  return _.merge(...types);
};

function CreateGraphQLSchema(
  schema,
  queries,
  mutations,
  subscriptions,
  resolvers,
  graphqlFormatError,
) {
  const graphQlSchema = gql`
    ${collectFragments(schema.enum)}

    ${collectFragments(schema.type)}

    type Query {
      ${schema.Query}
    }

    ${collectFragments(schema.input)}

    type Mutation {
      ${schema.Mutation}
    }

    type Subscription {
      ${schema.Subscription}
    }

    schema {
      query: Query
      mutation: Mutation
      subscription: Subscription
    }
  `;

  const resolverMap = {};
  resolverMap.Query = mergeObjects(queries);
  resolverMap.Mutation = mergeObjects(mutations);
  resolverMap.Subscription = mergeObjects(subscriptions);
  resolvers.$list().forEach(type => (resolverMap[type] = resolvers[type]));

  return new ApolloServer({
    typeDefs: graphQlSchema,
    resolvers: resolverMap,
    context: ({ req, res }) => {
      return { req, res, user: req.user };
    },
    formatError: graphqlFormatError,
    playground: process.env.NODE_ENV !== "production",
  });
}

@AlbertoPL рдореИрдВ рднреА рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ред рдпрд╣ рдПрдХ CORS рдореБрджреНрджрд╛ рдирд┐рдХрд▓рд╛, рдЕрдкреЛрд▓реЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдирд╣реАрдВред

рдЬрдм рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ рдпрд╛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ CORS рдХреЛ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рднреНрд░реВрдг () рд╡рд╛рджрд╛ рдПрдХ TypeError рдХреЗ рд╕рд╛рде рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рджреЗрдЧрд╛

рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЕрдиреБрд░реЛрдз рдХреЛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╕рдордп рдЖрдк рдЙрдЪрд┐рдд рд╢реАрд░реНрд╖рд▓реЗрдЦ рд╡рд╛рдкрд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореИрдВ рдПрдкреАрдЖрдИ рдЧреЗрдЯрд╡реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рдерд╛ рдФрд░ рдореЗрд░рд╛ рдХрд╕реНрдЯрдо рдСрдерд░рд╛рдЗрдЬрд╝рд░ рдЕрдиреБрд░реЛрдз рдХреЛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд░рд╣рд╛ рдерд╛, рд▓реЗрдХрд┐рди Access-Control-Allow-Origin рд╣реЗрдбрд░ рд╕рдВрд▓рдЧреНрди рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рдерд╛ред рдореИрдВ рддреИрдирд╛рддреА рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдХреНрд▓рд╛рдЙрдбрдлреЙрд░реНрдореЗрд╢рди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: https://serverless.com/blog/cors-api-gateway-survival-guide/#cors -with-custom-authorizersред

рдЕрдЪреНрдЫрд╛ рдЦреЛрдЬ @ рдХреНрд░рд┐рд╕-рдлреАрд╕реНрдЯ!
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ Access-Control-Allow-Origin рд╣реЗрдбрд░ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдЕрдкреЛрд▓реЛ-рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реЛ рдЧрдпрд╛

Express.js рдореЗрдВ, рдореИрдВрдиреЗ рдмрд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд┐рдпрд╛:

res.set('Access-Control-Allow-Origin', '*').status(401).send()

рдПрдХреНрд╕реЗрд╕-рдХрдВрдЯреНрд░реЛрд▓-рдЕрдиреБрдорддрд┐-рдЙрддреНрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рдВрднрд╛рд╡рд┐рдд рд╕реБрд░рдХреНрд╖рд╛ рдЬреЛрдЦрд┐рдо рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ? https://stackoverflow.com/questions/12001269/what-are-the-security-risks-of-setting-access-control-allow-origin

рддреЛ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВ ...

StatusCode рдорд╛рди рдХреЛ networkError рдкрд░ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ networkError рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЛ рдпрд╣рд╛рдБ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛: https://github.com/apollographql/apollo-link/pull/530

рдЪреВрдВрдХрд┐ networkError рдЕрдм Error | ServerError | ServerParseError рдХрд╛ рдПрдХ рд╕рдВрдШ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЙрди рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдЬреЛ рд╕рдВрдШ рдореЗрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рд╣реИрдВред statusCode рдкреНрд░рдХрд╛рд░ Error рдкрд░ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред рд╣рдо рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рд╢рд┐рдХрд╛рдпрдд рдХреЗ рдмрд┐рдирд╛ networkError.statusCode рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗ; рд╣рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рдЕрдВрддрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк рдЧрд╛рд░реНрдб рдпрд╛ рдХреБрдЫ рдФрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИрдВрдбрдмреБрдХ рдореЗрдВ рдХрдИ рддрд░реАрдХреЗ рд╕реБрдЭрд╛рдП рдЧрдП рд╣реИрдВ: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type -guards-and-differentiating-types

рдЕрдкрдиреЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП in рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред

  onError: ({ networkError }: ErrorResponse) => {
    if (
      networkError &&
      'statusCode' in networkError &&
      networkError.statusCode === 401
    ) {
      // perform logout stuff
    }
  },

@JoviDeCroock рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░рдирд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ?

@mrkrli рдзрдиреНрдпрд╡рд╛рджред рд╕рднреНрдп рд╕рдорд╛рдзрд╛рдиред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

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

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

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

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

steffenmllr picture steffenmllr  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Kisepro picture Kisepro  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ