Reputation: 3
I'm new to Next js and I'm a bit lost regarding the fetch data to an external API.
I basically want to fetch data (GET, POST, PUT, whatever), and add some pieces of logic that I don't wish to rewrite every time I call an endpoint: in my case it's adding the authorization token to the header for each request.
I used to do this with axios in a basic react project thanks to middleware or addAsyncRequestTransform
function.
I already have an external REST API done by a backend dev.
In my current project, I fetch users in my Users server component:
// page.tsx file
export default async function Users() {
const users = await fetchUsers();
return (
<UserTable data={users} />
);
}
I'm using server actions to fetch my users:
// admin.action.ts file
const endpoint = '/admin';
export async function fetchUsers() {
return await fetchWrapper<User[]>(endpoint + '/accounts');
}
and I have a fetchWrapper function to add my authorization token and other options to the header if necessary
// fetchWrapper.ts
import { notFound } from 'next/navigation';
interface FetchOptions extends RequestInit {
headers?: HeadersInit;
}
export interface ErrorData {
code: number;
status: string;
message: string;
}
// Define a generic FetchWrapper type
type FetchWrapper = <T>(url: string, options?: FetchOptions) => Promise<T>;
const fetchWrapper: FetchWrapper = async <T>(
url: string,
options: FetchOptions = {}
): Promise<T> => {
const token = "<my-hardcoded-token>";
const defaultHeaders: HeadersInit = {
'Content-Type': 'application/json',
};
if (token) {
defaultHeaders['Authorization'] = `Bearer ${token}`;
}
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL as string;
const response = await fetch(`${baseUrl}${url}`, {
...options,
headers: {
...defaultHeaders,
...options.headers,
},
});
if (!response.ok) {
const errorData = (await response.json()) as ErrorData;
if (errorData.code === 404) notFound();
throw new Error(`Error ${response.status}: ${errorData.message}`);
}
return response.json() as Promise<T>;
};
export default fetchWrapper;
First of all, I'm not even sure that I should be using a GET
to fetch my users with a server-action even though it seems to be working.
Next js documentation says:
Behind the scenes, actions use the POST method, and only this HTTP method can invoke them.
In a second place, I can't useSession
from next-auth to get the token in my fetchWrapper
function to add it for each request. So for not it's hardcoded token that I need to replace manually every time.
I tried to explore the middleware
option in order to add the authorization header to my requests, but I ran into a problem:
// middleware.ts
export function middleware(request: NextRequest) {
console.log('🚀 ~ request >>', request);
}
when I log the request in the middleware I can see that the nextUrl is http://localhost:4000/users
instead of being the url of my external API.
as per chatgpt
When you log the request in Next.js middleware, the nextUrl refers to the internal URL of your Next.js application, not the external API you are fetching data from. This is because the middleware runs on requests made to your Next.js server itself, not on the outgoing requests made by your application to external services.
I also read about the route handlers, but since i'm using an external api I don't really see the point of using these.
Am I missing something ? Is middleware not designed to call external API ? Should I keep my current way of fetching data and find a way to pass the token every time ?
Upvotes: 0
Views: 676