I was testing get and post requests in jsfiddle to better understand cors and csrf.
fetch('http://localhost:5000/auth')
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Where in the code is an OPTIONS request handled with a status code of 200? I don't have any catch all middleware.
const app = express()
//Listen
//Connect to database
//Middlewares
app.use(express.json())
//Routes
app.use('/auth', require('./routes/auth'))
const router = express.Router()
router.get('/', async (req, res) => {
console.log('test')
res.status(202).send(await User.find())
})
router.post('/signup', async (req, res) => {
})
module.exports = router
I am having a hard time finding an OPTIONS route in the source code. Is express handling other routes as well by default?
For context, when I added cors middleware, I was confused by why the options request had a status code of 204. Then, I removed the cors middleware to see what would happen and was surprised that a response was being sent, which made me wonder what other things are handled by default.
Edit 2: Tried a simpler test without the json middleware in case it did something:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hi')
})
app.listen(3001, () => {
console.log('Listening on port', 3001)
})
Edit 3: Used a simple webpage instead of jsfiddle:
<script>
const data = { name: 'example', password: 'password'};
fetch('http://localhost:3001', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
</script>
No preflight happens for get requests








Express apparently does have code that will, in some circumstances, send a 200 response back from an OPTIONS request. That code is here and here in the Express repository for further context. These two snippets of Express code are shown below here:
And this (which sends a 200 response):
I found this by inserting this middleware into your Express server code and then setting a breakpoint inside the middleware and then stepping through the call to
next()to see exactly what Express does in this case. And, low and behold, it eventually gets tosendOptionsResponse()and sends a 200 response for some OPTIONS requests.FYI, you can use this above middleware to see exactly what is arriving on your server and in what order.
For your particular jsFiddle this is what I see:
You can see there is exactly one inbound request to the server, an OPTIONS request. The express server (on it's own sends a 200 status, but only allows
text/htmlas the content-typefor a GET, HEAD or POST. Since the jsFiddle wants to sentcontent-type: application/json`, the browser fails the request as a CORS violation.NOTE and further explanation
As a point of confusion, the Chrome inspector (network tab) in the browser are showing more requests than actually show up on the server so you are being deceived by what Chrome is showing. When I run your client-side code in a JSFiddle, I get ONLY one OPTIONS request send to the server and NO other requests, even though the Chrome inspector shows more than that. What I think is happening is that Chrome sees the POST request as being
content-type: application/jsonso it needs pre-flight. It sends the OPTIONS request as the pre-flight, it gets back a 200 response, but does NOT get back the headers it needs to allow that specific POST request to be sent so it doesn't send it.When in doubt, instrument your server and see exactly what it is actually receiving.
Chrome deprecating direct access to private network endpoints
See this article. This may also be a reason why the public website jsFiddle can't access
localhostor why there are extra warnings in the Chrome inspector. This is a fairly new restriction (in the last year). I've seen some other sites have to remove features because of this. For example, Tivo had to remove the ability to watch saved Tivo recordings (which are served from a local http server) from Chrome even when on my own local network. You can now only do that from an app.