cloudflare / next-on-pages

CLI to build and develop Next.js apps for Cloudflare Pages
https://www.npmjs.com/package/@cloudflare/next-on-pages
MIT License
1.26k stars 122 forks source link

[🐛 Bug]: wrangler POST /api/payment 404 Not Found #644

Open rusakovic opened 8 months ago

rusakovic commented 8 months ago

The main question: Is it possible to use a combination of Static export and POST Request function? If Yes, then it's a bug, if not, then should be documented better.

next-on-pages environment related information

System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000 CPU: (10) arm64 Apple M1 Pro Memory: 32 GB Shell: /bin/zsh Package Manager Used: pnpm (8.10.5)

Relevant Packages: @cloudflare/next-on-pages: 1.8.5 vercel: N/A next: 14.0.4

Description

Which Cloudflare product(s) does this pertain to?

Pages

What version(s) of the tool(s) are you using?

Wrangler 3.22.5, "@cloudflare/next-on-pages": "1.8.5", "next": "14.0.4"

What version of Node are you using?

20.10.0

What operating system are you using?

macOS 14.2

Describe the Bug

Task: check POST request for path api/payment on local with @cloudflare/next-on-pages build and Wrangler

  1. functions is placed in the root of the folder

image

  1. For using TS, added "@cloudflare/workers-types": "4.20231218.0", according to https://developers.cloudflare.com/pages/functions/typescript/

and in tsconfig.json

image

  1. In next.config.js is used output: "export", to generate static pages.

  2. Build is run by pnpm dlx @cloudflare/next-on-pages image

  3. I don't know if after the build I should see this function in nop-build-log.json but I don't

image

  1. Run Wrangler with pnpm dlx wrangler pages dev .vercel/output/static --compatibility-flag=nodejs_compat

  2. Navigate to POST /api/payment but got the error

[wrangler:inf] POST /api/payment 404 Not Found (19ms)

image

What should I do to have static exports and working API Requests from the routes?

Thank you in advance.

Would you like to help?

james-elicx commented 8 months ago

The functions directory does not work with next-on-pages as we generate our own worker for your application that handles routing and whatnot. You should convert your functions directory to Next.js route handlers using the edge runtime.

https://nextjs.org/docs/app/building-your-application/routing/route-handlers#edge-and-nodejs-runtimes

If you would like to use a static export with output: 'export' and use the functions directory, you should just deploy your app normally without using next-on-pages.

rusakovic commented 8 months ago

The functions directory does not work with next-on-pages as we generate our own worker for your application that handles routing and whatnot. You should convert your functions directory to Next.js route handlers using the edge runtime.

https://nextjs.org/docs/app/building-your-application/routing/route-handlers#edge-and-nodejs-runtimes

If you would like to use a static export with output: 'export' and use the functions directory, you should just deploy your app normally without using next-on-pages.

@james-elicx Thank you for your quick response. Correct. I want to use a static export with output: 'export' and use the functions directory,.

How to check the POST function locally? With wrangler? If yes, my steps

  1. pnpm build ("build": "next build",)
  2. pnpm dlx wrangler pages dev .vercel/output/static --compatibility-flag=nodejs_compat --log-level=debug
  3. But when I run the browser and send POST request:
    curl -X POST http://localhost:8788/api/payment -H "Content-Type: application/json" -d '{"priceIds": ["price_1"], "jobPostUrl": "https://example.com"}'

Got error in Wrangler CLI:

[InspectorProxyWorker] RUNTIME INCOMING MESSAGE {
  method: 'Network.requestWillBeSent',
  params: {
    requestId: '67',
    loaderId: '',
    request: {
      url: 'http://localhost:8788/404',
      method: 'POST',
      headers: [Object],
      mixedContentType: 'blockable',
      initialPriority: 'VeryLow',
      referrerPolicy: 'unsafe-url',
      isLinkPreload: false
    },
    timestamp: 179424.787,
    wallTime: 1705521184.839,
    initiator: { type: 'script', stack: [Object], lineNumber: 0 },
    type: 'Fetch'
  }
}
[wrangler-ProxyWorker:inf] POST /api/payment 404 Not Found (11ms)
[InspectorProxyWorker] RUNTIME INCOMING MESSAGE {
  method: 'Network.responseReceived',
  params: {
    requestId: '67',
    timestamp: 179424.792,
    type: 'Other',
    response: {
      status: 405,
      statusText: 'Method Not Allowed',
      headers: [Object],
      mimeType: 'text/plain;charset=UTF-8',
      connectionReused: false,
      connectionId: 0,
      remotePort: 0,
      fromDiskCache: false,
      fromServiceWorker: false,
      encodedDataLength: 0,
      protocol: 'http/1.1',
      securityState: 'unknown'
    }
  }
}
[InspectorProxyWorker] RUNTIME INCOMING MESSAGE {
  method: 'Network.loadingFinished',
  params: {
    requestId: '67',
    timestamp: 179424.793,
    encodedDataLength: 0,
    cfResponse: { body: '', base64Encoded: true }
  }
}
[InspectorProxyWorker] SEND TO RUNTIME {"method":"Runtime.getIsolateId","id":100000005}
[InspectorProxyWorker] RUNTIME INCOMING MESSAGE { id: 100000005, result: { id: '5f8c685b73776271' } }

Could you, please, help to understand why? Thank you .

TimKieu commented 6 months ago

I think that the root cause is POST method not allowed (405 error code). Then the builder ignore api routes, accordingly to 404 not found. I am also finding the solution for 405 POST error, involving to form data submit, server actions with client data, and also edge API functions.

dario-piotrowicz commented 6 months ago

@rusakovic I've created this very quick example hoping that it can clarify how to use Next.js static exports with Pages functions: https://github.com/dario-piotrowicz/static-nextjs-app-with-cf-pages-functions-example

Hopefully this helps, please let me know 🙂

simplenotezy commented 2 weeks ago

We have the same issue here. Issuing a GET request will work, but a POST will fail.

We are proxying requests, and we can confirm that the endpoint returns a 204. When constructing a response like this:

    return new NextResponse(proxiedRequest.body, {
      headers: responseHeaders,
      status: proxiedRequest.status, // 204 on POST
    });

Wrangler still returns:

[wrangler:inf] POST /api/events/1071519/favorite 404 Not Found (218ms)

By the way, we are using middleware.ts to proxy the requests. We have tried also simply proxying using using the app router (e.g. /api/[...path]/route.ts but that seems to have the same effect:

🐛 Proxying request from http://localhost:8788/api/events/1234/favorite -> https://website.com/api/events/1234/favorite
🐛 Got response from https://website.com/api/events/1234/favorite 204
[wrangler:inf] POST /api/events/1234/favorite 404 Not Found (237ms)