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

[NEXT-1194] After upgrade to 13.3 request.json() in DELETE route handler fails #48096

Closed
1 task done
gitdagray opened this issue Apr 7, 2023 · 53 comments · Fixed by #51874
Closed
1 task done

[NEXT-1194] After upgrade to 13.3 request.json() in DELETE route handler fails #48096

gitdagray opened this issue Apr 7, 2023 · 53 comments · Fixed by #51874
Assignees
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked

Comments

@gitdagray
Copy link

gitdagray commented Apr 7, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Pro
    Binaries:
      Node: 18.12.1
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.3.1-canary.1
      eslint-config-next: 13.2.4
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue

N/A

To Reproduce

import { NextResponse } from "next/server"
const DATA_SOURCE_URL = "https://jsonplaceholder.typicode.com/todos"

type Todo = {
    userId: number,
    id: number,
    title: string,
    completed: boolean,
}

export async function DELETE(request: Request) {

    const { id }: Partial<Todo> = await request.json() // error

    if (!id) return NextResponse.json({ "message": "Todo id required" })

    await fetch(`${DATA_SOURCE_URL}/${id}`, {
        method: 'DELETE',
    })

    return NextResponse.json({ "message": `Todo ${id} deleted` })
}

Describe the Bug

I only encounter this error on the DELETE route handler. My POST and PUT route handlers can await request.json() with no issues.

I run the same code in 13.2.4 and do not receive the error.

I am sending valid and very simple JSON:

{
   "id": 3
}

Nevertheless, I receive this error:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at NextRequest.json (node:internal/deps/undici/undici:6160:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DELETE (webpack-internal:///(sc_server)/./src/app/api/todos/route.ts:63:21)

Expected Behavior

I expect await request.json() to work as it does in the POST and PUT route handlers.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

NEXT-1194

@gitdagray gitdagray added the bug Issue was opened via the bug report template. label Apr 7, 2023
@fbuyuk
Copy link

fbuyuk commented Apr 8, 2023

+1

1 similar comment
@batuhanbilginn
Copy link

+1

@niwsa
Copy link

niwsa commented Apr 10, 2023

+1 Facing the issue with dev server. Production build works fine.

@andrewbateman
Copy link

+1

1 similar comment
@nadam131
Copy link

+1

randreu28 added a commit to randreu28/next-to-do that referenced this issue Apr 14, 2023
@zenix-s
Copy link

zenix-s commented Apr 17, 2023

Similar error I'm using axios, Post works fine but delete dont work and leaves a status code 500

@arasrezaei
Copy link

Same here... it worked previous versions, now I had to use url query parameters instead ...

@simonknittel
Copy link

simonknittel commented Apr 23, 2023

Still happens with 13.3.3 (dev and build)

@danielmarkow
Copy link

danielmarkow commented Apr 29, 2023

+1

@ralfscheffler
Copy link

Same, same

@vlsk3104
Copy link

same

@codingforfoodllc
Copy link

Same here

@aFendell
Copy link

aFendell commented May 3, 2023

Same issue

@H3nry-T
Copy link

H3nry-T commented May 3, 2023

yep still happens :( oh well back to 13.2.4

@daveteu
Copy link

daveteu commented May 5, 2023

The problem exist also in 13.4.1

@Carduelis
Copy link

Phew. I'm not alone. 13.4.0

@palamago
Copy link

palamago commented May 8, 2023

Kind of duplicate of: #48898
My isolated proof of the issue: https://codesandbox.io/p/sandbox/nextjs-issue-canary-xyyiu7

@ameetmadan
Copy link

I am having the same issue with the POST endpoint. Debugging for two days, decided to switch back to /pages router and it works on first try. The app router is not ready for production yet, in my case atleast.

@Farhanaziz95
Copy link

i dont know if this will also work for delete i got this issue with POST where i wasn't able to get body
i'm a noob in this kind of this discussions

export async function POST(request: Request, response: NextApiResponse) {
    if (request.method !== 'POST') {

    }
    else {

        const a = await request.text()
        const data = JSON.parse(a)
        const { id, email, password, role } = data;
        const modipassword = process.env.SECRATE_KEY + password
        const salt = await bcrypt.genSalt(10)
        const hashedPassword = await bcrypt.hash(modipassword, salt);
        



        const newUser: typeAuthor = {
            id: id,
            name: '',
            email: email,
            password: hashedPassword,
            role: role,
            facebook_link: '',
            insta_link: '',
            twitter_link: '',
            status: 'Active',
            created_at: new Date(),
            updated_at: new Date(),
        };

        await db.insert(Author).values(newUser);



        const custom_data_array = [{ message: 'Successfully Added' }]
        return new Response(JSON.stringify(custom_data_array), { status: 200 })
    }
}

well i got work around for my problem like this hope it would be some use to everyone here

@Frost7994
Copy link

also having this issue with route handler DELETE request, is there any update or simple workaround besides rolling back to an earlier version?

Geuni620 added a commit to Geuni620/Breakable-Toy that referenced this issue May 15, 2023
@alecf
Copy link

alecf commented May 15, 2023

I stumbled across this but then found that DELETE generally should not have a request body - the fact that nextjs previously supported it sounds like a bug to me:
https://www.rfc-editor.org/rfc/rfc9110.html#name-delete

Although request message framing is independent of the method used, content received in a DELETE request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

Though it sounds frustrating if you were previously depending on this behavior...

@cjcheshire
Copy link

@alecf nice find, I’ve subsequently changed my request to pass query params and all is good again. Safe to upgrade to latest :)

@daveteu
Copy link

daveteu commented May 17, 2023

@alecf thanks.

I use the following codes for those new to app /api and do not know how to get the query params.

DELETE /api/post?_id=12345

export async function DELETE(request: Request) {

  const { searchParams } = new URL(request.url);
  const _id = searchParams.get('_id') || ''; // for ts

  // ...
}

@cjcheshire
Copy link

cjcheshire commented May 17, 2023

@daveteu

export async function DELETE(request: Request) {
  const { query } = request; // query will hold all of them

  // ...
}

@iamlucasgomes
Copy link

Ainda com problemas na rota Delete, estou usando next 13.4.4

@james-william-r
Copy link

Just some clarity on method bodies. It's not common practice for methods other than PUT, POST and PATCH to have a body.

There's no reason you can't have use a POST request for multiple purposes, as in, adding content and deleting, you could change the action depending on a URL param. That being said, obviously be extra careful not to delete content where you want to add it, and vice versa. 😅

As for the issue, I can't even get an empty DELETE request (without body) to work. 🥲

@leslee-glints
Copy link

leslee-glints commented May 31, 2023

Just some clarity on method bodies. It's not common practice for methods other than PUT, POST and PATCH to have a

There's no reason you can't have use a POST request for multiple purposes, as in, adding content and deleting, you could change the action depending on a URL param. That being said, obviously be extra careful not to delete content where you want to add it, and vice versa.

As for the issue, I can't even get an empty DELETE request (without body) to work.

Working with next@13.4.4 by using POST Method facing this issue as well.

here are the error messages.

By useing request.body

export async function POST(request: Request) {
  const res = request.body;
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.body`.

By useing request.json()

export async function POST(request: Request) {
  const res = request.json();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.json`.

By useing request.text()

export async function POST(request: Request) {
  const res = request.text();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.text`.

Could anyone tell me how can I retrive BODY in request ? 😿😿😿😿

@Amyx000
Copy link

Amyx000 commented Jun 1, 2023

Just some clarity on method bodies. It's not common practice for methods other than PUT, POST and PATCH to have a
There's no reason you can't have use a POST request for multiple purposes, as in, adding content and deleting, you could change the action depending on a URL param. That being said, obviously be extra careful not to delete content where you want to add it, and vice versa.
As for the issue, I can't even get an empty DELETE request (without body) to work.

Working with next@13.4.4 by using POST Method facing this issue as well.

here are the error messages.

By useing request.body

export async function POST(request: Request) {
  const res = request.body;
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.body`.

By useing request.json()

export async function POST(request: Request) {
  const res = request.json();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.json`.

By useing request.text()

export async function POST(request: Request) {
  const res = request.text();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.text`.

Could anyone tell me how can I retrive BODY in request ? 😿😿😿😿

use await const body = await request.json()

@leslee-glints
Copy link

Tried. Still doesn't work.

image

image

@RobertoGallego
Copy link

RobertoGallego commented Jun 1, 2023

Tried. Still doesn't work.

image

image

I believe that this should work, maybe ur problem is coming from the way u call it, can u share with us your handle, and maybe try to change ur Response with NextResponse for example :

return new NextResponse(data, { status: 200 });

@RobertoGallego
Copy link

RobertoGallego commented Jun 1, 2023

The way that work for me with DELETE is using the params (same as the doc) and stop to use the body like other on top suggest

export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
)

maybe is not in the doc but the magic here is too create the route like this :

--- api 
    --- myRouteFolder        // named as you prefer 
        --- route.tsx
        --- [myRouteFolderid]  // create this folder to receive the ID for example
             ---route.tsx             // add a new route file and here u go to create wherever u want to pass (id) to ur function

for example :

export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
) {
  const { id } = params;
  console.log("###", id)
}

and then u just need to

await fetch(`api/myRouteFolder/${deleteByID}`, {
      method: "DELETE",
    });

I hope it will be helpful

@mehtasag
Copy link

mehtasag commented Jun 2, 2023

Hi guys ! I just found working solution to get ID when performing DELETE Request ......

const deleteResponse = await fetch(/api/yourRoute/route`, {
method: "DELETE",

		headers: {
			"Content-Type": "application/json",
			"X-ID": id,
		},
	});`

Basically what we are passing ID in our own header... On other hand in NextJS

app/api/route we can access it by using

const head = headers();

	console.log(request.headers);

	const head_token = head.get("x-id");

	console.log(head_token);

It works for me... Thanks

@leslee-glints
Copy link

Tried. Still doesn't work.
image
image

I believe that this should work, maybe ur problem is coming from the way u call it, can u share with us your handle, and maybe try to change ur Response with NextResponse for example :

return new NextResponse(data, { status: 200 });

Thank you for your useful advice.

By changing to return new NextResponse(data, { status: 200 }); it could work fine.

@BhargavEverestek
Copy link

image

any solution???

Just some clarity on method bodies. It's not common practice for methods other than PUT, POST and PATCH to have a
There's no reason you can't have use a POST request for multiple purposes, as in, adding content and deleting, you could change the action depending on a URL param. That being said, obviously be extra careful not to delete content where you want to add it, and vice versa.
As for the issue, I can't even get an empty DELETE request (without body) to work.

Working with next@13.4.4 by using POST Method facing this issue as well.

here are the error messages.

By useing request.body

export async function POST(request: Request) {
  const res = request.body;
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.body`.

By useing request.json()

export async function POST(request: Request) {
  const res = request.json();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.json`.

By useing request.text()

export async function POST(request: Request) {
  const res = request.text();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.text`.

Could anyone tell me how can I retrive BODY in request ? 😿😿😿😿

@t-kings
Copy link

t-kings commented Jun 5, 2023

Just some clarity on method bodies. It's not common practice for methods other than PUT, POST and PATCH to have a
There's no reason you can't have use a POST request for multiple purposes, as in, adding content and deleting, you could change the action depending on a URL param. That being said, obviously be extra careful not to delete content where you want to add it, and vice versa.
As for the issue, I can't even get an empty DELETE request (without body) to work.

Working with next@13.4.4 by using POST Method facing this issue as well.

here are the error messages.

By useing request.body

export async function POST(request: Request) {
  const res = request.body;
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.body`.

By useing request.json()

export async function POST(request: Request) {
  const res = request.json();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.json`.

By useing request.text()

export async function POST(request: Request) {
  const res = request.text();
}

Throws

error StaticGenBailoutError: Page with `dynamic = "error"` couldn't be rendered statically because it used `request.text`.

Could anyone tell me how can I retrive BODY in request ? 😿😿😿😿

Add this to the bottom of your route file to make your route handler a dynamic route;

export const dynamic = "force-dynamic";

You need to make your route handler a dynamic route. NextJs failed to do this automatically, I think it has a bug that sets dynamic as error when trying to calculate it automatically.

See References

@OlegKochiev
Copy link

+1: work in production, don't work in localhost

@petrnovikov
Copy link

+1

@iv7dev
Copy link

iv7dev commented Jun 10, 2023

+1 Working with next@13.4.4 by using DELETE Method facing this issue as well.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Pro
    Binaries:
      Node: 18.12.1
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.3.1-canary.1
      eslint-config-next: 13.2.4
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue

N/A

To Reproduce

import { NextResponse } from "next/server"
const DATA_SOURCE_URL = "https://jsonplaceholder.typicode.com/todos"

type Todo = {
    userId: number,
    id: number,
    title: string,
    completed: boolean,
}

export async function DELETE(request: Request) {

    const { id }: Partial<Todo> = await request.json() // error

    if (!id) return NextResponse.json({ "message": "Todo id required" })

    await fetch(`${DATA_SOURCE_URL}/${id}`, {
        method: 'DELETE',
    })

    return NextResponse.json({ "message": `Todo ${id} deleted` })
}

Describe the Bug

I only encounter this error on the DELETE route handler. My POST and PUT route handlers can await request.json() with no issues.

I run the same code in 13.2.4 and do not receive the error.

I am sending valid and very simple JSON:

{
   "id": 3
}

Nevertheless, I receive this error:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at NextRequest.json (node:internal/deps/undici/undici:6160:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DELETE (webpack-internal:///(sc_server)/./src/app/api/todos/route.ts:63:21)

Expected Behavior

I expect await request.json() to work as it does in the POST and PUT route handlers.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

NEXT-1194

@Amyx000
Copy link

Amyx000 commented Jun 11, 2023

+1 Working with next@13.4.4 by using DELETE Method facing this issue as well.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: win32
      Arch: x64
      Version: Windows 10 Pro
    Binaries:
      Node: 18.12.1
      npm: N/A
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.3.1-canary.1
      eslint-config-next: 13.2.4
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue

N/A

To Reproduce

import { NextResponse } from "next/server"
const DATA_SOURCE_URL = "https://jsonplaceholder.typicode.com/todos"

type Todo = {
    userId: number,
    id: number,
    title: string,
    completed: boolean,
}

export async function DELETE(request: Request) {

    const { id }: Partial<Todo> = await request.json() // error

    if (!id) return NextResponse.json({ "message": "Todo id required" })

    await fetch(`${DATA_SOURCE_URL}/${id}`, {
        method: 'DELETE',
    })

    return NextResponse.json({ "message": `Todo ${id} deleted` })
}

Describe the Bug

I only encounter this error on the DELETE route handler. My POST and PUT route handlers can await request.json() with no issues.
I run the same code in 13.2.4 and do not receive the error.
I am sending valid and very simple JSON:

{
   "id": 3
}

Nevertheless, I receive this error:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at NextRequest.json (node:internal/deps/undici/undici:6160:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async DELETE (webpack-internal:///(sc_server)/./src/app/api/todos/route.ts:63:21)

Expected Behavior

I expect await request.json() to work as it does in the POST and PUT route handlers.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response
NEXT-1194

You cant access request body for DELETE method, you can access the id from url.

Example route structure: app/api/delete/[id]/route.ts

export async function DELETE(
  req: NextRequest,
  { params }: { params: { id: string } }
) {
  const { id } = params;
}

@elem15

This comment was marked as resolved.

@james-william-r
Copy link

Working with Next 13.4.4

Only for POST, PUT not for DELETE.

If you use JSON as Request Body

export async function POST(request: Request) {
  const body = await request.text()
  const obj = JSON.parse(body)
  return NextResponse.json(obj)
}

If you use 'x-www-form-urlencoded' as Request Body

export async function POST(request: Request) {
  const body = await request.text()
  const { searchParams } = new URL(`http://api?${body}`)
  const obj = Object.fromEntries(searchParams.entries())
  return NextResponse.json(obj)
}

I hope it will be helpful

Unfortunately not, this question's specifically in relation to using DELETE in the route file. 😅

@mohamed-ali-agourram
Copy link

mohamed-ali-agourram commented Jun 21, 2023

The issue here is that the DELETE method typically expects the identifier of the resource to be deleted to be provided in the URL parameters, rather than in the request body. For example, you can include the id parameter in the URL like this:

export async function DELETE(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id");

// Delete from the database using the extracted id
}

To perform the DELETE operation, you can make a request to the API endpoint with the id parameter specified in the URL:

export const delete_post = async (id: string) => {
await fetch(http://localhost:3000/api/posts?id=${id}, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
}
});
}

and this worked for me!

@kodiakhq kodiakhq bot closed this as completed in #51874 Jun 27, 2023
kodiakhq bot pushed a commit that referenced this issue Jun 27, 2023
It looks like the `content-length` header can't be ignored for the request forwarded to the render worker. See nodejs/node#27880.

Closes #48096, closes #49310. Fix NEXT-1194
fix NEXT-1114
@aniketbiprojit
Copy link

Encountered again. Fixed with editing next.config.js:

Doesn't work for static builds though which is sad.

image

@timneutkens
Copy link
Member

@aniketbiprojit encountered what exactly? A fully static build can't have Route Handler that are not static, which is expected because there is no server.

@JohnFoster44
Copy link

This issue was resolved for me upgrading to 13.4.16

@github-actions
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 31, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked
Projects
None yet
Development

Successfully merging a pull request may close this issue.