Skip to content

Commit

Permalink
Handle ETag and If-None-Match (#39)
Browse files Browse the repository at this point in the history
* Automatically handle ETags

* Document what is happening

* Clarify with comment

* Better check, as range headers can be 0

* Clarify even more
  • Loading branch information
leo authored Jul 25, 2018
1 parent afc1387 commit d7e026b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ Allows you to set custom headers (and overwrite the default ones) for certain pa
}
```

If you define the `ETag` header for a path, the handler will automatically reply with status code `304` for that path if a request comes in with a matching `If-None-Match` header.

**NOTE:** The paths can only contain globs that are matched using [minimatch](https://github.com/isaacs/minimatch).

### directoryListing (Boolean|Array)
Expand Down
13 changes: 13 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,19 @@ module.exports = async (request, response, config = {}, methods = {}) => {
const stream = await handlers.createReadStream(absolutePath);
const headers = await getHeaders(config.headers, current, absolutePath, stats);

// We need to check for `headers.ETag` being truthy first, otherwise it will
// match `undefined` being equal to `undefined`, which is true.
//
// Checking for `undefined` and `null` is also important, because `Range` can be `0`.
//
// eslint-disable-next-line no-eq-null
if (request.headers.range == null && headers.ETag && headers.ETag === request.headers['if-none-match']) {
response.statusCode = 304;
response.end();

return;
}

response.writeHead(response.statusCode || 200, headers);
stream.pipe(response);
};
38 changes: 38 additions & 0 deletions test/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1031,3 +1031,41 @@ test('modify config in `createReadStream` handler', async t => {
t.deepEqual(output, header.value);
});

test('automatically handle ETag headers for normal files', async t => {
const name = 'object.json';
const related = path.join(fixturesFull, name);
const content = await fs.readJSON(related);
const value = 'd2ijdjoi29f3h3232';

const url = await getUrl({
headers: [{
source: '**',
headers: [{
key: 'ETag',
value
}]
}]
});

const response = await fetch(`${url}/${name}`);
const {headers} = response;

const type = headers.get('content-type');
const eTag = headers.get('etag');

t.is(type, 'application/json; charset=utf-8');
t.is(eTag, value);

const text = await response.text();
const spec = JSON.parse(text);

t.deepEqual(spec, content);

const cacheResponse = await fetch(`${url}/${name}`, {
headers: {
'if-none-match': value
}
});

t.is(cacheResponse.status, 304);
});

0 comments on commit d7e026b

Please sign in to comment.