New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support range based HTTP queries for the HTTP file server #716

Closed
s-ludwig opened this Issue Jul 10, 2014 · 4 comments

Comments

Projects
None yet
4 participants
@s-ludwig
Member

s-ludwig commented Jul 10, 2014

To support resuming of downloads and fix certain issues on some browsers, the Accept-Ranges and related headers should be supported by the HTTP file server module.

See also http://forum.dlang.org/post/vrshdjypnvxkurufqmut@forum.dlang.org

@UplinkCoder

This comment has been minimized.

Show comment
Hide comment
@UplinkCoder

UplinkCoder Jul 11, 2014

Contributor

That would really be a useful addition

Contributor

UplinkCoder commented Jul 11, 2014

That would really be a useful addition

@yebblies

This comment has been minimized.

Show comment
Hide comment
@yebblies

yebblies May 20, 2016

diff --git a/source/vibe/http/fileserver.d b/source/vibe/http/fileserver.d
index e3c4f48..71b45a8 100644
--- a/source/vibe/http/fileserver.d
+++ b/source/vibe/http/fileserver.d
@@ -13,6 +13,7 @@ import vibe.http.server;
 import vibe.inet.message;
 import vibe.inet.mimetypes;
 import vibe.inet.url;
+import vibe.stream.counting;

 import std.conv;
 import std.datetime;
@@ -311,7 +312,23 @@ 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;
+    if (auto prange = "Range" in req.headers)
+    {
+        auto range = (*prange).chompPrefix("bytes=");
+        auto s = range.split("-");
+        rangeStart = s[0].to!ulong();
+        rangeEnd = s[1].length ? s[1].to!ulong() : dirent.size;
+        res.headers["Content-Length"] = to!string(rangeEnd - rangeStart + 1);
+        res.headers["Content-Range"] = "bytes %s-%s/%s".format(rangeStart, rangeEnd, dirent.size);
+    }
+    else
+    {
+        res.headers["Content-Length"] = to!string(dirent.size);
+    }

    // check for already encoded file if configured
    string encodedFilepath;
@@ -366,6 +383,13 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse
    }
    scope(exit) fil.close();

+    if ("Range" in req.headers)
+    {
+        fil.seek(rangeStart);
+        res.bodyWriter.write(new LimitedInputStream(fil, rangeEnd - rangeStart + 1));
+        return;
+    }
+
    if (pce && !encodedFilepath.length)
        res.bodyWriter.write(fil);
    else res.writeRawBody(fil);

yebblies commented May 20, 2016

diff --git a/source/vibe/http/fileserver.d b/source/vibe/http/fileserver.d
index e3c4f48..71b45a8 100644
--- a/source/vibe/http/fileserver.d
+++ b/source/vibe/http/fileserver.d
@@ -13,6 +13,7 @@ import vibe.http.server;
 import vibe.inet.message;
 import vibe.inet.mimetypes;
 import vibe.inet.url;
+import vibe.stream.counting;

 import std.conv;
 import std.datetime;
@@ -311,7 +312,23 @@ 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;
+    if (auto prange = "Range" in req.headers)
+    {
+        auto range = (*prange).chompPrefix("bytes=");
+        auto s = range.split("-");
+        rangeStart = s[0].to!ulong();
+        rangeEnd = s[1].length ? s[1].to!ulong() : dirent.size;
+        res.headers["Content-Length"] = to!string(rangeEnd - rangeStart + 1);
+        res.headers["Content-Range"] = "bytes %s-%s/%s".format(rangeStart, rangeEnd, dirent.size);
+    }
+    else
+    {
+        res.headers["Content-Length"] = to!string(dirent.size);
+    }

    // check for already encoded file if configured
    string encodedFilepath;
@@ -366,6 +383,13 @@ private void sendFileImpl(scope HTTPServerRequest req, scope HTTPServerResponse
    }
    scope(exit) fil.close();

+    if ("Range" in req.headers)
+    {
+        fil.seek(rangeStart);
+        res.bodyWriter.write(new LimitedInputStream(fil, rangeEnd - rangeStart + 1));
+        return;
+    }
+
    if (pce && !encodedFilepath.length)
        res.bodyWriter.write(fil);
    else res.writeRawBody(fil);
@s-ludwig

This comment has been minimized.

Show comment
Hide comment
@s-ludwig

s-ludwig May 21, 2016

Member

Thanks, Daniel! I'll add some code to detect multi-ranges and integrate this on master.

Member

s-ludwig commented May 21, 2016

Thanks, Daniel! I'll add some code to detect multi-ranges and integrate this on master.

@etcimon

This comment has been minimized.

Show comment
Hide comment
@etcimon

etcimon May 23, 2016

Contributor

status code should be 206 and response should use writeRawBody if there's an encoding

Contributor

etcimon commented May 23, 2016

status code should be 206 and response should use writeRawBody if there's an encoding

@s-ludwig s-ludwig closed this in 745ee0f Nov 27, 2016

s-ludwig added a commit that referenced this issue Nov 27, 2016

Merge pull request #1634 from WebFreak001/master
fix #716 (Add partial content with range)

s-ludwig added a commit that referenced this issue Dec 19, 2016

Merge pull request #1634 from WebFreak001/master
fix #716 (Add partial content with range)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment