diff --git a/README.md b/README.md
index ac93633..c690c33 100644
--- a/README.md
+++ b/README.md
@@ -88,11 +88,24 @@ zstd.output\_compression\_dict | "" | PHP\_INI\_ALL
* zstd.output\_compression\_exclude\_types _string_
- Comma-separated list of MIME types to exclude from transparent output
- compression, e.g. `"image/*,application/pdf"`. Both exact types
- (`application/pdf`) and wildcard subtypes (`image/*`) are supported.
- The comparison ignores any parameters (such as `charset`) present in
- the response's `Content-Type` header.
+ Extension contains a built-in list of non-compressible MIME types.
+ The list can be found from phpinfo() output. If something is
+ missing, more MIME types can be added with this ini setting.
+
+ Comma-separated list of MIME types that should not be
+ compressed by the transparent output handler.
+
+ Supports exact MIME type matches and wildcard family matches.
+ A wildcard entry must use the `type/*` form.
+
+ Example (both of these are already in the built-in list):
+
+ ```ini
+ zstd.output_compression_exclude_types="video/*,application/pdf"
+ ```
+
+ This is useful for already-compressed binary formats where
+ additional Zstd compression usually provides little benefit.
* zstd.output\_compression\_dict _string_
diff --git a/package.xml b/package.xml
index 3eb2cfc..4fc5f39 100644
--- a/package.xml
+++ b/package.xml
@@ -32,6 +32,7 @@
+
diff --git a/php_zstd_mimetype_exclude.h b/php_zstd_mimetype_exclude.h
new file mode 100644
index 0000000..1c88189
--- /dev/null
+++ b/php_zstd_mimetype_exclude.h
@@ -0,0 +1,37 @@
+#ifndef ZSTD_MIMETYPE_EXCLUDE
+
+/**
+ * Image types listed separately, because svg is quite common
+ * and compresses well.
+ *
+ * Less common types have both, x-prefixed and non-prefixed
+ * versions because they are somewhat inconsistent with each
+ * other and perhaps more likely to be misconfigured due to
+ * those inconsistencies.
+ **/
+#define ZSTD_MIMETYPE_EXCLUDE "\
+video/*, \
+audio/*, \
+image/png, \
+image/gif, \
+image/jpeg, \
+image/jxl, \
+image/jp2, \
+image/jpm, \
+image/webp, \
+image/avif, \
+image/x-icon, image/vnd.microsoft.icon, \
+font/woff, application/font-woff, application/x-font-woff, \
+font/woff2, \
+application/pdf, application/x-pdf, \
+application/zip, application/x-zip, application/zip-compressed, application/x-zip-compressed, \
+application/7z-compressed, application/x-7z-compressed, \
+application/vnd.rar, application/x-vnd.rar, \
+application/gzip, application/x-gzip, \
+application/zstd, application/x-zstd, \
+application/br, application/x-br, \
+application/lz4, application/x-lz4, \
+application/bzip2, application/x-bzip2\
+"
+
+#endif
diff --git a/tests/info.phpt b/tests/info.phpt
index 735ffa4..678e8da 100644
--- a/tests/info.phpt
+++ b/tests/info.phpt
@@ -66,12 +66,38 @@ if (count($lines) >= 4) {
echo ($lines[3] == 'APCu serializer support => not built') ? "Apcu OK\n" : "Fail: not built\n";
}
- /**
- * TODO: test built-in header exclusion list
- **/
+ if (PHP_VERSION_ID >= 80000) {
+ $search = 'Built-in output compression exclusions => ';
+ $mimeIndex = null;
+ // could be 4 or 5 depending on apcu
+ foreach([4, 5] as $index) {
+ if (isset($lines[$index]) && substr($lines[$index], 0, 42) == $search) {
+ $mimeIndex = $index;
+ }
+ }
+ if ($mimeIndex) {
+ $types = explode(', ', substr($lines[$mimeIndex], 42));
+ $invalidTypes = [];
+ foreach($types as $type) {
+ if (!preg_match('/^([a-z]+)\/(([a-z0-9\-\.]+)|\*)$/', $type)) {
+ $invalidTypes[] = $type;
+ }
+ }
+ if ($invalidTypes) {
+ echo "Fail: " . implode(", ", $invalidTypes) . "\n";
+ } else {
+ echo "MIMEs OK\n";
+ }
+ } else {
+ echo "Fail\n";
+ }
+ } else {
+ echo "MIMEs OK\n";
+ }
}
--EXPECTF--
Ext version OK
Bundled/external zstd OK
Zstd version OK
Apcu OK
+MIMEs OK
diff --git a/tests/ob_exclude_001.phpt b/tests/ob_exclude_001.phpt
index c38e5fd..1ef421d 100644
--- a/tests/ob_exclude_001.phpt
+++ b/tests/ob_exclude_001.phpt
@@ -6,7 +6,6 @@ include (dirname(__FILE__) . '/ob_skipif.inc');
?>
--INI--
zstd.output_compression=1
-zstd.output_compression_exclude_types=application/pdf
--ENV--
HTTP_ACCEPT_ENCODING=zstd
--GET--
diff --git a/tests/ob_exclude_002.phpt b/tests/ob_exclude_002.phpt
index 8a1a36b..806ded2 100644
--- a/tests/ob_exclude_002.phpt
+++ b/tests/ob_exclude_002.phpt
@@ -13,7 +13,7 @@ HTTP_ACCEPT_ENCODING=zstd
ob=021
--FILE--
--EXPECT--
diff --git a/zstd.c b/zstd.c
index 0f01f05..4386faa 100644
--- a/zstd.c
+++ b/zstd.c
@@ -41,6 +41,9 @@
#include
#include
#include "php_zstd.h"
+#if PHP_VERSION_ID >= 80000
+#include "php_zstd_mimetype_exclude.h"
+#endif
# pragma GCC diagnostic ignored "-Wunicode"
@@ -1293,10 +1296,9 @@ static int php_zstd_output_encoding(void)
return PHP_ZSTD_G(compression_coding);
}
-static int php_zstd_output_mimetype_excluded(void)
+static int php_zstd_output_mimetype_excluded(const char *exclude)
{
const char *mimetype = SG(sapi_headers).mimetype;
- const char *exclude = PHP_ZSTD_G(output_compression_exclude_types);
const char *p, *end;
size_t mimetype_len;
@@ -1556,7 +1558,11 @@ php_zstd_output_handler(void **handler_context,
php_zstd_context *ctx = *(php_zstd_context **) handler_context;
if ((output_context->op & PHP_OUTPUT_HANDLER_START)
- && php_zstd_output_mimetype_excluded()) {
+ && (
+ php_zstd_output_mimetype_excluded(ZSTD_MIMETYPE_EXCLUDE)
+ ||
+ php_zstd_output_mimetype_excluded(PHP_ZSTD_G(output_compression_exclude_types))
+ )) {
return FAILURE;
}
@@ -1964,6 +1970,9 @@ ZEND_MINFO_FUNCTION(zstd)
php_info_print_table_row(2, "APCu serializer interface version", APC_SERIALIZER_ABI);
#else
php_info_print_table_row(2, "APCu serializer support", "not built");
+#endif
+#if PHP_VERSION_ID >= 80000
+ php_info_print_table_row(2, "Built-in output compression exclusions", ZSTD_MIMETYPE_EXCLUDE);
#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();