Skip to content

Commit

Permalink
[BREAKING] dub.sdl: Move Zlib dependency to subpackage
Browse files Browse the repository at this point in the history
When building with Dub, ae will now build without Zlib support by
default.

Rationale:

- Though Zlib is used by Phobos, the D standard library, some D
  compilers (at least, specifically, LDC on Debian) may not pull in a
  libz.so dependency automatically.  However, because ae uses Zlib, it
  used to declare a library dependency (`libs "z" platform="posix"`)
  in its dub.sdl.

  This was problematic because it caused *all* programs which used ae
  to need to link to Zlib, even when they never used any Zlib features
  or even imported any modules which directly or indirectly used Zlib
  or Phobos modules which use Zlib.

Changes required:

- If your program uses Zlib features of ae, add a dependency to
  ae:zlib to your dub.sdl/.json file.

- Note that you may want to do so also if you use ae.net.http or
  ae.sys.net.ae, as otherwise ae's HTTP implementation will be built
  without Zlib support and will not attempt to negotiate or be able to
  decompress deflate or gzip content-encoding.
  • Loading branch information
CyberShadow committed Jun 20, 2023
1 parent edc1ddc commit 543fc15
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 30 deletions.
27 changes: 22 additions & 5 deletions dub.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ excludedSourceFiles "sys/net/system.d"
excludedSourceFiles "sys/net/wininet.d"
excludedSourceFiles "sys/net/test.d"

# In ae:zlib
excludedSourceFiles "utils/gzip.d"
excludedSourceFiles "utils/zlib.d"

# Triggers on import
excludedSourceFiles "sys/benchmark.d"

Expand All @@ -62,11 +66,24 @@ excludedSourceFiles "utils/container/package.d"
excludedSourceFiles "utils/serialization/*.d"
excludedSourceFiles "utils/xmldom.d"

# libz (zlib) is a dependency on Phobos, and normally shouldn't be
# explicitly specified as required, however in some setups (such as
# LDC on Debian) it is not pulled in automatically for whatever
# reason.
libs "z" platform="posix"

---------------------------

subPackage {
name "zlib"
targetType "sourceLibrary"

# libz (zlib) is a dependency on Phobos, and normally shouldn't be
# explicitly specified as required, however in some setups (such as
# LDC on Debian) it is not pulled in automatically for whatever
# reason.
libs "z" platform="posix"

dependency "ae" version="*" path="."
sourceFiles \
"utils/gzip.d" \
"utils/zlib.d"
}

---------------------------

Expand Down
3 changes: 2 additions & 1 deletion makejson.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ packages=(
# These don't have any special *compile-time* dependencies.
# (We're not going to try to link the output.)
ae
ae:zlib
ae:sqlite
)

Expand All @@ -22,7 +23,7 @@ done
mapfile -t files < files.txt
rm files.txt describe.json

dmd -o- -dw -Xfae.json "${files[@]}"
dmd -o- -dw -I.. -Xfae.json "${files[@]}"

(
echo "deprecated module ae.all;"
Expand Down
21 changes: 16 additions & 5 deletions net/http/caching.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ import ae.sys.dataset : DataVec, bytes;
import ae.utils.mime;
import ae.utils.time.common;
import ae.utils.time.parse;
import ae.utils.zlib;
import ae.utils.gzip;
private alias zlib = ae.utils.zlib;
static if (haveZlib)
{
import ae.utils.zlib;
import ae.utils.gzip;
private alias zlib = ae.utils.zlib;
}

/// Controls which caching headers are sent to clients.
enum CachePolicy
Expand Down Expand Up @@ -82,7 +85,9 @@ protected: // interface with descendant classes
/// (overhead is negligible).
final void invalidate()
{
uncompressedDataCache = deflateDataCache = gzipDataCache = null;
uncompressedDataCache = null;
static if (haveZlib)
deflateDataCache = gzipDataCache = null;
lastModified = getLastModified();
}

Expand All @@ -92,7 +97,9 @@ protected: // interface with descendant classes
}

private:
DataVec uncompressedDataCache, deflateDataCache, gzipDataCache;
DataVec uncompressedDataCache;
static if (haveZlib)
DataVec deflateDataCache, gzipDataCache;
SysTime lastModified;

@property final ref DataVec uncompressedData()
Expand All @@ -102,13 +109,15 @@ private:
return uncompressedDataCache;
}

static if (haveZlib)
@property final ref DataVec deflateData()
{
if (!deflateDataCache)
deflateDataCache = zlib.compress(uncompressedData[], zlib.ZlibOptions(compressionLevel));
return deflateDataCache;
}

static if (haveZlib)
@property final ref DataVec gzipData()
{
// deflate2gzip doesn't actually make a copy of the compressed data (thanks to DataVec).
Expand All @@ -124,12 +133,14 @@ private:
final class Response : HttpResponse
{
protected:
static if (haveZlib)
override void compressWithDeflate()
{
assert(data is uncompressedData);
data = deflateData.dup;
}

static if (haveZlib)
override void compressWithGzip()
{
assert(data is uncompressedData);
Expand Down
7 changes: 6 additions & 1 deletion net/http/client.d
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,12 @@ public:
if ("User-Agent" !in request.headers && agent)
request.headers["User-Agent"] = agent;
if ("Accept-Encoding" !in request.headers)
request.headers["Accept-Encoding"] = "gzip, deflate, identity;q=0.5, *;q=0";
{
static if (haveZlib)
request.headers["Accept-Encoding"] = "gzip, deflate, identity;q=0.5, *;q=0";
else
request.headers["Accept-Encoding"] = "identity;q=0.5, *;q=0";
}
if (request.data)
request.headers["Content-Length"] = to!string(request.data.bytes.length);
if ("Connection" !in request.headers)
Expand Down
68 changes: 50 additions & 18 deletions net/http/common.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,28 @@ import ae.sys.dataset;
import ae.utils.array : amap, afilter, auniq, asort;
import ae.utils.text;
import ae.utils.time;
import zlib = ae.utils.zlib;
import gzip = ae.utils.gzip;

version (ae_with_zlib) // Explicit override
enum haveZlib = true;
else
version (ae_without_zlib) // Explicit override
enum haveZlib = false;
else
version (Have_ae) // Building with Dub
{
version (Have_ae_zlib) // Using ae:zlib
enum haveZlib = true;
else
enum haveZlib = false;
}
else // Not building with Dub
enum haveZlib = true; // Pull in zlib by default

static if (haveZlib)
{
import zlib = ae.utils.zlib;
import gzip = ae.utils.gzip;
}

/// Base HTTP message class
private abstract class HttpMessage
Expand Down Expand Up @@ -512,21 +532,30 @@ public:
Data getContent()
{
if ("Content-Encoding" in headers && headers["Content-Encoding"]=="deflate")
return zlib.uncompress(data[]).joinData();
else
{
static if (haveZlib)
return zlib.uncompress(data[]).joinData();
else
throw new Exception("Built without zlib - can't decompress \"Content-Encoding: deflate\" content");
}
if ("Content-Encoding" in headers && headers["Content-Encoding"]=="gzip")
return gzip.uncompress(data[]).joinData();
else
return data.joinData();
assert(0);
{
static if (haveZlib)
return gzip.uncompress(data[]).joinData();
else
throw new Exception("Built without zlib - can't decompress \"Content-Encoding: gzip\" content");
}
return data.joinData();
}

static if (haveZlib)
protected void compressWithDeflate()
{
assert(compressionLevel >= 0);
data = zlib.compress(data[], zlib.ZlibOptions(compressionLevel));
}

static if (haveZlib)
protected void compressWithGzip()
{
assert(compressionLevel >= 0);
Expand All @@ -551,16 +580,19 @@ public:
foreach (method; supported)
switch (method)
{
case "deflate":
headers["Content-Encoding"] = method;
headers.add("Vary", "Accept-Encoding");
compressWithDeflate();
return;
case "gzip":
headers["Content-Encoding"] = method;
headers.add("Vary", "Accept-Encoding");
compressWithGzip();
return;
static if (haveZlib)
{
case "deflate":
headers["Content-Encoding"] = method;
headers.add("Vary", "Accept-Encoding");
compressWithDeflate();
return;
case "gzip":
headers["Content-Encoding"] = method;
headers.add("Vary", "Accept-Encoding");
compressWithGzip();
return;
}
case "*":
if("Content-Encoding" in headers)
headers.remove("Content-Encoding");
Expand Down

0 comments on commit 543fc15

Please sign in to comment.