Skip to content
Advertisement

Access from origin ‘https://example.com’ has been blocked even though I’ve allowed https://example.com/

I have an app made with React, Node.js and Socket.io
I deployed Node backend to heroku , frontend to Netlify


I know that CORS errors is related to server but no matter what I add, it just cant go through that error in the picture below.
I also added proxy script to React’s package.json as “proxy”: “https://googledocs-clone-sbayrak.herokuapp.com/”

corserror

And here is my server.js file;

const mongoose = require('mongoose');
const Document = require('./Document');
const dotenv = require('dotenv');
const path = require('path');
const express = require('express');
const http = require('http');
const socketio = require('socket.io');
dotenv.config();

const app = express();
app.use(cors());
const server = http.createServer(app);
const io = socketio(server, {
  cors: {
    origin: 'https://googledocs-clone-sbayrak.netlify.app/',
    methods: ['GET', 'POST'],
  },
});

app.get('/', (req, res) => {
  res.status(200).send('hello!!');
});

const connectDB = async () => {
  try {
    const connect = await mongoose.connect(process.env.MONGODB_URI, {
      useUnifiedTopology: true,
      useNewUrlParser: true,
    });

    console.log('MongoDB Connected...');
  } catch (error) {
    console.error(`Error : ${error.message}`);
    process.exit(1);
  }
};

connectDB();


let defaultValue = '';

const findOrCreateDocument = async (id) => {
  if (id === null) return;

  const document = await Document.findById({ _id: id });

  if (document) return document;

  const result = await Document.create({ _id: id, data: defaultValue });
  return result;
};
io.on('connection', (socket) => {
  socket.on('get-document', async (documentId) => {
    const document = await findOrCreateDocument(documentId);
    socket.join(documentId);
    socket.emit('load-document', document.data);
    socket.on('send-changes', (delta) => {
      socket.broadcast.to(documentId).emit('receive-changes', delta);
    });

    socket.on('save-document', async (data) => {
      await Document.findByIdAndUpdate(documentId, { data });
    });
  });
  console.log('connected');
});

server.listen(process.env.PORT || 5000, () =>
  console.log(`Server has started.`)
);

and this is where I make request from frontend;

import Quill from 'quill';
import 'quill/dist/quill.snow.css';
import { useParams } from 'react-router-dom';
import { io } from 'socket.io-client';

const SAVE_INTERVAL_MS = 2000;
 

const TextEditor = () => {
  const [socket, setSocket] = useState();
  const [quill, setQuill] = useState();
  const { id: documentId } = useParams();

  useEffect(() => {
    const s = io('https://googledocs-clone-sbayrak.herokuapp.com/');
    setSocket(s);
     

    return () => {
      s.disconnect();
    };
  }, []); 

 /* below other functions */
 /* below other functions */
 /* below other functions */
 }

Advertisement

Answer

TL;DR

https://googledocs-clone-sbayrak.netlify.app/ is not an origin. Drop that trailing slash.

More details about the problem

No trailing slash allowed in the value of the Origin header

According to the CORS protocol (specified in the Fetch standard), browsers never set the Origin request header to a value with a trailing slash. Therefore, if a page at https://googledocs-clone-sbayrak.netlify.app/whatever issues a cross-origin request, that request’s Origin header will contain

https://googledocs-clone-sbayrak.netlify.app

without any trailing slash.

Byte-by-byte comparison on the server side

You’re using Socket.IO, which relies on the Node.js cors package. That package won’t set any Access-Control-Allow-Origin in the response if the request’s origin doesn’t exactly match your CORS configuration’s origin value (https://googledocs-clone-sbayrak.netlify.app/).

Putting it all together

Obviously,

'https://googledocs-clone-sbayrak.netlify.app' ===
    'https://googledocs-clone-sbayrak.netlify.app/'

evaluates to false, which causes the cors package not to set any Access-Control-Allow-Origin header in the response, which causes the CORS check to fail in your browser, hence the CORS error you observed.

Example from the Fetch Standard

Section 3.2.5 of the Fetch Standard even provides an enlightening example of this mistake,

Access-Control-Allow-Origin: https://rabbit.invalid/

and explains why it causes the CORS check to fail:

A serialized origin has no trailing slash.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement