Encountering the error message "Method not permitted" while working with API routes in Next.js

When attempting to utilize API routes in Next.js to make a POST method call to an API from the server side, I'm encountering a "Method not allowed" error.

In my page.tsx file, there is a form; upon submitting the form, it should trigger the handleSubmit function, which in turn should invoke a function in app/api/pinToIPFS/route.js that will execute a POST method on the API. The goal is to have the API called from the server side.

"use client";

import { useState } from "react";
import "../../globals.css";
import Link from "next/link";


function CreatePage() {

  const [form, setForm] = useState({ address: "", title: "", proposal: "" });


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


    const formData = new FormData();
    formData.append(
      "file",
      new Blob([JSON.stringify(form)], { type: "application/json" })
    );

    try {
      const res = await fetch("/api/pinToIPFS", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: formData,
      });

      const resData = await res.json();
      console.log("resData:", resData);
    } catch (error) {
      console.error("Error uploading file:", error);
      alert("Trouble uploading file");
    }
  };

  return (
      <form
        onSubmit={handleSubmit}
      ></form>

And here is the route.js file within api/pinToIPFS/:

export default async function handler(req, res) {
  if (req.method === "POST") {
    try {

      const formData = req.body;


      const JWT = process.env.PINATA_JWT;
      const response = await fetch(
        "https://api.pinata.cloud/pinning/pinFileToIPFS",
        {
          method: "POST",
          headers: {
            Authorization: `Bearer ${JWT}`,
            "Content-Type": "application/json",
          },
          body: formData,
        }
      );


      const data = await response.json();

      res.status(200).json(data);
    } catch (error) {
      console.error("Error pinning file to IPFS:", error);
      res.status(500).json({ error: "Error pinning file to IPFS" });
    }
  } else {
    
    res.status(405).json({ error: "Method not allowed" });
  }
}

An error message is displayed in the console:

page.tsx:81       
POST http://localhost:3000/api/pinToIPFS 405 (Method Not Allowed)

page.tsx:94 
Error uploading file: SyntaxError: Unexpected end of JSON input
    at handleSubmit (page.tsx:89:33)

The code snippet from line 80-97 in page.tsx is as follows:

    try {
      const res = await fetch("/api/pinToIPFS", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: formData,
      });

      const resData = await res.json();
      console.log("done!");

      console.log("resData:", resData);
    } catch (error) {
      console.log("Error uploading file:", error);
      alert("Trouble uploading file");
      setUploading(false);
    }

How can this issue be resolved?

Answer №1

To ensure proper functionality, the POST function in route.ts must be invoked and FormData should be created within route.ts instead of page.tsx.

export async function POST(req: Request) {
  console.log("ok, im in post");

  // Extract data from the request body

  const form = await new Response(req.body).json();
  console.log("this is form in post:", form);

  const JWT = process.env.PINATA_JWT;

  const formData = new FormData();
  formData.append(
    "file",
    new Blob([JSON.stringify(form)], { type: "application/json" })
  );
  const response = await fetch(
    "https://api.pinata.cloud/pinning/pinFileToIPFS",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${JWT}`,
      },
      body: formData,
    }
  );

  // Handle the response from Pinata
  const data = await response.json();
  console.log("this is original response:", response);
  console.log("pinata reponse:", data);

  // Respond with the data returned by Pinata
  return NextResponse.json(data, { status: 200 });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason for calling Proxy on nested elements?

Trying to organize Cypress methods into a helper object using getters. The idea is to use it like this: todoApp.todoPage.todoApp.main.rows.row .first().should('have.text', 'Pay electric bill'); todoApp.todoPage.todoApp.main.rows.ro ...

A static factory method within an abstract class

I am currently developing a class system using Typescript. The main structure consists of an abstract class called Component, which includes a static method called create(). This method is utilized on child classes to generate specific instances. abstract ...

Ways to prevent Deno Workers from using cached source code

Good day, I am currently working on building a custom javascript code execution platform using Deno Workers. Additionally, I have implemented an Oak web server to manage requests for script modifications and their compilation and execution. An issue arise ...

What is the best way to extract values from a TypeORM property decorator?

import { PrimaryColumn, Column } from 'typeorm'; export class LocationStatus { @PrimaryColumn({ name: 'location_id' }) locationId: string; @Column({ name: 'area_code', type: 'int' }) areaCode: number; } I& ...

Enhance your text in TextInput by incorporating newline characters with advanced editing features

I'm encountering an issue with my Textarea component that handles Markdown headers: type TextareaProps = { initValue: string; style?: StyleProp<TextStyle>; onChange?: (value: string) => void; }; type OnChangeFun = NativeSynthetic ...

Using a loop variable within a callback function in JavaScript/TypeScript: Tips and tricks

I have a method in my TypeScript file that looks like this: getInitialBatches() { var i = 0; for (var dto of this.transferDTO.stockMovesDTOs) { i++; this.queryResourceService .getBatchIdUsingGET(this.batchParams) ...

Nested Tagged Union Types in Typescript

Imagine having the following types (syntax similar to Elm/Haskell): type Reply = LoginReply | LogoutReply type LoginReply = LoginSucceeded | AlreadyLoggedIn String When trying to represent this in Typescript using discriminated unions, a challenge arises ...

Merge arrays values with Object.assign function

I have a function that returns an object where the keys are strings and the values are arrays of strings: {"myType1": ["123"]} What I want to do is merge all the results it's returning. For example, if I have: {"myType1": ["123"]} {"myType2": ["45 ...

Challenges encountered while retrieving data from Cloud Firestore

Here's the setup I have on my Cloud Firestore: Collection question: - userID - text and Collection user: - name - key I am able to easily retrieve the question data from the database and display it, but currently without the user data. Then, I nee ...

transform json array into a consolidated array by merging identical IDs

I need to transform an array into a different format based on the values of the ID and class properties. Here is the initial array: const json = [{ "ID": 10, "Sum": 860, "class": "K", }, { "ID": 10, "Sum": 760, "class": "one", }, { "ID": ...

There seems to be a syntax error in the regular expression used in Angular TypeScript

I've encountered an error and I'm struggling to identify the syntax issue. core.mjs:6495 ERROR SyntaxError: Invalid regular expression: /https://graph.microsoft.com/v1.0/communications/callRecords/getPstnCalls(fromDateTime=2020-01-30,toDateTime ...

Issue with TypeScript: variable lacks an initializer and is not explicitly assigned within the constructor

Code: class Example { private server: string; constructor() { this.setServer(); } setServer(): void { this.server = 'server'; } } new Example(); Error: ⨯ Unable to compile TypeScript: src/index.ts:309:13 ...

Access the plugin object from a Vue.js 2 component using typescript

I devised a plugin object to handle the regular expressions used in my application in a more global manner. Here's an example of how it looks: import Vue from "vue"; Vue.prototype.$regex = { //isEmail function implementation goes here } ...

Using NextJS with SWR allows for the display of initialData while validating with getServerSideProps

Currently, I am utilizing NextJS in conjunction with SWR for data fetching. I provide SWR with initialData obtained from the output of getServerSideProps. The pagination feature is functioning correctly. However, I am experiencing an issue where upon navi ...

An issue has arisen regarding the type definition for the random-string module

I am currently working on creating a .d.ts file for random-string. Here is the code I have so far: declare module "random-string" { export function randomString(opts?: Object): string; } When I try to import the module using: import randomString = ...

Loading screen displayed while transitioning between routes within Angular

I have been struggling to implement a loading spinner in my project. How can I display a loading screen when changing routes in Angular? Here is the HTML code snippet: <div *ngIf="showLoadingIndicator" class="spinner"></div> ...

Issue: The module "Angular" cannot be found in the Swiper package, resulting in an "ionic2-calendar Error

I recently updated the package for my project Utilizing Ionic and Angular to create applications for iOS and Android Current versions: Ionic 7, Angular 16 Following a recommendation, I made the switch from 'ion-slides' to the Swiper.js library ...

I'm curious if anyone has experimented with implementing TypeScript enums within AngularJS HTML pages

During my Typescript project, I defined an enum like this: enum Action { None = 0, Registering = 1, Authenticating = 2 }; In the controller, I declared a property named action as follows: class AuthService implements IAuthService { action: number; ...

What could be the reason for Angular to merge the element at index 0 of an array into a subarray instead of doing

After setting up the Array in my oninit function, I encountered an issue where one part of the array was functioning as intended while the other returned an error. this.tests = [{ status: 0, testresults: [{ name: 'test ...

Utilizing AWS Websockets with lambda triggers to bypass incoming messages and instead resend the most recent message received

I am facing an issue when invoking a lambda that sends data to clients through the websocket API. Instead of sending the actual message or payload, it only sends the last received message. For example: Lambda 1 triggers Lambda 2 with the payload "test1" ...