Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

headers, conditional range requests, tests

  • Loading branch information...
commit 468fcfe3d24337c74c0017f954c64a8d8f73785d 1 parent 99089b6
@ryanrolds ryanrolds authored tj committed
Showing with 43 additions and 22 deletions.
  1. +22 −19 lib/middleware/static.js
  2. +21 −3 test/static.test.js
View
41 lib/middleware/static.js
@@ -155,7 +155,27 @@ var send = exports.send = function(req, res, next, options){
return;
}
+ // header fields
+ if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
+ if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
+ if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
+ if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
+ if (!res.getHeader('content-type')) {
+ var charset = mime.charsets.lookup(type);
+ res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+ }
+ res.setHeader('Accept-Ranges', 'bytes');
+
+ // conditional GET support
+ if (utils.conditionalGET(req)) {
+ if (!utils.modified(req, res)) {
+ req.emit('static', null);
+ return utils.notModified(res);
+ }
+ }
+
var opts = {};
+ var chunkSize = stat.size;
// we have a Range request
if (ranges) {
@@ -166,6 +186,7 @@ var send = exports.send = function(req, res, next, options){
// TODO: multiple support
opts.start = ranges[0].start;
opts.end = ranges[0].end;
+ chunkSize = opts.end - opts.start + 1;
res.statusCode = 206;
res.setHeader('Content-Range', 'bytes '
+ opts.start
@@ -179,27 +200,9 @@ var send = exports.send = function(req, res, next, options){
? fn(new Error('Requested Range Not Satisfiable'))
: invalidRange(res);
}
- // stream the entire file
- } else {
- res.setHeader('Content-Length', stat.size);
- if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
- if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
- if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
-
- // conditional GET support
- if (utils.conditionalGET(req)) {
- if (!utils.modified(req, res)) {
- return utils.notModified(res);
- }
- }
}
- // header fields
- if (!res.getHeader('content-type')) {
- var charset = mime.charsets.lookup(type);
- res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
- }
- res.setHeader('Accept-Ranges', 'bytes');
+ res.setHeader('Content-Length', chunkSize);
// transfer
if (head) return res.end();
View
24 test/static.test.js
@@ -136,13 +136,31 @@ module.exports = {
'test Range': function(){
assert.response(app,
{ url: '/list', headers: { Range: 'bytes=0-4' }},
- { body: '12345', status: 206 });
+ { body: '12345', 'Content-Range': 'bytes 0-4/9', status: 206 });
},
'test Range 2': function(){
assert.response(app,
- { url: '/list', headers: { Range: 'bytes=5-9' }},
- { body: '6789', status: 206 });
+ { url: '/list', headers: { Range: 'bytes=5-8' }},
+ { body: '6789', 'Content-Range': 'bytes 5-8/9', status: 206 });
+ },
+
+ 'test Range 3': function(){
+ assert.response(app,
+ { url: '/list', headers: { Range: 'bytes=3-6' }},
+ { body: '4567', 'Content-Range': 'bytes 3-6/9', status: 206 });
+ },
+
+ 'test conditional range': function(){
+ assert.response(app,
+ { url: '/list' },
+ function(res) {
+ res.headers.should.have.property('etag');
+ assert.response(app,
+ { url: '/list', headers: { Range: 'bytes=3-6', 'If-None-Match': res.headers.etag }},
+ { status: 304 }
+ );
+ });
},
'test invalid Range': function(){
Please sign in to comment.
Something went wrong with that request. Please try again.