Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug]: Next.js Server Components - Missing Headers in Outbound Requests #54

Closed
3 tasks done
DebugNinjaSlayer opened this issue Feb 12, 2025 · 5 comments · Fixed by #57
Closed
3 tasks done

[bug]: Next.js Server Components - Missing Headers in Outbound Requests #54

DebugNinjaSlayer opened this issue Feb 12, 2025 · 5 comments · Fixed by #57
Assignees
Labels
issue: bug Issue reporting a bug status: confirmed The issue has been confirmed or reproduced manually by a team member

Comments

@DebugNinjaSlayer
Copy link

Bug Description

Hi community!

I'm encountering a very strange issue with Next.js Server Components and the official Strapi JS library (@strapi/sdk-js). When I make requests to my Strapi backend from within a Server Component using the Strapi JS library, the Content-Type and Authentication headers are mysteriously missing in the outbound request. This results in a 403 error from Strapi.

Here's the breakdown of what I've observed:

Server Components + Strapi JS Library: Headers (Content-Type, Authentication) are missing in the request. Strapi returns 403.

Client Components + Strapi JS Library: Headers are present, request is successful, Strapi works as expected.

Direct Node.js script (using this demo outside Next.js) + Strapi JS Library: Headers are present, request is successful, Strapi works as expected.

Server Components + fetch or axios: Headers are present, request is successful, Strapi works as expected.

This isolates the issue specifically to the combination of Next.js Server Components and the Strapi JS library. It's not a general networking problem in Server Components because fetch and axios work fine. It's also not a fundamental issue with the Strapi JS library itself, as it works in other contexts.

Steps to Reproduce

Steps to Reproduce

  1. clone this simple demo repo: https://github.com/DebugNinjaSlayer/missing-header-demo
  2. yarn
  3. yarn dev
  4. access http://127.0.0.1:3000
  5. there should be error logs on server like this
Running with api token e4525f6cb23fd4c477b0071d067b31701f481678d1f022bf3eddbffb3e3494830cfe5feab5fa09f7a33ecd27b105a20bd22f3028250afb67dad85770f7e687b5b3e0697e4a3eac4362782d074157521c78512d9d2d1b4900b072813942eabf991addfa9ba5c35c530b3949e0dd05a64296eadca877cdc2360b54609e3529c470
Error [HTTPForbiddenError]: Request failed with status code 403 Forbidden: GET http://localhost:1337/api/categories
    at <unknown> (HTTPForbiddenError: Request failed with status code 403 Forbidden: GET http://localhost:1337/api/categories)
    at async Home (src/app/page.tsx:17:17)
  15 |     const categories = sdk.collection("categories");
  16 |
> 17 |     const docs = await categories.find();
     |                 ^
  18 |     console.dir(docs, { depth: null });
  19 |   } catch (error) {
  20 |     console.log(error); {
  response: Response {
    status: 403,
    statusText: 'Forbidden',
    headers: Headers {
      'content-security-policy': "connect-src 'self' https:;img-src 'self' data: blob: market-assets.strapi.io course-hosting-kit-dev.ccdf58dba7baa04c265641c25962951d.r2.cloudflarestorage.com;media-src 'self' data: blob: market-assets.strapi.io course-hosting-kit-dev.ccdf58dba7baa04c265641c25962951d.r2.cloudflarestorage.com;frame-src 'self' youtube.com www.youtube.com vimeo.com *.vimeo.com facebook.com www.facebook.com course-hosting-kit-dev.ccdf58dba7baa04c265641c25962951d.r2.cloudflarestorage.com;default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline'",
      'referrer-policy': 'no-referrer',
      'strict-transport-security': 'max-age=31536000; includeSubDomains',
      'x-content-type-options': 'nosniff',
      'x-dns-prefetch-control': 'off',
      'x-download-options': 'noopen',
      'x-frame-options': 'SAMEORIGIN',
      'x-permitted-cross-domain-policies': 'none',
      vary: 'Origin',
      'access-control-allow-origin': '',
      'access-control-allow-credentials': 'true',
      'content-type': 'application/json; charset=utf-8',
      'x-powered-by': 'Strapi <strapi.io>',
      'content-length': '95',
      date: 'Wed, 12 Feb 2025 06:50:10 GMT',
      connection: 'keep-alive',
      'keep-alive': 'timeout=5'
    },
    body: undefined,
    bodyUsed: false,
    ok: false,
    redirected: false,
    type: 'basic',
    url: 'http://localhost:1337/api/categories'
  },
  request: Request {
    method: 'GET',
    url: 'http://localhost:1337/api/categories',
    headers: Headers {
      'Content-Type': 'application/json',
      Authorization: 'Bearer e4525f6cb23fd4c477b0071d067b31701f481678d1f022bf3eddbffb3e3494830cfe5feab5fa09f7a33ecd27b105a20bd22f3028250afb67dad85770f7e687b5b3e0697e4a3eac4362782d074157521c78512d9d2d1b4900b072813942eabf991addfa9ba5c35c530b3949e0dd05a64296eadca877cdc2360b54609e3529c470'
    },
    destination: '',
    referrer: 'about:client',
    referrerPolicy: '',
    mode: 'cors',
    credentials: 'same-origin',
    cache: 'default',
    redirect: 'follow',
    integrity: '',
    keepalive: false,
    isReloadNavigation: false,
    isHistoryNavigation: false,
    signal: [AbortSignal]
  }
}
 GET / 200 in 142ms
 GET /favicon.ico?favicon.45db1c09.ico 200 in 23ms

It's worthy noting that there are Authorization header in the error log but when capturing requests with Wireshark, the headers are actually missing

I also created a repo shows it works well with client component https://github.com/DebugNinjaSlayer/client-component-demo

Expected Behavior

Given these observations, I'm wondering if there's something I might be misunderstanding about how to use the Strapi JS library within Next.js Server Components.

Is it expected to work correctly in this environment?

Or could this behavior point to a potential incompatibility or bug within the library itself when used in Server Components?

Any guidance on proper usage or confirmation regarding expected compatibility would be incredibly helpful. Thank you!

Version

1.0.0

Operating System

MacOS

Runtime Environment

Node.js

Logs

Media

this is what the missing header requests like

Image

and this is the requests sent from client components or typescript script

Image

Confirmation Checklist

  • I have checked the existing issues
  • I agree to follow this project's Code of Conduct
  • I would like to work on this issue
@DebugNinjaSlayer DebugNinjaSlayer added issue: bug Issue reporting a bug status: to be confirmed The issue needs to be reproduced or confirmed by a team member labels Feb 12, 2025
@Convly
Copy link
Member

Convly commented Feb 14, 2025

Hi, thanks for opening this issue, and thank you for the detailed reproduction steps and time spent doing some research; it's gonna help us a lot!

I'm gonna try and reproduce the issue, see if we can understand why it happens and then come back to you!

@Convly
Copy link
Member

Convly commented Feb 14, 2025

Some update there. I've managed to reproduce your issue. It seems like the patched fetch instance that next is creating to intercept HTTP requests is wiping out the headers defined by the Strapi client.

I've spent the last few hours trying different approaches to debug that behavior, but so far no luck 😕

To confirm the issues come from the patched fetch, I've forced the SDK HTTP client to use another fetch implementation (undici) which isn't caught by Next... it worked as expected, and headers were preserved.

I'll continue looking into this next week. If anyone has any ideas on how we can approach this, I'm all ears, I'm by no mean a Next expert.

@Convly Convly added status: confirmed The issue has been confirmed or reproduced manually by a team member and removed status: to be confirmed The issue needs to be reproduced or confirmed by a team member labels Feb 14, 2025
@Convly
Copy link
Member

Convly commented Feb 14, 2025

Alright, so we finally understood the issue, and I've opened a PR with a fix at #57.

I'll let you know whenever it gets merged and we'll release a new version with the fix as soon as possible!

@Convly Convly self-assigned this Feb 14, 2025
@DebugNinjaSlayer
Copy link
Author

Alright, so we finally understood the issue, and I've opened a PR with a fix at #57.

I'll let you know whenever it gets merged and we'll release a new version with the fix as soon as possible!

Great to hear! Thanks so much for the quick fix and hard work on this. Looking forward to the new release!

@Convly
Copy link
Member

Convly commented Feb 17, 2025

Hey 👋

I've just released v1.0.1 which includes the fix, hope everything will work fine for you now.

Have a great day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue: bug Issue reporting a bug status: confirmed The issue has been confirmed or reproduced manually by a team member
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants