next.jspostman

HTTP POST Request doesn't resolve a response with Next JS 13


I'm trying to make an HTTP POST request to a Next JS API route. I'm using Postman to send this request. This POST request is trying to add a user to my Postgres database. However, before that data is saved, it's validated on all fields and checks to ensure the account doesn't already exist. If the account already exists then I get a response:

{
    "response": "Your account already exists! Please sign in."
}

This is the intended behavior. However, if the account doesn't exist then Postman is just constantly stuck on the loading screen and I never get a response. I've verified this isn't an issue with Postman as I've tested it with Testfully as well. Here's my code:

import { PrismaClient } from "@prisma/client";
import { NextResponse } from "next/server";
import validator from "validator";
import bcrypt from "bcrypt";
import * as jose from "jose";

const prisma = new PrismaClient();

export async function POST(request: Request) {
  const { firstName, lastName, email, phone, city, password } = await request.json();
  const errors: string[] = [];

  const validationSchema = [
    {
      valid: validator.isLength(firstName, {
        min: 1,
        max: 20,
      }),
      error: "Invalid first name.",
    },
    {
      valid: validator.isLength(lastName, {
        min: 1,
        max: 20,
      }),
      error: "Invalid last name.",
    },
    {
      valid: validator.isEmail(email),
      error: "Invalid email.",
    },
    {
      valid: validator.isMobilePhone(phone),
      error: "Invalid phone number.",
    },
    {
      valid: validator.isLength(city, {
        min: 1,
        max: 20,
      }),
      error: "Invalid city.",
    },
    {
      valid: validator.isStrongPassword(password),
      error: "Invalaid password.",
    },
  ];

  validationSchema.forEach((check) => {
    if (!check.valid) {
      errors.push(check.error);
    }
  });

  if (errors.length) {
    return NextResponse.json(errors[0]);
  }

  const userWithEmail = await prisma.user.findUnique({
    where: {
      email,
    },
  });

  if (userWithEmail) {
    return NextResponse.json({
      response: "Your account already exists! Please sign in.",
    });
  }

  const hash = await bcrypt.hash(password, 22);

  const user = await prisma.user.create({
    data: {
      first_name: firstName,
      last_name: lastName,
      email: email,
      phone: phone,
      city: city,
      password: hash,
    },
  });

  const alg = "HS256";
  const JWTSecret = new TextEncoder().encode(process.env.JWT_SECRET);

  const token = await new jose.SignJWT({
    email: user.email,
  })
    .setProtectedHeader({ alg })
    .setExpirationTime("24h")
    .sign(JWTSecret);

  console.log(token);

  return NextResponse.json({
    JWT: token,
  });
}

Edit: I ran I bunch of console.log()```` tests to see where the code is failing and it happens right after prisma create```. No errors.


Solution

  • The issue, from what I see testing, is your hashing of the password. Adding 22 salt rounds takes a significant amount of time. Reducing this to 10 allows the server to response within 73ms. But with 22, it takes a long time. Even with 15 rounds, it takes 2seconds. Increasing the salt round by 1, doubles the cost.

    I would suggest lowering the salt rounds, or using another hashing method.