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();