The resolver function in the Nextjs higher order API is not defined

I am trying to create a custom wrapper function for my NextJs API routes that will verify a JWT in the request, validate it, and then execute the original API handler.

Here is how I have defined my wrapper function:

interface ApiError {
  message: string,
}

export async function withJwt<T>(
  handler: ((req: NextApiRequest, res: NextApiResponse<T>, user?: User)=>void|Promise<void>))
  : Promise<(req: NextApiRequest, res: NextApiResponse<T | ApiError>)=>Promise<void>> {  
  return async (req: NextApiRequest, res: NextApiResponse<T | ApiError>) => {
    const authHeader = req.headers.authorization;
    if(!authHeader || !authHeader.startsWith(JWT_PREFIX)){ 
      return res.status(401).json({
        message: `Provide the header 'Authorization: ${JWT_PREFIX}<token>'`,
      });
    }
    let user: User;
    try {
      user = await verify(authHeader.substring(JWT_PREFIX.length));
    } catch(err) {
      return res.status(401).json({message: (err as any).message as string});
    }

    try {
      return handler(req, res, user);
    } catch(err){
      return res.status(500).json({message: (err as any).message});
    }
  };
}

This is how my API route is structured:

// page/api/hello.ts

type Data = {
  name: string
}

const wrapped = withJwt((
  req: NextApiRequest,
  res: NextApiResponse<Data>
) => {
  res.status(200).json({ name: 'John Doe' })
});

export default wrapped;

However, when I visit /api/hello, I encounter the following error message:

Server Error

TypeError: resolver is not a function

Uncaught at Object.apiResolver (file:///root/projects/taskmanager-next/node_modules/next/dist/server/api-utils.js:101:15) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async DevServer.runApi (file:///root/projects/taskmanager-next/node_modules/next/dist/server/next-server.js:320:9) at async Object.fn (file:///root/projects/taskmanager-next/node_modules/next/dist/server/base-server.js:486:37) at async Router.execute (file:///root/projects/taskmanager-next/node_modules/next/dist/server/router.js:228:32) at async DevServer.run (file:///root/projects/taskmanager-next/node_modules/next/dist/server/base-server.js:598:29) at async DevServer.run (file:///root/projects/taskmanager-next/node_modules/next/dist/server/dev/next-dev-server.js:444:20) at async DevServer.handleRequest (file:///root/projects/taskmanager-next/node_modules/next/dist/server/base-server.js:305:20)

What could be causing this issue?

Answer №1

After some trial and error, I finally got it:

The mistake I made was declaring the withJwt function as asynchronous. Only the returned function needs to be asynchronous in order to return a Promise.

Here's the corrected code that is now functioning properly:

export function withJwt<T>(
  handler: ((req: NextApiRequest, res: NextApiResponse<T>, user?: User)=>void|Promise<void>))
  : (req: NextApiRequest, res: NextApiResponse<T | ApiError>)=>Promise<void> {  
  return async (req: NextApiRequest, res: NextApiResponse<T | ApiError>) => {
    const authHeader = req.headers.authorization;
    if(!authHeader || !authHeader.startsWith(JWT_PREFIX)){ 
      return res.status(401).json({
        message: `Don't forget to include 'Authorization: ${JWT_PREFIX}<token>' in the header`,
      });
    }
    let user: User;
    try {
      user = await verify(authHeader.substring(JWT_PREFIX.length));
    } catch(err) {
      return res.status(401).json({message: (err as any).message as string});
    }

    try {
      return handler(req, res, user);
    } catch(err){
      return res.status(500).json({message: (err as any).message});
    }
  };
}

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

The .slice() function in TypeScript has the ability to alter the initial array

I am diving into TypeScript and just tackled my first slice() method. My understanding is that the slice() method is supposed to create a copy of an array. Here's a snippet of the code: class ChapterOne { // Gauss Jordan Elimination // No ...

A: TypeScript Error TS7006: Parameter implicitly has an 'any' type

TS7006: The parameter 'port' is implicitly assigned an 'any' type. constructor(port) { TS7006: The parameter 'message' is implicitly assigned an 'any' type. Emit(message) { I'm confused because all the other r ...

Refreshing Custom Functions within Excel Add-On - Web Edition

Currently, I am working on an Excel Add-In that includes custom functions utilizing the Javascript API. I have been following a particular tutorial for guidance. While attempting to debug using the Web version of Excel due to its superior logging capabili ...

Issue: unable to establish a connection to server at localhost port 5000 while using Next.js getServerSideProps function

I am experiencing an issue with connecting to an API on localhost:5000. The API works perfectly when called from Postman or the browser, but it does not work when called inside Next.js getserverside props: mport { useEffect,useState } from "react"; i ...

Error message displayed on Next/Image: "The first certificate on the next image could not be verified" - NextJS

Recently, I encountered an issue while fetching a public API that had an SSL error. Fortunately, I was able to resolve it by adding the following line of code to a variable: Agent({ rejectUnauthorized: false, keepAlive: false,)} However, when I at ...

Vue encountered a double loading issue when utilizing a library compiled with Webpack

I am facing an issue with my TypeScript library of Vue components that gets compiled into a single JS file using Webpack. The problem arises when the TypeScript project consuming this library also depends on Vue. Upon running the application, I noticed tha ...

The process of invoking the AsyncThunk method within the Reducer method within the same Slice

Within my slice using reduxjs/toolkit, the state contains a ServiceRequest object as well as a ServiceRequest array. My objective is to dispatch a call to a reducer upon loading a component. This reducer will check if the ServiceRequest already exists in ...

TypeScript utility function that retrieves properties from an interface based on a specified type

Is there a way to create a new object type that includes only properties from another Object that match specific types, as opposed to property names? For example: interface A { a: string; b: number; c: string[]; d: { [key: string]: never }; } int ...

Encountered an issue with valid types while executing the following build

Encountering an error when attempting to run the next build process. https://i.stack.imgur.com/qM3Nm.png Tried various solutions including updating to ES6, switching the module to commonJs, downgrading webpack to version 4 with no success. The only worka ...

Having trouble with getStaticProps serialization error in Next.js?

I encountered an error in my Next.js application that reads as follows: Error: Error serializing `.posts[0]` returned from `getStaticProps` in "/blog". Reason: `object` ("[object Promise]") cannot be serialized as JSON. Please only ret ...

"Modifying state within a child component and utilizing the refreshed value in the parent component

I'm currently working on creating a simple header mini cart with a cart item counter in NextJS. I'm utilizing the form state value in the header component and then passing that value to the child components of the header where the numerical quant ...

The new update of ag-grid, version 18.1, no longer includes the feature for enabling cell text selection

I am attempting to disable the clipboard service in ag-grid. I have come across the enableCellTextSelection flag, which supposedly disables it completely. However, when I try to use this flag as a direct property of <ag-grid-angular>, it results in a ...

Exploring a JSON Object in TypeScript: A Step-by-Step Guide

I am currently utilizing Angular 7 and have a query that returns JSON data with a specific format: [ { "text": "test 1", "value": "1", "nbr": "1", "children": [ { "text": "test 1_1", ...

Open the JSON file and showcase its contents using Angular

I am attempting to read a JSON file and populate a table with the values. I've experimented with this.http.get('./data/file.json') .map(response => response.json()) .subscribe(result => this.results =result, function(error) ...

Top tips for handling HTML data in JSON format

I'm looking to fetch HTML content via JSON and I'm wondering if my current method is the most efficient... Here's a sample of what I'm doing: jsonRequest = [ { "id": "123", "template": '<div class=\"container\"&g ...

Stopping HTTP client calls in OnDestroy hook of an Angular Service

Is it possible to automatically unsubscribe from an http call in an Angular service using the ngOnDestroy hook? Just to note, I am already familiar with using the rxjs 'take' operator or manually unsubscribing from the service within the compone ...

Is your Angular5 service failing to transmit data?

I have two components in my code, A and B. Component A contains a form with data that I want to send to component B. However, it seems like component B is not receiving any data. Here is the code for Component A: import { MyService } from 'path/my ...

Tips on preventing the need for null or undefined checks in JS/Typescript singletons that have an initialization function

Is there a way to streamline the process of handling props in an Object literal that is dynamically initialized only once? I'm looking for a pattern that would eliminate the need for repetitive null/undefined checks and throw errors when certain metho ...

Encountering an error message that reads "State.Push is not a valid function" upon integrating

Currently, I am working on developing a Todo app using react-typescript and redux. During testing, I noticed that the app functions properly without redux-persist, displaying the list of added tasks. However, upon integrating redux-persist, the store does ...

Creating a conditional class property requirement in TypeScriptAnother way to implement conditionally required class

I am currently in the process of creating an Event class with a data property that is typed based on the type of the event. Here is the code snippet I have been working on: export interface EventTypes { localeChange: { locale: string; }; translat ...