Skip to content

Commit

Permalink
Merge pull request #1634 from WebFreak001/master
Browse files Browse the repository at this point in the history
fix #716 (Add partial content with range)
  • Loading branch information
s-ludwig authored Nov 27, 2016
2 parents dbfb12c + 85e6ea1 commit 6805267
Showing 1 changed file with 48 additions and 5 deletions.
53 changes: 48 additions & 5 deletions http/vibe/http/fileserver.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import std.conv;
import std.datetime;
import std.digest.md;
import std.string;
import std.algorithm;


/**
Expand Down Expand Up @@ -311,7 +312,43 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse
if ("Content-Encoding" in res.headers && isCompressedFormat(mimetype))
res.headers.remove("Content-Encoding");
res.headers["Content-Type"] = mimetype;
res.headers["Content-Length"] = to!string(dirent.size);
res.headers.addField("Accept-Ranges", "bytes");
ulong rangeStart = 0;
ulong rangeEnd = 0;
auto prange = "Range" in req.headers;

if (prange) {
auto range = (*prange).chompPrefix("bytes=");
if (range.canFind(','))
throw new HTTPStatusException(HTTPStatus.notImplemented);
auto s = range.split("-");
// https://tools.ietf.org/html/rfc7233
// Range can be in form "-\d", "\d-" or "\d-\d"
if (s[0].length) {
rangeStart = s[0].to!ulong;
rangeEnd = s[1].length ? s[1].to!ulong : dirent.size;
} else if (s[1].length) {
rangeEnd = dirent.size;
auto len = s[1].to!ulong;
if (len >= rangeEnd)
rangeStart = 0;
else
rangeStart = rangeEnd - len;
} else {
throw new HTTPStatusException(HTTPStatus.badRequest);
}
if (rangeEnd > dirent.size)
rangeEnd = dirent.size;
if (rangeStart > rangeEnd)
rangeStart = rangeEnd;
if (rangeEnd)
rangeEnd--; // End is inclusive, so one less than length
// potential integer overflow with rangeEnd - rangeStart == size_t.max is intended. This only happens with empty files, the + 1 will then put it back to 0
res.headers["Content-Length"] = to!string(rangeEnd - rangeStart + 1);
res.headers["Content-Range"] = "bytes %s-%s/%s".format(rangeStart < rangeEnd ? rangeStart : rangeEnd, rangeEnd, dirent.size);
res.statusCode = HTTPStatus.partialContent;
} else
res.headers["Content-Length"] = dirent.size.to!string;

// check for already encoded file if configured
string encodedFilepath;
Expand Down Expand Up @@ -366,8 +403,14 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse
}
scope(exit) fil.close();

if (pce && !encodedFilepath.length)
res.bodyWriter.write(fil);
else res.writeRawBody(fil);
logTrace("sent file %d, %s!", fil.size, res.headers["Content-Type"]);
if (prange) {
fil.seek(rangeStart);
res.bodyWriter.write(fil, rangeEnd - rangeStart + 1);
logTrace("partially sent file %d-%d, %s!", rangeStart, rangeEnd, res.headers["Content-Type"]);
} else {
if (pce && !encodedFilepath.length)
res.bodyWriter.write(fil);
else res.writeRawBody(fil);
logTrace("sent file %d, %s!", fil.size, res.headers["Content-Type"]);
}
}

0 comments on commit 6805267

Please sign in to comment.