Upload API give me 502 Bad Gateway

stefifm
stefifm Member Posts: 1

Hi. I'm in a Next js 13 project. I tried to upload a image using an unsigned upload preset call restaurant and Upload API but it gives me a 502 Bad Gateway.

This is my code


'use client'


import { useSession } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import { useState } from 'react'


function AddPage() {
  const { data: session, status } = useSession()
  const [inputs, setInputs] = useState({
    title: '',
    desc: '',
    price: 0,
    catSlug: ''
  })


  const [option, setOption] = useState({
    title: '',
    additionalPrice: 0
  })


  const [options, setOptions] = useState([])
  const [file, setFile] = useState()


  const router = useRouter()


  if (status === 'loading') {
    return <p>Loading...</p>
  }


  if (status === 'unauthenticated' || !session?.user.isAdmin) {
    router.push('/')
  }


  const handleChange = (e) => {
    setInputs((prev) => ({ ...prev, [e.target.name]: e.target.value }))
  }
  const changeOption = (e) => {
    const { name, value } = e.target
    const newValue = name === 'additionalPrice' ? parseFloat(value) : value
    setOption((prev) => ({ ...prev, [name]: newValue }))
  }


  const handleChangeImage = (e) => {
    const target = e.target
    const item = target.files[0]
    setFile(item)
  }


  const upload = async () => {
    try {
      const dataForm = new FormData()
      dataForm.append('file', file)
      dataForm.append('upload_preset', 'restaurant')
      dataForm.append('cloud_name', 'stefigallery')
      const res = await fetch('https://api.cloudinary.com/v1_1/stefigallery/image', {
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        body: dataForm
      })


      const dataImage = await res.json()
      return dataImage.url
    } catch (error) {
      console.log(error)
    }
  }


  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      const imageUrl = await upload()
      const formattedOptions = options.map((opt) => ({
        ...opt,
        additionalPrice: parseFloat(opt.additionalPrice)
      }))


      const res = await fetch('http://localhost:3000/api/products', {
        method: 'POST',
        body: JSON.stringify({ img: imageUrl, ...inputs, options: formattedOptions })
      })


      const data = await res.json()
      // router.push(`/product/${data.id}`)
    } catch (error) {
      console.log(error)
    }
  }


  return (
    <div className='p-4 my-9 lg:px-20 xl:px-40 h-[calc(100vh-6rem)] md:h-[calc(100vh-9rem)] flex items-center justify-center text-red-500'>
      <form
        className='shadow-lg flex flex-wrap gap-4 p-8'
        onSubmit={handleSubmit}>
        <h1 className='text-4xl mb-2 text-gray-300 font-bold'>Add New Product</h1>
        <div className='w-full flex flex-col gap-2'>
          <label>Title</label>
          <input
            type='text'
            name='title'
            className='ring-1 ring-red-200 rounded-sm p-2'
            onChange={handleChange}
          />
        </div>
        <div className='w-full flex flex-col gap-2'>
          <label>Image</label>
          <input
            type='file'
            id='file'
            className='ring-1 ring-red-200 rounded-sm p-2'
            onChange={handleChangeImage}
          />
        </div>
        <div className='w-full flex flex-col gap-2'>
          <label>Description</label>
          <textarea
            name='desc'
            className='ring-1 ring-red-200 rounded-sm'
            onChange={handleChange}></textarea>
        </div>
        <div className='w-full flex flex-col gap-2'>
          <label>Price</label>
          <input
            type='number'
            name='price'
            className='ring-1 ring-red-200 rounded-sm p-2'
            onChange={handleChange}
          />
        </div>
        <div className='w-full flex flex-col gap-2'>
          <label>Category</label>
          <input
            type='text'
            name='catSlug'
            className='ring-1 ring-red-200 rounded-sm p-2'
            onChange={handleChange}
          />
        </div>
        <div className='w-full flex flex-col gap-2'>
          <label>Options</label>
          <div className='flex gap-3'>
            <input
              type='text'
              placeholder='Title'
              name='title'
              className='ring-1 ring-red-200 rounded-sm p-2'
              onChange={changeOption}
            />
            <input
              type='number'
              placeholder='Additional Price'
              name='additionalPrice'
              className='ring-1 ring-red-200 rounded-sm p-2'
              onChange={changeOption}
            />
          </div>
          <input
            className='w-52 bg-red-500 text-white p-2 cursor-pointer'
            type='button'
            value='Add Option'
            onClick={() => setOptions((prev) => [...prev, option])}
          />
        </div>


        <div>
          {options.map((item) => (
            <div
              className='ring-1 p-2 ring-red-500 rounded-md cursor-pointer'
              key={item.tile}
              onClick={() => setOptions(options.filter((option) => option.title !== item.title))}>
              <span>{item.title}</span>
              <span>${item.additionalPrice}</span>
            </div>
          ))}
        </div>


        <button
          type='submit'
          className='w-full bg-red-500 text-white p-2'>
          Add Product
        </button>
      </form>
    </div>
  )
}


export default AddPage


Answers

  • Vdeub
    Vdeub Member, Cloudinary Staff Posts: 78

    Hi @stefifm,

    I am afraid I am not able to locate any 502s in our logs for the cloud stefigallery which makes me think that the 502 is actually from your side. I am also not able to see any errors related to uploads so the requests don't even reach Cloudinary.

    Would you have any error log from your localhost?

    Thanks in advance.

    Loic

  • NayaO
    NayaO Member Posts: 1

    Hi @Vdeub , I have the same error and here's my code:

    "use client";


    import { useSession } from "next-auth/react";

    import { useRouter } from "next/navigation";

    import { useState } from "react";


    type Inputs = {

      title: string;

      desc: string;

      price: number;

      catSlug: string;

    };

    type Option = {

      title: string;

      additionalPrice: number;

    };


    const AddPage = () => {

      const { data: session, status } = useSession();

      const [inputs, setInputs] = useState<Inputs>({

        title: "",

        desc: "",

        price: 0,

        catSlug: "",

      });


      const [option, setOption] = useState<Option>({

        title: "",

        additionalPrice: 0,

      });


      const [options, setOptions] = useState<Option[]>([]);

      const [file, setFile] = useState<File>();


      const router = useRouter();


      if (status === "loading") {

        return <p>Loading...</p>;

      }

      if (status === "unauthenticated" || !session?.user.isAdmin) {

        router.push("/");

      }


      const handleChange = (

        e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>

      ) => {

        setInputs((prev) => {

          return { ...prev, [e.target.name]: e.target.value };

        });

      };


      const changeOption = (e: React.ChangeEvent<HTMLInputElement>) => {

        setOption((prev) => {

          return { ...prev, [e.target.name]: e.target.value };

        });

      };


      const handleChangeImg = (e: React.ChangeEvent<HTMLInputElement>) => {

        const target = e.target as HTMLInputElement;

        const item = (target.files as FileList)[0];

        setFile(item);

      };


      const upload = async () => {

        const data = new FormData();

        data.append("file", file!);

        data.append("upload_preset", "restaurant");


        const res = await fetch("https://api.cloudinary.com/v1_1/nayadev/image", {

          method: "POST",

          headers: { "Content-Type": "multipart/form-data" },

          mode: "no-cors",

          body: data,

        });

        const resData = await res.json();

        return resData.url;

      };


      const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {

        e.preventDefault();


        try {

          const url = await upload();

          const res = await fetch("http://localhost:3000/api/products", {

            method: "POST",

            body: JSON.stringify({

              img: url,

              ...inputs,

              options,

            }),

          });


          const data = await res.json();


          router.push(`/product/${data.id}`);

        } catch (err) {

          console.log(err);

        }

      };

      return (

        <div>

          <form

            className="shadow-lg flex flex-wrap gap-4 p-8"

            onSubmit={handleSubmit}

          >

            <h1>Add New Product</h1>

            <div className="w-full flex flex-col gap-2">

              <label>Image</label>

              <input

                className="ring-1 ring-red-200 p-2 rounded-sm"

                type="file"

                onChange={handleChangeImg}

              />

            </div>

            <div className="w-full flex flex-col gap-2">

              <label>Title</label>

              <input

                onChange={handleChange}

                className="ring-1 ring-red-200 p-2 rounded-sm"

                type="text"

                name="title"

              />

            </div>

            <div className="w-full flex flex-col gap-2">

              <label>Desc</label>

              <textarea

                onChange={handleChange}

                className="ring-1 ring-red-200 p-2 rounded-sm"

                name="desc"

              />

            </div>

            <div className="w-full flex flex-col gap-2">

              <label>Price</label>

              <input

                onChange={handleChange}

                className="ring-1 ring-red-200 p-2 rounded-sm"

                type="number"

                name="price"

              />

            </div>

            <div className="w-full flex flex-col gap-2">

              <label>Category</label>

              <input

                onChange={handleChange}

                className="ring-1 ring-red-200 p-2 rounded-sm"

                type="text"

                name="catSlug"

              />

            </div>

            <div className="w-full flex flex-col gap-2">

              <label>Options</label>

              <div className="w-full flex flex-col gap-2">

                <input

                  onChange={changeOption}

                  className="ring-1 ring-red-200 p-2 rounded-sm"

                  type="text"

                  placeholder="Title"

                  name="title"

                />

                <input

                  onChange={changeOption}

                  className="ring-1 ring-red-200 p-2 rounded-sm"

                  type="number"

                  placeholder="Additional Price"

                  name="additionalPrice"

                />

              </div>

              <div

                className="w-52 bg-red-500 text-white p-2"

                onClick={() => setOptions((prev) => [...prev, option])}

              >

                Add Option

              </div>

            </div>

            <div>

              {options.map((item) => (

                <div

                  className="ring-1 p-2 ring-red-500 rounded-md cursor-pointer"

                  key={item.title}

                  onClick={() =>

                    setOptions(options.filter((opt) => opt.title !== item.title))

                  }

                >

                  <span>{item.title}</span>

                  <span>${item.additionalPrice}</span>

                </div>

              ))}

            </div>

            <button type="submit" className="p-2 w-full bg-red-500 text-white">

              Submit

            </button>

          </form>

        </div>

      );

    };


    export default AddPage;

    The console gave this error:

    POST https://api.cloudinary.com/v1_1/nayadev/image 502 (Bad Gateway) page.tsx:67 

    SyntaxError: Unexpected end of input (at page.tsx:75:35)

      at upload (page.tsx:75:35)

      at async handleSubmit (page.tsx:81:25)