最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - CORS Issue When Using External Service for API Calls in Next.js" - Stack Overflow

programmeradmin4浏览0评论

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
Add a comment  | 

1 Answer 1

Reset to default 0

The 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.

发布评论

评论列表(0)

  1. 暂无评论