Reputation: 41
I have been developing this app for months now and using axios to make http requests from my React front-end to my Express backend in both development and production without problem. Yesterday, I began getting "net::ERR_EMPTY_RESPONSE" messages, which after checking the network calls I realized was because it was doing a pre-flight OPTIONS request, then not making the subsequent actual request.
I have included the cors express module and placed it above my routes on my server. I have specifically created middleware for all OPTIONS requests that will set their "Access-Control-" headers to allow all origins,methods and headers(yes, I know it's a vulnerability). In my react application I have set "proxy":"https://example.com" inside my package.json. Even after doing all of this I still cannot get my React application(or the browser?) to cooperate with any "complicated" requests(my understanding is that anything with Authorization headers will trigger a preflight). I had been accessing these protected routes from both development(localhost:3000) and from the production app with the same origin(https://example.com) successfully until yesterday. I have seen a lot of other people with issues with this, but none of them had been unable to make network requests to their own server from production.
//package.json for React app
"name": "homebrew",
"version": "0.1.0",
"private": true,
"proxy": "https://example.com",
"dependencies": {
"axios": "^0.19.0",
"gsap": "^2.1.2",
"jwt-decode": "^2.2.0",
"react": "^16.8.5",
"react-dom": "^16.8.5",
"react-helmet": "^5.2.1",
"react-router-dom": "^5.0.0",
"react-scripts": "2.1.8",
"request": "^2.88.0"
},
//Admin component in React App
componentDidMount(){
var jwt = JSON.parse(localStorage.getItem('brew-jwt'));
let config =
{ headers : {
'Authorization': "Bearer " + jwt,
}
}
console.log(jwt);
axios.get('https://example.com/admin/submissions',config)
.then(response =>{
console.log(response);
})
.catch(error=>{
console.log(error);
})
}
//server.js file
var port = 443;
var app = express();
app.use(cors());
app.set('views', path.join(__dirname,'views'));
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
//Farther down in my server.js file
app.options('*',function(req,res){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,HEAD,POST,PATCH');
res.header('Access-Control-Allow-Headers',
'Authorization,Origin,Referer,Content-Type,Accept,User-Agent');
res.sendStatus(200);
res.end();
});
app.use('/',index);
app.use('/users',users);
app.use('/forgot',forgot);
app.use('/ingredients',ingredients);
app.use('/admin',admin);
app.use('*',index);
The OPTIONS request sends this request to my server:
Access-Control-Request-Headers: authorization,content-type
Access-Control-Request-Method: POST
Origin: http://localhost:3000
Referer: http://localhost:3000/Admin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
The OPTIONS request gets this response from my server:
Request URL: https://example.com/admin/submissions
Request Method: OPTIONS
Status Code: 204 No Content
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
The headers my actual request were to send are:
Accept,Auhtorization,Content-Type,Origin,Referer,User-Agent
This request is never being sent, though, because I am logging requests on my server and it never receives it.
Note: I am able to make "simple" network requests from my front-end still, like fetching public resources, images, etc.
Is this a chrome problem? A react problem? Axios problem? Help!
Upvotes: 3
Views: 1295
Reputation: 41
Solved it. The issue was that the jwt (json web token) that I was sending in my Authorization header was too large due to the fact that it contained other user data besides their credentials (quite a bit of data actually). I figured this out when I accidentally deleted the token from local storage and still attempted the request. It managed to send the Authorization header but it' s content was just 'Bearer null' . I logged in to receive the token again and reattempt and it gave me the CORS looking issue. IT WASN'T A CORS ISSUE AFTER ALL. My request header was too large!
Solution was to send the user 2 tokens when they login; a small user jwt that would be sent back to the server as an Authorization header and a larger user-data jwt that would hold all the users saved data. When the jwt was too big to be sent as a header it created the appearance of a CORS/preflight issue, but really the only reason it wasn't making the request was the large header. Lots of people are probably having this issue and don't realize it (i've seen it everywhere people losing their minds over this).
Upvotes: 1