Skip to content

Commit 2413f11

Browse files
chore: add apache rewriter for webp and avif
1 parent f6eaf25 commit 2413f11

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

src/class-tiny-apache-rewrite.php

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?php
2+
/*
3+
* Tiny Compress Images - WordPress plugin.
4+
* Copyright (C) 2015-2018 Tinify B.V.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by the Free
8+
* Software Foundation; either version 2 of the License, or (at your option)
9+
* any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14+
* more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along
17+
* with this program; if not, write to the Free Software Foundation, Inc., 51
18+
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n*/
19+
20+
class Tiny_Apache_Rewrite extends Tiny_WP_Base
21+
{
22+
23+
const MARKER = 'tinify_modern_images';
24+
25+
/**
26+
* Generate .htaccess rewrite rules for serving WebP and AVIF images.
27+
*
28+
* @return string The .htaccess rules
29+
*/
30+
public static function get_rewrite_rules()
31+
{
32+
$rules = array(
33+
'<IfModule mod_rewrite.c>',
34+
'RewriteEngine On',
35+
'RewriteOptions Inherit',
36+
);
37+
38+
$rules = array_merge($rules, self::get_avif_rules());
39+
$rules = array_merge($rules, self::get_webp_rules());
40+
41+
$rules[] = '</IfModule>';
42+
43+
$rules[] = '<IfModule mod_headers.c>';
44+
$rules[] = 'Header append Vary Accept';
45+
$rules[] = '<FilesMatch "\\.(webp|avif)$">';
46+
$rules[] = 'Header set Cache-Control "max-age=31536000, public"';
47+
$rules[] = '</FilesMatch>';
48+
$rules[] = '</IfModule>';
49+
50+
$rules[] = '<IfModule mod_mime.c>';
51+
$rules[] = 'AddType image/webp .webp';
52+
$rules[] = 'AddType image/avif .avif';
53+
$rules[] = '</IfModule>';
54+
55+
return implode("\n", $rules);
56+
}
57+
58+
/**
59+
* Generate AVIF rewrite rules.
60+
*
61+
* @return array[] AVIF rewrite rules
62+
*/
63+
private static function get_avif_rules()
64+
{
65+
$rules = array();
66+
67+
// AVIF rule 1: Try file with original extension appended (image.jpg.avif)
68+
$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/avif';
69+
$rules[] = 'RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.avif -f';
70+
$rules[] = 'RewriteRule ^(.+)$ $1.avif [T=image/avif,L]';
71+
72+
// AVIF rule 2: Try file with extension replaced (image.avif)
73+
$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/avif';
74+
$rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\\.(?:jpe?g|png|gif)$';
75+
$rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.avif -f';
76+
$rules[] = 'RewriteRule (.+)\\.(?:jpe?g|png|gif)$ $1.avif [T=image/avif,L]';
77+
78+
return $rules;
79+
}
80+
81+
/**
82+
* Generate WebP rewrite rules.
83+
*
84+
* @return array[] WebP rewrite rules
85+
*/
86+
private static function get_webp_rules()
87+
{
88+
$rules = array();
89+
90+
// WebP rule 1: Try file with original extension appended (image.jpg.webp)
91+
// Check for Chrome browser or explicit Accept header
92+
$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/webp [OR]';
93+
$rules[] = 'RewriteCond %{HTTP_USER_AGENT} Chrome';
94+
$rules[] = 'RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.webp -f';
95+
$rules[] = 'RewriteRule ^(.+)$ $1.webp [T=image/webp,L]';
96+
97+
// WebP rule 2: Try file with extension replaced (image.webp)
98+
$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/webp [OR]';
99+
$rules[] = 'RewriteCond %{HTTP_USER_AGENT} Chrome';
100+
$rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\\.(?:jpe?g|png|gif)$';
101+
$rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.webp -f';
102+
$rules[] = 'RewriteRule (.+)\\.(?:jpe?g|png|gif)$ $1.webp [T=image/webp,L]';
103+
104+
return $rules;
105+
}
106+
107+
/**
108+
* Install rewrite rules to .htaccess files.
109+
*
110+
* @return bool True on success, false otherwise
111+
*/
112+
public static function install()
113+
{
114+
if (! function_exists('insert_with_markers')) {
115+
require_once ABSPATH . 'wp-admin/includes/misc.php';
116+
}
117+
118+
$rules = self::get_rewrite_rules();
119+
120+
// Write to uploads directory
121+
$upload_dir = wp_upload_dir();
122+
if (isset($upload_dir['basedir']) && is_writable($upload_dir['basedir'])) {
123+
$htaccess_file = $upload_dir['basedir'] . '/.htaccess';
124+
insert_with_markers($htaccess_file, self::MARKER, $rules);
125+
}
126+
127+
// Write to root directory
128+
if (is_writable(get_home_path())) {
129+
$htaccess_file = get_home_path() . '.htaccess';
130+
insert_with_markers($htaccess_file, self::MARKER, $rules);
131+
}
132+
133+
return true;
134+
}
135+
136+
/**
137+
* Remove rewrite rules from .htaccess files.
138+
*
139+
* @return bool True on success, false otherwise
140+
*/
141+
public static function uninstall()
142+
{
143+
if (! function_exists('insert_with_markers')) {
144+
require_once ABSPATH . 'wp-admin/includes/misc.php';
145+
}
146+
147+
// Remove from uploads directory
148+
$upload_dir = wp_upload_dir();
149+
if (isset($upload_dir['basedir']) && file_exists($upload_dir['basedir'] . '/.htaccess')) {
150+
$htaccess_file = $upload_dir['basedir'] . '/.htaccess';
151+
insert_with_markers($htaccess_file, self::MARKER, '');
152+
}
153+
154+
// Remove from root directory
155+
if (file_exists(get_home_path() . '.htaccess')) {
156+
$htaccess_file = get_home_path() . '.htaccess';
157+
insert_with_markers($htaccess_file, self::MARKER, '');
158+
}
159+
160+
return true;
161+
}
162+
}

0 commit comments

Comments
 (0)