Skip to content
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
Closed

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

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

Comments

@s-ludwig
Copy link
Member

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/[email protected]

@UplinkCoder
Copy link
Contributor

That would really be a useful addition

@yebblies
Copy link

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
Copy link
Member Author

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

@etcimon
Copy link
Contributor

etcimon commented May 23, 2016

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

s-ludwig added a commit that referenced this issue Nov 27, 2016
fix #716 (Add partial content with range)
s-ludwig added a commit that referenced this issue Dec 19, 2016
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
Projects
None yet
Development

No branches or pull requests

4 participants