Search code examples
google-chromehttpscache-control

Chrome doesn't send "if-none-match" header in HTTPS (but sends it in HTTP)


tl;dr: Chrome is not sending "If-None-Match" header for HTTPS request but sends it for HTTP request. Firefox always send "If-None-Match", both in HTTPS and HTTP.

I was trying to optimize cookies management for my node server when I came across a weird behavior with Chrome. I will try to describe it and compare it with Firefox.

First, here is the HTTP node server I'm using to test this:

#!/usr/bin/env node

'use strict';

const express = require('express');
const cors = require('cors');
const compression = require('compression');
const pathUtils = require('path');
const fs = require('fs');

const http = require('http');
let app = express();
app.disable('x-powered-by');
app.use(function (req, res, next) {
    res.set('Cache-control', 'no-cache');
    console.log(req.headers);
    next();
});

app.use(express.json({ limit: '50mb' }));
app.use(cors());
app.use(compression({}));

let server = http.createServer(app);

app.get('/api/test', (req, res) => {
    res.status(200).send(fs.readFileSync(pathUtils.join(__dirname, 'dummy.txt')));
});

server.listen(1234);

And there the client code :

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <script>
            let test = fetch('http://localhost:1234/api/test', { mode: 'no-cors' })
                .then((res) => {
                    return res.text();
                })
                .then((resText) => console.log(resText));
        </script>
    </body>
</html>

I use the header "no-cache" to force the client to re-validate the response. If I've understood correctly how the cache work, I'm expecting client to send the request with the "If-None-Match" header having the previous request's e-tag and the server responding with a 304 code.

Here is the result when I refresh the page in Firefox (so at least one response has already be received). I embedded the server log of the request header. enter image description here Here the header "If-None-Match" is sent by the client request, as expected.

Now the same test with Chrome gives :

enter image description here

Well, here Chrome shows a 200 response code, but under the hood, it's really a 304 response that is sent by the server, which is shown by this wireshark capture :

enter image description here

As you can see, Chrome send the "If-None-Match" header with the correct e-tag, hence the 304 response.

So now, let's try this with HTTPS. In the server code, I just replaced require('http'); by require('https') and pass my ssl keys in createServer options (as described here)

So first, Firefox behaviour:

enter image description here

I've included the wireshark capture. And as you can see, everything is right, Firefox has the expected behaviour.

Now let's see the same thing with Chrome :

enter image description here

Here is my problem : as you can see, "If-None-Match" is not sent by Chrome. So as expected, the server returns a 200 response which can be seen in the wireshark capture (I refreshed the page twice, that's why there are 2 exchanges).

Do anyone have an idea on why Chrome has this weird behaviour?


Solution

  • I think it happened because you didn't set in your setting the certificat of your localhost.

    Go to the settings and add it :)

    chrome settings capture