0

I created a project and faced the CORS Policy error when redirecting to another Domain or website out of my project, for example I want to visit https://www.google.com by clicking a button or before some page load.

I did the redirection in backend.

const visitLink = async (req, res, next) => {
  try {
    const { id } = req.query;
    const website = await Urls.find({ slug: id });
    res.redirect(`https://www.google.com`);
  } catch (error) {
    throw new Error(error.message);
  }
};

but the error not happening from every page in my website, for example if i set button in Profile page and by clicking it redirect the user to Google's Website it works just fine and error not happening, but if i add same button in index page to redirect user to same website its make CORS Policy error.

Index Page

import axios from "../axiosConfig";
import LinkShortnerForm from "../components/Link/LinkShortner";
import Layout from "../components/Layout/layout";
import Navbar from "../components/Navbar/navbar";
import { useState } from "react";

const Home = () => {
  const [Link, setLink] = useState();
  const [Error, setError] = useState();
  const [Success, setSuccess] = useState();

  const submitForm = async (url, slug) => {
    try {
      const res = await axios.post("/api/urls", { url, slug });
      if (res.data) {
        setLink(res.data);
        setError();
        setSuccess(true);
      }
    } catch (error) {
      setError(error.response.data);
      console.log(error);
      setSuccess(false);
    }
  };
  return (
    <Layout title="New Page">
      <Navbar active={"home"} />
      <div className={"container"}>
        <LinkShortnerForm
          submitForm={submitForm}
          shortUrl={Link}
          Err={Error}
          success={Success}
        />
      </div>
    </Layout>
  );
};

export default Home;

LinkShortnerForm Component

import React, { useState } from "react";
import classes from "./formShortner.module.css";
import Link from "next/link";

const LinkShortner = (props) => {
  const [Url, setUrl] = useState();
  const [Slug, setSlug] = useState();

  const submitHandler = (e) => {
    e.preventDefault();
    props.submitForm(Url, Slug);
  };
  return (
    <div className={"mt-5 " + classes.form}>
      <h1 className={classes.header}>URL Shortner</h1>
      <div className="row">
        <div className="col-sm-8">
          <form
            onSubmit={submitHandler}
            action=""
            className={classes.form + "row "}
          >
            <div className={"col-sm-12 " + classes.formInput}>
              <div className="inputField">
                <label htmlFor="Url">URL</label>
                <input
                  type="text"
                  className="form-control"
                  id="Url"
                  onChange={(e) => setUrl(e.target.value)}
                />
              </div>
            </div>
            <div className={"col-sm-12 " + classes.formInput}>
              <div className="inputField">
                <label htmlFor="ID">Slug</label>
                <input
                  type="text"
                  className="form-control"
                  id="ID"
                  onChange={(e) => setSlug(e.target.value)}
                />
              </div>
            </div>
            <div className={"col-sm-12 " + classes.formInput}>
              <div className="inputField">
                <button
                  className={"btn mt-5 " + classes.btn}
                >
                  Submit
                </button>
              </div>
            </div>
          </form>
          <>
            {props.shortUrl && props.success ? (
              <div className={classes.shortLinkSection}>
                <h2 className="my-5">SUCCESS</h2>
                <div className={classes.boxContainer}>
                  <Link href={props.shortUrl}>
                    <h3>Short URL : {props.shortUrl}</h3>
                  </Link>
                </div>
              </div>
            ) : null}

            {props.Err ? (
              <div className={classes.shortLinkSectionErr}>
                <h2 className="my-5">Failed</h2>
                <div className={classes.boxContainerErr}>
                  <h3>Problem : {props.Err}</h3>
                </div>
              </div>
            ) : null}
          </>
        </div>
      </div>
    </div>
  );
};

export default LinkShortner;

In profile page i added only one button by clicking it redirect the user to the page (he/she) clicked.

and here is the next.config file.

const nextConfig = {
  reactStrictMode: false,

  env: {
    NEXTAUTH_SECRET: "******",
    MONGODB_URI:
      "*********",
  },
};

module.exports = nextConfig;

finally when user create a short link should visit it, and in the link redirect user to the real website or URL, here is the page i called VisitRealURL

import axios from "../axiosConfig";
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";

const VisitRealURL = () => {
  const [Error, setError] = useState();
  const router = useRouter();
  useEffect(() => {
    const visitUrl = async () => {
      try {
        if (router.query.id) {
          const { data } = await axios(`/api/visitPage?id=${router.query.id}`);
          window.location = data;
        }
      } catch (err) {
        // setError(err.response.data);
        console.log(err);
      }
    };
    visitUrl();
  }, [router.query.id]);

  return <div>{Error && <h1>{Error}</h1>}</div>;
};

export default VisitRealURL;

Rawand
  • 47
  • 1
  • 1
  • 8

1 Answers1

2

You are redirecting your API call to google.com which results in the CORS error. Google.com doesn't allow cross origin requests.

You should send a reply with the data you need and make use the response at the client side. Also you should inform the client, if the search failed. An errorcode for not found will be fine.

const visitLink = async (req, res, next) => {
  try {
    const { id } = req.query;
    const website = await Urls.find({ slug: id });
    res.status(200).json(website);
  } catch (error) {
    res.status(404); // will trigger the error path on the client side
    throw new Error(error.message);
  }
};

Instead of 404 you can also use a different status code larger or equal 400.

The code also contains some other minor errors.

  • You are sending a post request but you try to get the data from req.query which only contains the information from the query paramaters of the requested url (http://example/?queryParameter=foo). Changing the axios.post to axios.get and appending the object as url search params will solve this.

    If it has to be a post request, you should take a look at the documentation for req.body and add the required middleware(s).

  • You are not submitting a query parameter id as a value in your axios request either, you are submitting slug, therefor you should change this in the server or client side function too.

await axios.get("/api/urls", { params: { urls, id: slug } });

/*
If you are using app.use(...) (or router.use(...)) ignore this:

  At the server side you should change:
    app.post("/api/urls", visitLink); // or router.post(...)
  to:
 */
app.get("/api/urls", visitLink); // or router.get(...)

Should solve the issues mentioned.

Other useful info:

Christopher
  • 3,124
  • 2
  • 12
  • 29
  • Thank You so much, you meant i should doing the redirection in client side? Thank you for your notice about POST and GET Http Request, but in the index page as it has in the question its all about creating new Short URL based on the real URL not sending get request to load the page. this lines is used to send user to another page and in there sending get request to redirect the user to the real URL **https://www.googe.com** in my question. `

    Short URL : {props.shortUrl}

    `
    – Rawand Jan 01 '23 at 21:07
  • 1
    If you want to redirect the client to a new url when the API call is successful, you can use the response and `window.location = res.data.url` for example. – Christopher Jan 01 '23 at 21:10
  • Thank you so much, i'm doing it but i need a better solution like doing redirection in server side and get rid of this error. – Rawand Jan 01 '23 at 21:12
  • now i edited the question, and added the page that takes user to real URL and its code – Rawand Jan 01 '23 at 21:17
  • There you do already what I mentioned above. You use `window.location = ...`. -- You have to use the same method, if the reply from the API call was successful. – Christopher Jan 01 '23 at 21:20
  • Yes sir i did, but i wanted to do the redirection in server side not in client side. – Rawand Jan 01 '23 at 22:38
  • Why do you want to redirect it on the server side? The only possible thing i can think off, is to check if the given (long) URL is still reachable. But for this, you don't need to redirect the client. In that situation, you have to make a (new) request at the serverside and check the response code. If an error occurs, forward the response code to the client or send a 404 on a timeout. – Christopher Jan 01 '23 at 23:20
  • I want to redirect from serverside just because if i send the URL to frontend then redirect user to long URL it takes some time and i don't want it... anyway thank you so much, i appreciate your discussion and mark your comment as the right answer because helped me and discuss it well. – Rawand Jan 02 '23 at 06:56