urql-graphql / urql

The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
https://urql.dev/goto/docs
MIT License
8.68k stars 452 forks source link

initUrqlClient does not send headers to the server #1603

Closed softshipper closed 3 years ago

softshipper commented 3 years ago

Hi all

I am using NextJS and I followed the tutorials on https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#nextjs to set up URQL client for NextJS.

I have created the client as follows:

export const getServerSideProps: GetServerSideProps = withPageAuthRequired({
    async getServerSideProps({req, res}: GetServerSidePropsContext<ParsedUrlQuery>) {
        ...
        const ssrCache = ssrExchange({isClient: false});

        const client = initUrqlClient({
            url: addr.gql,
            exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange],
            fetchOptions: () => {
                return session.idToken === undefined ? {} : {headers: {Authorization: `Bearer ${session.idToken}`}}
            }
        }, false);

     await client.query(PROVIDERS_QUERY).toPromise();
     const extract = ssrCache.extractData();
     console.log(extract);

as the query result I have got:

{ '1928170296': { error: { graphQLErrors: [], networkError: 'Error: Unauthorized' } } }

the GraphQL server is set up as follows:

const server = new ApolloServer({
    schema,
    context: () => new Context()
});
const handler = server.createHandler({path: "/api/graphql"});

export const config = {
    api: {
        bodyParser: false,
    },
};

export default withApiAuthRequired((req: NextApiRequest, res: NextApiResponse<void>)  => {
    console.log(req.headers);
    return handler(req, res);
});

the req.headers does not contain the Authorization header.

{
  host: 'localhost:3000',
  connection: 'keep-alive',
  'content-length': '96',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
  'content-type': 'application/json',
  accept: '*/*',
  'sec-gpc': '1',
  origin: 'http://localhost:3000',
  'sec-fetch-site': 'same-origin',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  referer: 'http://localhost:3000/account',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9',
  cookie: 'appSession=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaWF0IjoxNjIwMDY5NTkxLCJ1YXQiOjE2MjAwNzM3NTgsImV4cCI6MTYyMDE2MDE1OH0..M2bN4euymWXbCfaN.yVdCxi3n310QvSmCMWUGC2fW2Nx51gh3lDEKgw3azDGNy4_psx7Xsr-smjlR2drnp2dD0jJ54N409D5W0URadPs15Y_f_bSQQlIBosJOdRJafj_GbNplCZYCkjfp7Cm4axM-xUxS19pxJK8Fnkd93TeppBtrP1y20lu6XaMLU87pGZJcB9NsW4mRH6Ge-otrUTqhfHeFXkycM4LHSNz9OFi1REKMOxSeMJSX0MvVJR-Vc9uq7nz2IiZzXfFO4t2aNUZed34e3nkp2NCi1QSEExu1wpQCNEq-5ir0KUm3LdV-R7pChLjcIjfWrcxMG8FIOFPDTdt8AAp4iurs7rF0BLtESJhmXS-GkECloViG8bVv0txGOQXw6KfQJGbc38bsquVMoA8URkLeXU7XH8BLe91eo6UZRPyzSoYy9ImQOFuDMeqSeh8_eidGTy_VxJjOHXhBdOOHMowjYllDifCyRxP8-7dg3CM1eTJoeXrS6a16i0UU60dfjTDMlg9Snr4OOSfoZXKS8dFAyR0111O1ctR_MIugLaQ1RLUtclqHmpa-aKjttMBlXtN-DfvAzC2hRPZOMFSMtqDZ3v1FQ0gDRzZjvCde2i1pMkxr5_8_dcZuZEIgL3dy63xKqn0PEj24SgvJ7xEC00uoGvZxImIp1qUoHvxgOG9soQudltpf-M2fwqgJucQR5YajZmywmPDVvMe3V22PM-tdNuB_IbFqEAdFtBUm0LDvVP11LWims8-a1DgHjQwKb8wUd5-viqKytW0r-k4WZUhLUzXHuEV6qS8BCUihO3YI8njyTmAH5y5mSsxNuI4Zl_fAZ2KNTYwj7rtjJHV96TmV0JKyYmEQAFe-zU_s89krR-rLrbEicQhMouXhDAz9OxbEHcaYluyN20jc-NsZYP7PcQfhhdr8eHqQMTC8NbQsYgeet6jr36KqvCg7qASkmkrbRR6xAzVBoHj4O-6qiXcBR0aLT56GDQlirQdCHqplUZypupKYofdTGKQhzixnU4aSxQXyYwJFk0oajHiB5ygYaei2Uoht7qJAR4yP5U5tjJhb-JSnR-e_tUqSC9bfnLwZ_SoUWrjgkDC_VQ_XW4aL9tzv1Vr7CF-tV-5fjk89aebH_wFe92RhnNvQGbp2gR7e8AJptkxChNmcn3mWsKqO5Nda_u1qoagbJ-SfGrD0j_76BREVrG3P120ptjE7r25UIjsHZRxaDrAFXABhf_sVEmYVWzZzYGfjOOsiIEI-Qwn1NKXux5V9TU9GLOPI0_STnRjbYxyrQDr08KxtbA39NhPXDLSkJV6ewAxxhRC6GvbekjdO0hX9Wod18Btj6QlP0e4VeudFFaLXQU9_P57FlgqbdsR1_9k07dJZiv13OndZDxqixy3cmMSxFclcsvqPuzRRDDPjr4lYpBFwXoJdBQdTwmQ_dEiznEi1NXuUAYVG5QAJ0P-NMpaE8ttTCCapLBYz511zEen_5YYVejIPsTpstGOB37G2pXb-RdtN28Da31TDXKq5Gt7g0iXNv_8mN8n39HaSOD1R28QzF23e-mUJHPaK1giv6JRs1onBGV5f1w3yBdyaUjwVqpnIPX9D1Z65PgV9bO51au4_uKD1hYfT8PBeh3h7KbIkICkpctLOP6DhxkeoUEghQUF1wNEBfl_kSqZ9HeFi-UV1EPy1jFsj7-kZnnTSm6so2GAV0us2Ljyg1aYXOfcFsPsWbOkUFJ62zt9NObO7-NcWuK3nvF8F3zwN0_xdRSmFtrx74JwOpst1HFxqdK0gS3LmjsMoDHpKpHenlotM70z9qHRY7n0YuJOGHbr6xDElOxbof6koc36izoI9bQd9KUaM_W5_xQ.Y9vUqu2Od2hTMcIiR4GgHQ'
}

Best regards Softshipper

JoviDeCroock commented 3 years ago

Have you checked whether session.idToken is defined when you enter the fetchOptions? I just did a test with headers: { test: 'x' } which seemed to work fine

Repro: https://codesandbox.io/s/nice-curran-vjrd1?file=/pages/index.js

softshipper commented 3 years ago

@JoviDeCroock I have changed to

 const client = initUrqlClient({
            url: addr.gql,
            exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange],
            fetchOptions: () => {
                return {headers: { test: 'x' }}
            }
        }, false);

and unfortunately, the headers are without test

{
  host: 'localhost:3000',
  connection: 'keep-alive',
  'content-length': '96',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
  'content-type': 'application/json',
  accept: '*/*',
  'sec-gpc': '1',
  origin: 'http://localhost:3000',
  'sec-fetch-site': 'same-origin',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  referer: 'http://localhost:3000/account',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9',
  cookie: 'appSession=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaWF0IjoxNjIwMDY5NTkxLCJ1YXQiOjE2MjAwNzUyMDMsImV4cCI6MTYyMDE2MTYwM30..904-aZyhrY7jhJGl.LdIxJH-ZVyOfPi4ExSuazmL3rSTdn0C1Jy-17psPwA7-bS2txliy4JJXZo-NJcYeBaxNlUWBB3FXPv-zYPJk-mG4-dXtk8IFSVhIPGFCCchmFW2-X0pCCHhTEcDm_Axao7MiCahBeNFhbsaEw_3s8OwQ9ojwdNNBtg0bZBtuBCbC_WB-4-fX9haXyYIidoFiis2-Kh969gkQM8LfKzRIcolTbuJsuroRMgUsxUtcdhNA2jJRUrBSTMVCEw80NBvrq_UjgszDVmlHGVIUQcIpRS11RJzvUYMvw-yng5sfqpgnyDxfbLhjo4OL1f0fPMTqT4IRhrr34oCAYvE3bU-5RXLyJCswo2wqjTAIJCm0NxnG9l8GBeql2uVxd389K2S2jYp8lnCiMBhb2h-wVrUFpf-OqMspGrG-1jOI8n4_iaCz14eGAqq8vUcj9TKBsxgfXIQeTWimBHB8Rr3AG3g3no8v7I5gIX-5_sJAfPhIRSaP_yhWY8QMe1ESJ88gdN8o4zmZ57rBOb9cAg2oxGd8k55BVkEzevjJrIR50eSBdxFxiafzJqC_NaPSQq9Or1SABP8ncWDn7uYSJp65wT4u7qSvMur5aJlQzveuhg-Fd6bn478IZsDMbwL8J4-9uYaRTqIRhTZMpt47oqkto6qrHQu_WB56tc1HpTDx8Zht7tKlOlm1PPo1j9HoVc5v4JQOcwrB3yW74vNl0lWJ03fcQwsHEp-pwthdeVcqTosecs9N8SDEwpdUlFXJW1-u9cxFrndtaGaGd-6c2qNYkjhlH1acSyO3FjCnYqGVCHY1NVVQU2jluBdupNC5KjbeQMQ5rmyfJBYP1d6PZhK8KmUI0eH06Qj5-m-FqW_Eov-62YFsFEhUdQVBSQJ_Xvq9JDYdvMhROtKEYgUxML9CW-NfcmUD85dfdKw6VZoMY96wK_HtA9AH93qZmoVFgfoFf3_Tb3XRLoMBMPV4Q7_jI5dcY36cd4hHDHJ4qgjSVn7AcfGrSbYvzq1m2Dw5clVWfH2DAPSt89Da-XPmUe0jNOFZ3YH3eSjC-dHcxkfdjahzD9WMMEDMkzOI_KsXWjs8PIJyigWl50KHPX4CUIQfvTlAmsieGq7eONC1v6jiJ6BgNorGvrqdypER8f9aRxSpExH25HpqAh6S6CExDJyjszG0fC_aL8W8ctekxBzCZOQW1gUtbkvw0LlnHGZQYOYCjgbHCbp12d9OgotBextq3rUjxVc3-koSa7kWQ5H7dsQAWY6biiT4GOWGfCCuXub9R_H38vVP-tiamsxxR0ldhzEXcijVly4b8iAWZtLFSjezlFUqNCeX7j8-dKEgXdMpMdAscOzOapk-fAfgX84MPVjN-UKQQXzMRx65bGYA20VjtRpN20-tr4-ZQvAoA8JbgtIoQ9dEEVy-v7qtydCi48UsCfolbstQ2UhqIyDT5fhY3b2P33vAEo_r9Oy8nHpKjXgDa0OmvVdqO_UJWMj4CO04uoqIOaHsNTDOAzPu02tAczdpOVgTZ-qx1wJtWAnRB4CLah_LPEK7goh8ylz7FzSlgudZTPsqYw_UhDVaWb3kw9f132hs-c8SSvcORmQr2J1pnAaiP-pJusw7RNUeVDMB7hWxLpcan9EPWDZ6iq0FCbrNhzL6nWvbH2TIaSp7_RlN7uXr0EOWWQYRg4Tjjd3fXCDde2qkjHUi8JEHEjiXr_PMQca9sOSw2OG8aaqH_BfI8qHuMsAqWFWLfr8JpBKYtclIXiiHR-ZchwqqTcwRSkXGv4rKhsgkPblRFScP7WTBMlbdwUwFs3jcAxcPE38mgjl3X1dJoUXOBu26ke1yvZxK9Kdzy_Ahdpn6AA.hgCEdvwat_CWGZC4DB9x0Q'
}
softshipper commented 3 years ago

I have changed the ApolloServer handler to

const server = new ApolloServer({
    schema,
    context: () => new Context()
});
const handler = server.createHandler({path: "/api/graphql"});

export const config = {
    api: {
        bodyParser: false,
    },
};

export default function api(req: NextApiRequest, res: NextApiResponse<void>) {
    console.log(req.headers)
    return handler(req, res);
}

and the header test appears now:

app-ui: {
app-ui:   'content-type': 'application/json',
app-ui:   test: 'x',
app-ui:   accept: '*/*',
app-ui:   'content-length': '96',
app-ui:   'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
app-ui:   'accept-encoding': 'gzip,deflate',
app-ui:   connection: 'close',
app-ui:   host: 'localhost:3000'
app-ui: }

Something is wrong with the withApiAuthRequired method.

Thanks a lot