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;
CodePudding user response:
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 theaxios.post
toaxios.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 submittingslug
, 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:
- Axios.request documentation -- Take a look at params, maxRedirects and validateStatus properties.
- what's the different between app.post and app.use in nodes express?