aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-03-13 14:40:15 +0100
committerEelco Dolstra <edolstra@gmail.com>2017-03-15 16:49:06 +0100
commite8186085e07104d4b844208613c2d704b5b57dec (patch)
treecce5074dd45b109c0edd5427fa06c4f8ec668bbe /src
parent73d7a51ee6942f681db468dc8e3c631b4d3daa4e (diff)
Add support for brotli compression
Build logs on cache.nixos.org are compressed using Brotli (since this allows them to be decompressed automatically by Chrome and Firefox), so it's handy if "nix log" can decompress them.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/download.cc21
-rw-r--r--src/libutil/compression.cc7
-rw-r--r--src/libutil/local.mk2
3 files changed, 28 insertions, 2 deletions
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index 6567a4dc4..d9b8fbc08 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -5,6 +5,8 @@
#include "store-api.hh"
#include "archive.hh"
#include "s3.hh"
+#include "compression.hh"
+
#ifdef ENABLE_S3
#include <aws/core/client/ClientConfiguration.h>
#endif
@@ -70,6 +72,8 @@ struct CurlDownloader : public Downloader
struct curl_slist * requestHeaders = 0;
+ std::string encoding;
+
DownloadItem(CurlDownloader & downloader, const DownloadRequest & request)
: downloader(downloader), request(request)
{
@@ -127,6 +131,7 @@ struct CurlDownloader : public Downloader
auto ss = tokenizeString<vector<string>>(line, " ");
status = ss.size() >= 2 ? ss[1] : "";
result.data = std::make_shared<std::string>();
+ encoding = "";
} else {
auto i = line.find(':');
if (i != string::npos) {
@@ -142,7 +147,8 @@ struct CurlDownloader : public Downloader
debug(format("shutting down on 200 HTTP response with expected ETag"));
return 0;
}
- }
+ } else if (name == "content-encoding")
+ encoding = trim(string(line, i + 1));;
}
}
return realSize;
@@ -268,7 +274,18 @@ struct CurlDownloader : public Downloader
{
result.cached = httpStatus == 304;
done = true;
- callSuccess(success, failure, const_cast<const DownloadResult &>(result));
+
+ /* Ad hoc support for brotli, since curl doesn't do
+ this yet. */
+ try {
+ if (encoding == "br")
+ result.data = decompress("br", *result.data);
+
+ callSuccess(success, failure, const_cast<const DownloadResult &>(result));
+ } catch (...) {
+ done = true;
+ callFailure(failure, std::current_exception());
+ }
} else {
Error err =
(httpStatus == 404 || code == CURLE_FILE_COULDNT_READ_FILE) ? NotFound :
diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc
index a3bbb5170..723b072af 100644
--- a/src/libutil/compression.cc
+++ b/src/libutil/compression.cc
@@ -89,6 +89,11 @@ static ref<std::string> decompressBzip2(const std::string & in)
}
}
+static ref<std::string> decompressBrotli(const std::string & in)
+{
+ return make_ref<std::string>(runProgram(BRO, true, {"-d"}, in));
+}
+
ref<std::string> compress(const std::string & method, const std::string & in)
{
StringSink ssink;
@@ -106,6 +111,8 @@ ref<std::string> decompress(const std::string & method, const std::string & in)
return decompressXZ(in);
else if (method == "bzip2")
return decompressBzip2(in);
+ else if (method == "br")
+ return decompressBrotli(in);
else
throw UnknownCompressionMethod(format("unknown compression method ā€˜%sā€™") % method);
}
diff --git a/src/libutil/local.mk b/src/libutil/local.mk
index cac5c8795..0721b21c2 100644
--- a/src/libutil/local.mk
+++ b/src/libutil/local.mk
@@ -9,3 +9,5 @@ libutil_SOURCES := $(wildcard $(d)/*.cc)
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS)
libutil_LIBS = libformat
+
+libutil_CXXFLAGS = -DBRO=\"$(bro)\"