I am encountering an issue with Next.js that I don't quite understand. I have a service file that I want to use to make API calls faster and more structured. However, when I call the API via this service, I get a CORS error, but everything works when I call the API directly from my component.
My apiService.ts file:
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
const apiClient = axios.create({
baseURL: 'http://localhost:4000',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*', // Allow all origins
},
withCredentials: true,
});
// Generic function for GET requests
export const get = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
try {
const response: AxiosResponse<T> = await apiClient.get(url, config);
return response.data;
} catch (error) {
console.error('GET request error:', error);
throw error;
}
};
// Generic function for POST requests
export const post = async <T, R>(url: string, data: T, config?: AxiosRequestConfig): Promise<R> => {
try {
const response: AxiosResponse<R> = await apiClient.post(url, data, config);
return response.data;
} catch (error) {
console.error('POST request error:', error);
throw error;
}
};
// Generic function for PUT requests
export const put = async <T, R>(url: string, data: T, config?: AxiosRequestConfig): Promise<R> => {
try {
const response: AxiosResponse<R> = await apiClient.put(url, data, config);
return response.data;
} catch (error) {
console.error('PUT request error:', error);
throw error;
}
};
// Generic function for DELETE requests
export const deleteRequest = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
try {
const response: AxiosResponse<T> = await apiClient.delete(url, config);
return response.data;
} catch (error) {
console.error('DELETE request error:', error);
throw error;
}
};
In my modal component (ModalCreateExercise.tsx), I call the API like this:
'use client'
import { zodResolver } from "@hookform/resolvers/zod"
import { SubmitHandler, useForm } from "react-hook-form"
import { z } from "zod"
import axios from 'axios';
import { BaseModal } from "@/components/commun/BaseModal"
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { createExercise, getExercises } from "@/services/exerciseService"
import { Exercise } from "@/types/exercise"
import { useEffect, useState } from "react"
import { get, post } from "@/app/services/axiosService";
const formSchema = z.object({
name: z.string().min(2, {
message: "Username must be at least 2 characters.",
}),
})
export function ModalCreateExercise() {
const [exercises, setExercises] = useState<Exercise[]>([]);
//it's working
useEffect(() => {
const fetchExercises = async () => {
try {
// Making the API call with axios directly
const response = await axios.get<Exercise[]>('http://localhost:4000/exercises');
console.log('Exercises fetched:', response.data);
} catch (error) {
console.error('Error fetching exercises:', error);
}
};
fetchExercises();
}, []);
// don't working
useEffect(() => {
const fetchExercises = async () => {
try {
const response = await get<Exercise[]>('/exercises');
console.log('Exercises fetched:', response);
} catch (error) {
console.error('Error fetching exercises:', error);
}
};
fetchExercises();
}, []);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: ""
},
})
const onSubmit = async() => {
const data: Exercise = {
userId: 1,
name: form.getValues().name,
};
try {
const newExercise = await post<typeof data, Exercise>('/exercises', data);
console.log('Exercise created:', newExercise);
} catch (error) {
console.error('Error creating exercise:', error);
}
};
return (
<BaseModal className="ml-auto" title="Créer un exercice" description="Créer un exercice pour vos étudiants" buttonTitle="Créer un exercice" saveButtonTitle="Créer">
<div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Nom de l'exercice</FormLabel>
<FormControl>
<Input placeholder="Nom" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
</div>
</BaseModal>
)
}
My issue: When I use the native axios method in the useEffect, everything works fine, and I can fetch the data from the API without any CORS issues. However, as soon as I try to call the API via my service with Axios, I run into a CORS problem.
The backend server (NestJS) is configured to accept CORS requests, but the issue only occurs when I call the API via the service I created. The problem seems to stem from the fact that the API is not recognizing calls coming from this service.
Here's what I've tried:
I verified the CORS configuration on my NestJS server, and it seems correct. I attempted to add Access-Control-Allow-Origin headers in my service file, but it didn't resolve the issue. Do you have any idea why this happens? Perhaps something related to how Axios is configured or how cookies are handled?
Thank you in advance for your help!
I am encountering an issue with Next.js that I don't quite understand. I have a service file that I want to use to make API calls faster and more structured. However, when I call the API via this service, I get a CORS error, but everything works when I call the API directly from my component.
My apiService.ts file:
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
const apiClient = axios.create({
baseURL: 'http://localhost:4000',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*', // Allow all origins
},
withCredentials: true,
});
// Generic function for GET requests
export const get = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
try {
const response: AxiosResponse<T> = await apiClient.get(url, config);
return response.data;
} catch (error) {
console.error('GET request error:', error);
throw error;
}
};
// Generic function for POST requests
export const post = async <T, R>(url: string, data: T, config?: AxiosRequestConfig): Promise<R> => {
try {
const response: AxiosResponse<R> = await apiClient.post(url, data, config);
return response.data;
} catch (error) {
console.error('POST request error:', error);
throw error;
}
};
// Generic function for PUT requests
export const put = async <T, R>(url: string, data: T, config?: AxiosRequestConfig): Promise<R> => {
try {
const response: AxiosResponse<R> = await apiClient.put(url, data, config);
return response.data;
} catch (error) {
console.error('PUT request error:', error);
throw error;
}
};
// Generic function for DELETE requests
export const deleteRequest = async <T>(url: string, config?: AxiosRequestConfig): Promise<T> => {
try {
const response: AxiosResponse<T> = await apiClient.delete(url, config);
return response.data;
} catch (error) {
console.error('DELETE request error:', error);
throw error;
}
};
In my modal component (ModalCreateExercise.tsx), I call the API like this:
'use client'
import { zodResolver } from "@hookform/resolvers/zod"
import { SubmitHandler, useForm } from "react-hook-form"
import { z } from "zod"
import axios from 'axios';
import { BaseModal } from "@/components/commun/BaseModal"
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { createExercise, getExercises } from "@/services/exerciseService"
import { Exercise } from "@/types/exercise"
import { useEffect, useState } from "react"
import { get, post } from "@/app/services/axiosService";
const formSchema = z.object({
name: z.string().min(2, {
message: "Username must be at least 2 characters.",
}),
})
export function ModalCreateExercise() {
const [exercises, setExercises] = useState<Exercise[]>([]);
//it's working
useEffect(() => {
const fetchExercises = async () => {
try {
// Making the API call with axios directly
const response = await axios.get<Exercise[]>('http://localhost:4000/exercises');
console.log('Exercises fetched:', response.data);
} catch (error) {
console.error('Error fetching exercises:', error);
}
};
fetchExercises();
}, []);
// don't working
useEffect(() => {
const fetchExercises = async () => {
try {
const response = await get<Exercise[]>('/exercises');
console.log('Exercises fetched:', response);
} catch (error) {
console.error('Error fetching exercises:', error);
}
};
fetchExercises();
}, []);
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: ""
},
})
const onSubmit = async() => {
const data: Exercise = {
userId: 1,
name: form.getValues().name,
};
try {
const newExercise = await post<typeof data, Exercise>('/exercises', data);
console.log('Exercise created:', newExercise);
} catch (error) {
console.error('Error creating exercise:', error);
}
};
return (
<BaseModal className="ml-auto" title="Créer un exercice" description="Créer un exercice pour vos étudiants" buttonTitle="Créer un exercice" saveButtonTitle="Créer">
<div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Nom de l'exercice</FormLabel>
<FormControl>
<Input placeholder="Nom" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
</div>
</BaseModal>
)
}
My issue: When I use the native axios method in the useEffect, everything works fine, and I can fetch the data from the API without any CORS issues. However, as soon as I try to call the API via my service with Axios, I run into a CORS problem.
The backend server (NestJS) is configured to accept CORS requests, but the issue only occurs when I call the API via the service I created. The problem seems to stem from the fact that the API is not recognizing calls coming from this service.
Here's what I've tried:
I verified the CORS configuration on my NestJS server, and it seems correct. I attempted to add Access-Control-Allow-Origin headers in my service file, but it didn't resolve the issue. Do you have any idea why this happens? Perhaps something related to how Axios is configured or how cookies are handled?
Thank you in advance for your help!
Share Improve this question asked Mar 25 at 3:33 KevinKevin 11 4- the issue is likely with the server, your client side code is more or less irrelevant if the server doesn't issue the correct response headers – Bravo Commented Mar 25 at 3:36
- Your "component" request adds headers and credentials. That is likely to trigger CORS. – James Commented Mar 25 at 4:03
- Please add the exact error message to your post, because there are different kinds of "CORS errors" – derpirscher Commented Mar 25 at 8:07
- Your post contains several indicators that ChatGPT or another LLM was used to generate it. For a variety of reasons, the use of such generative AI tools is strictly disallowed on Stack Overflow. Please edit your question to remove and replace content that was generated using these tools. – esqew Commented Mar 25 at 13:42
1 Answer
Reset to default 0The issues is how you are approaching CORS.
I'll break it down for you:
In the apiService.ts
file, while you are creating the axios instance, you are setting the Access-Control-Allow-Origin
to '*', and withCredentials
to true
.
This is not supported. You can either set the wild card *
or set withCredential
to true
, not both.
This isnt a problem in your API calls in the component because, you are not passing the above configs.
You may either remove withCredentials
config in the service file, or update the Access-Control-Allow-Origin
header to a non wildcard entry.