sindresorhus / ky

🌳 Tiny & elegant JavaScript HTTP client based on the Fetch API
MIT License
11.91k stars 342 forks source link

Content-length header is sent to the server with empty value in Next.js 13 route handler. #514

Open wa12rior opened 1 year ago

wa12rior commented 1 year ago

I'm using nextjs 13 with new app router and next-auth. My authorize method in CredentialsProvider looks like this:

async authorize(credentials) {
        if (!credentials) {
          return null;
        }

        try {
          const data = await loginUser({
            email: credentials.email,
            password: credentials.password,
            redirect: false,
          });

          const user: AppUser = {
            ...
          };

          return user;
        } catch (error) {
          console.error(error);
          return null;
        }
      },

Here is the body of the loginUser method

export const loginUser = async (values: LoginParams) => {
  const loginUrl = 'login';

  return await ky
    .post(loginUrl, {
      json: values,
      prefixUrl: prefixUrl,
    })
    .json<TokenUserResponse>();
};

And server gets empty request payload because header content-length is empty (""). When I add it manually it suddenly works.

headers: { 'content-type': 'application/json', 'content-length': JSON.stringify(values).length + '' },

Does someone knows why that is happening?

wa12rior commented 1 year ago

Anyone?

mabdullahadeel commented 1 year ago

don't know the exact reason I faced the same issue. the json payload sent to one of the backend service from route handler was empty. I did headers: { 'content-type': 'application/json', 'content-length': JSON.stringify(values).length + '' }, and it worked for me too.

It's definitely has to do something related to nextjs's wrap around the fetch (to handle cache) which is globally available. But thanks for your workaround here.

wa12rior commented 11 months ago

@mabdullahadeel No problem. Although this is workaround I found a way to do it in beforeRequest hook to avoid unnecessary code duplication.

hooks: {
    beforeRequest: [
      (request, options) => {
        request.headers.set('Content-Type', 'application/json');
        if (options.body) {
          request.headers.set('Content-Length', options.body.length);
        }
      },
    ],
  },