Next.js Discord

Discord Forum

Nextjs15 CORs: i keep getting blocked

Answered
Chilean Terrier posted this in #help-forum
Open in Discord
Chilean TerrierOP
Access to fetch at 'https://my_domain.com/api/petLevel' from origin 'https://www.my_domain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.



i've put the headers. see the image
Answered by Black Turnstone
maybe
instead of hard coding

const apiUrl =
    process.env.NODE_ENV === "development"
      ? "http://localhost:3000/api/petLevel"
      : "https://hhr-bot.xyz/api/petLevel";


you can just pass

const apiUrl = '/api/petLevel';
View full answer

13 Replies

Black Turnstone
Can you share some code for api and for how you are fetching it in component?
@Black Turnstone Can you share some code for api and for how you are fetching it in component?
Chilean TerrierOP
import { createClient } from "@supabase/supabase-js";
import { NextResponse } from "next/server";

const supabaseKey = process.env.SUPABASE_KEY as string;
const supabaseUrl = process.env.SUPABASE_URL as string;

console.log(supabaseUrl);

const supabase = createClient(supabaseUrl, supabaseKey);

export async function GET(request: Request) {
  try {
    const { searchParams } = new URL(request.url);
    const limit = searchParams.get("limit");

    let query = supabase.from("pet_lvl_lb").select("*");

    if (limit) {
      const limitValue = parseInt(limit);
      if (!isNaN(limitValue) && limitValue > 0) {
        query = query.limit(limitValue);
      }
    }

    const { data, error } = await query;

    if (error) {
      console.error("Error fetching data from Supabase:", error);
      return NextResponse.json(
        { error: "Failed to fetch data" },
        {
          status: 500,
          headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET",
            "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Accept",
            "Access-Control-Allow-Credentials": "true",
          },
        }
      );
    }

    return NextResponse.json(data, {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET",
        "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Accept",
        "Access-Control-Allow-Credentials": "true",
      },
    });
  } catch (error) {
    console.error("Internal Server Error:", error);
    return NextResponse.json(
      { error: "Internal Server Error" },
      {
        status: 500,
        headers: {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "GET",
          "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Accept",
          "Access-Control-Allow-Credentials": "true",
        },
      }
    );
  }
}
Black Turnstone
component?
@Black Turnstone component?
Chilean TerrierOP
/* eslint-disable */
'use client';

import type { Metadata } from "next";
import { useEffect, useState } from "react";
import { Pet, columns } from "./columns";
import { DataTable } from "./data-table";

const metadata: Metadata = {
  title: "Pet Level Leaderboard",
  description:
    "See the pet level rankings in the game.",
};

export default function PetLeaderboardPage() {
  const [petsData, setPetsData] = useState<Pet[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const apiUrl =
    process.env.NODE_ENV === "development"
      ? "http://localhost:3000/api/petLevel"
      : "https://hhr-bot.xyz/api/petLevel";

  useEffect(() => {
    async function fetchPetsData() {
      try {
        const res = await fetch(apiUrl, { cache: "no-store" });
        if (!res.ok) {
          throw new Error("Failed to fetch data");
        }
        const data: Pet[] = await res.json();
        const formattedData = data.map((pet) => ({
          pet_name: pet.pet_name,
          level: Number(pet.level).toLocaleString(),
          type: pet.type,
          rank: pet.rank,
        }));
        setPetsData(formattedData);
      } catch (err) {
        if (err instanceof Error) {
          setError(err.message);
        } else {
          setError("An unknown error occurred.");
        }
      } finally {
        setLoading(false);
      }
    }
    fetchPetsData();
  }, [apiUrl]);

  if (loading) {
    return (
      <div className="text-center text-lg text-gray-600 mt-10">
        Loading...
      </div>
    );
  }

  if (error) {
    return (
      <div className="text-center text-red-600 text-lg mt-10">
        Error: {error}
      </div>
    );
  }

  return (
    <div className="container mx-auto py-10">
      <DataTable columns={columns} data={petsData} />
    </div>
  );
}
Black Turnstone
Working in dev env?
@Black Turnstone Working in dev env?
Chilean TerrierOP
yes.
wait... let me qq fetch latest code from main.
Black Turnstone
maybe
instead of hard coding

const apiUrl =
    process.env.NODE_ENV === "development"
      ? "http://localhost:3000/api/petLevel"
      : "https://hhr-bot.xyz/api/petLevel";


you can just pass

const apiUrl = '/api/petLevel';
Answer
Black Turnstone
No need to write full url since fetching on client component it will automatically look for hostname.
@Chilean Terrier wait... let me qq fetch latest code from main.
Chilean TerrierOP
even still it works on dev, but not on main prod website
@Chilean Terrier even still it works on dev, but not on main prod website
Black Turnstone
probably because you are fetching https://hhr-bot.xyz/api/petLevel from https://www.hhr-bot.xyz/ -> that www makes a difference