Version Description
(released: 5 Nov 2020) * Bugfix: WebP Express uses live tests to determine the capabilities of the server in respect to .htaccess files (using the htaccess-capability-tester library). The results are used for warnings and also for optimizing the rules in the .htaccess files. However, HTTP Requests can fail due to other reasons than the feature not working (ie timeout). Such failures should lead to an indeterminate result, but it was interpreted as if the feature was not working. * The Live test now displays a bit more information if the HTTP request failed. * Changed default value for "destination structure" to "Image roots", as "Document root" doesn't work on hosts that have defined DOCUMENT_ROOT in an unusual way. * Added possibility to change "%{DOCUMENT_ROOT}" part of RewriteCond by adding a line to wp-config.php. THIS IS A BETA FEATURE AND MIGHT BE REVOKED IF NOBODY ACTUALLY NEEDS IT. * Got rid of PHP notice Constant WEBPEXPRESS_MIGRATION_VERSION already defined * Fixed donation link. It now points to https://ko-fi.com/rosell again
For more info, see the closed issues on the 0.18.3 milestone on the github repository
Release Info
Developer | rosell.dk |
Plugin | WebP Express |
Version | 0.18.3 |
Comparing to | |
See all releases |
Code changes from version 0.18.2 to 0.18.3
- README.md +10 -193
- README.txt +26 -8
- changelog.txt +11 -0
- composer.json +1 -1
- composer.lock +6 -6
- lib/classes/AdminInit.php +6 -2
- lib/classes/Config.php +1 -1
- lib/classes/ConvertHelperIndependent.php +1 -1
- lib/classes/HTAccess.php +11 -0
- lib/classes/HTAccessCapabilityTestRunner.php +3 -0
- lib/classes/HTAccessRules.php +12 -5
- lib/classes/SelfTestHelper.php +4 -1
- lib/classes/SelfTestRedirectToExisting.php +7 -2
- lib/classes/WPHttpRequester.php +1 -1
- lib/options/options/general/destination-structure.inc +9 -5
- vendor/composer/installed.json +6 -6
- vendor/rosell-dk/htaccess-capability-tester/.github/FUNDING.yml +1 -1
- vendor/rosell-dk/htaccess-capability-tester/README.md +16 -99
- vendor/rosell-dk/htaccess-capability-tester/docs/Running your own custom tests.md +85 -0
- vendor/rosell-dk/htaccess-capability-tester/src/HttpRequesterInterface.php +3 -1
- vendor/rosell-dk/htaccess-capability-tester/src/HttpResponse.php +0 -1
- vendor/rosell-dk/htaccess-capability-tester/src/SimpleHttpRequester.php +5 -3
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/CrashTester.php +2 -2
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/CustomTester.php +2 -0
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/Helpers/ResponseInterpreter.php +0 -1
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/HtaccessEnabledTester.php +4 -4
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/InnocentRequestTester.php +1 -0
- vendor/rosell-dk/htaccess-capability-tester/src/Testers/ModuleLoadedTester.php +1 -1
- vendor/rosell-dk/htaccess-capability-tester/tests/FakeServer.php +11 -0
- vendor/rosell-dk/htaccess-capability-tester/tests/Testers/ContentDigestTesterTest.php +8 -0
- vendor/rosell-dk/htaccess-capability-tester/tests/Testers/CrashTesterTest.php +8 -0
- vendor/rosell-dk/htaccess-capability-tester/tests/Testers/HtaccessEnabledTesterTest.php +8 -0
- vendor/rosell-dk/htaccess-capability-tester/tests/Testers/ModuleLoadedTesterTest.php +8 -0
- webp-express.php +1 -1
@@ -92,7 +92,7 @@ If you do not have quality detection working, you can try one of the following:
|
|
92 |
### Verifying that it works (in "Varied image responses" mode)
|
93 |
1. Make sure at least one of the conversion methods are working. It should have a green checkmark next to it.
|
94 |
2. If you haven't saved yet, click "Save settings". This will put redirection rules into .htaccess files in the relevant directories (typically in uploads, themes and wp-content/webp-express/webp-images, depending on the "Scope" setting)
|
95 |
-
3. I assume that you checked at least one of the checkboxes in the .htaccess rules section
|
96 |
4. Click the "Live test" buttons to see that the enabled rules actually are working. If they are not, it *could* be that the server needs a little time to recognize the changed rules.
|
97 |
|
98 |
The live tests are quite thorough and I recommend them over a manual test. However, it doesn't hurt to do a manual inspection too.
|
@@ -677,199 +677,16 @@ Here are my current plans ahead: 0.18 will probably be a file manager-like inter
|
|
677 |
|
678 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
679 |
|
680 |
-
## Changes in 0.18.
|
681 |
-
*(released:
|
682 |
-
* Bugfix:
|
|
|
|
|
|
|
|
|
|
|
683 |
|
684 |
-
|
685 |
-
*(released: 24 Sep 2020)*
|
686 |
-
* You can now set cache control header in CDN friendly mode too
|
687 |
-
* The code for testing what actually works in .htaccess files on the server setup has been moved to a new library: [htaccess-capability-tester](https://github.com/rosell-dk/htaccess-capability-tester). It has been strengthened in the process.
|
688 |
-
* Improved diagnosing in the "Live test" buttons
|
689 |
-
* Simplified the logic for adding "Vary header" in the .htaccess residing in the cache dir. The logic no longer depends on the Apache module "mod_envif" being installed. mod_envif has Apache "Base" status, which means it is very rarely missing, so I decided not to trigger automatically updating of the .htaccess rules. To apply the change, you must click the button that forces .htaccess regeneration
|
690 |
-
* The plugin has a folder called "wod" which contains php scripts for converting an image to webp. This is used for the function that rely on redirect magic to trigger conversion ("Enable redirection to converter?" and "Create webp files upon request?"). The .htaccess file in the "wod" folder in the plugin dir contains directives for modifying access (in order to counterfight rules placed by security plugins for disallows scripts to be run directly). However if these directives has been disallowed in the server setup, any request to a file in the folder will result in a 500 internal server error. To circumvent this, a "wod2" folder has been added, which contains the same scripts, but without the .htaccess. Upon saving, WebP Express now automatically checks which one works, and points to that in the .htaccess rules.
|
691 |
-
* Bugfix: webp mime type was not registred in .htaccess in "CDN friendly" mode. This is a minor fix so I decided not to update the .htaccess automatically. To apply it, you must click the button that forces .htaccess regeneration.
|
692 |
-
* Bugfix: Bulk convert failed to load the list when there were filenames containing non-unicode characters
|
693 |
-
* Added a new way to support me. I'm on [GitHub Sponsors](https://github.com/sponsors/rosell-dk)!
|
694 |
-
|
695 |
-
For more info, see the closed issues on the 0.18.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/33?closed=1
|
696 |
-
|
697 |
-
|
698 |
-
## Changes in 0.17.5
|
699 |
-
*(released: 11 Aug 2020)*
|
700 |
-
|
701 |
-
* Fixed "Path is outside resolved document root" in a certain symlinked configuration. Thanks to @spiderPan for providing the fix.
|
702 |
-
* Added content filtering hooks for several third party plugins including ACF and WooCommerce Product Images. With this change, the "Use content filtering hooks" in Alter HTML works in more scenarios, which means there are fewer scenarios where you have to resort to the slower "The complete page" option. Thanks to alextuan for providing the contribution
|
703 |
-
* Fixed problems with Alter HTML when migrating: Absolute paths were cached in the database and the cache was only updated upon saving settings. The paths are not cached anymore (recalculating these on each page load is not a performance problem)
|
704 |
-
|
705 |
-
For more info, see the closed issues on the 0.17.5 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/30?closed=1
|
706 |
-
|
707 |
-
## Changes in 0.17.4
|
708 |
-
*(released: 26 Jun 2020)*
|
709 |
-
|
710 |
-
* Fixed bug: Configuration was repeatedly resetting for some users
|
711 |
-
* Fixed "Path is outside resolved document root" on file conversion attempts in Windows. Thanks to @Ruzgfpegk from Japan for providing the fix.
|
712 |
-
* Fix errors not caught in the selftest. Thanks to Benji Bilheimer from Germany providing the fix.
|
713 |
-
* Fix errors not caught in the selftest with unverified certificates. Thanks to Rikesh Ramlochund from Mauritius for providing the fix.
|
714 |
-
* Fixed errors with filenames containing encoded symbols. Thanks to Eddie Zhou from Canada for the fix.
|
715 |
-
|
716 |
-
For more info, see the closed issues on the 0.17.4 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/32?closed=1
|
717 |
-
|
718 |
-
## Changes in 0.17.3
|
719 |
-
*(released: 3 Feb 2020)*
|
720 |
-
|
721 |
-
* Fixed critical bug: Fatal error after updating plugin (if one had been postponing updating WebP Express for a while and then updated Wordpress and THEN updated WebP Express)
|
722 |
-
* A critical bug was fixed in the webp-convert library (PHP 7.4 related)
|
723 |
-
* A critical bug was fixed in dom-util-for-webp library (PHP 7.4 related)
|
724 |
-
* Alter HTML now processes the "poster" attribute in Video tags. Thanks to @MikhailRoot from Russia for the PR on github.
|
725 |
-
* On some Litespeed hosts, WebP Express reported that mod_headers was not available even though it was. Thanks to @lubieowoce from Poland for the PR on github)
|
726 |
-
|
727 |
-
For more info, see the closed issues on the 0.17.3 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/31?closed=1
|
728 |
-
|
729 |
-
## Changes in 0.17.2
|
730 |
-
*(released: 5 Oct 2019)*
|
731 |
-
|
732 |
-
* Fixed bug: Updating plugin failed on some systems (in the unzip phase). Problem was introduced in 0.17.0 with the updated binaries.
|
733 |
-
* Fixed bug: Alter HTML used the protocol (http/https) for the site for generated links (rather than keeping the protocol for the link). Thanks to Jacob Gullberg from Sweden for discovering this bug.
|
734 |
-
|
735 |
-
If you experienced update problems due to the update bug, you will probably be left with an incomplete installation. Some of the plugin files are there, but not all. Especially, the main plugin file (webp-express.php) is missing, which means that Wordpress don't "see" the plugin (it is missing from the list). Trying to install WebP Express again will probably not work, because the "webp-express" folder is already there. You will then have to remove the "webp-express" folder in "plugins" manually (via ftp or a plugin, such as File Manager).
|
736 |
-
|
737 |
-
For more info, see the closed issues on the 0.17.2 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/29?closed=1
|
738 |
-
|
739 |
-
## Changes in 0.17.1
|
740 |
-
*(released: 3 Oct 2019)*
|
741 |
-
|
742 |
-
- Fixed NGINX rules in FAQ (added xdestination for the create webp upon request functionality)
|
743 |
-
- Fixed issue with Alter HTML. Thanks to @jonathanernst for discovering issue and supplying the patch.
|
744 |
-
- WebP Express now works on WP Engine. Check out the new "I am on WP Engine" section in the FAQ
|
745 |
-
- Miscellaneous bug fixes
|
746 |
-
|
747 |
-
For more info, see the closed issues on the 0.17.1 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/27?closed=1
|
748 |
-
|
749 |
-
## Changes in 0.17.0
|
750 |
-
*(released: 27 sep 2019)*
|
751 |
-
|
752 |
-
* Cwebp conversion method runs on more systems (not subject to open_basedir restrictions and also tries "pure" cwebp command). Thanks to cng11 for reaching out so I spotted this.
|
753 |
-
* Ewww conversion method no longer does a remote api-key check for each conversion - so it is faster. If an ewww conversions fails due to a non-functional key, the key will not be tried again (until next time the options are saved)
|
754 |
-
* Updated cwebp binaries to version 1.0.3
|
755 |
-
|
756 |
-
## Changes in 0.16.0
|
757 |
-
*(released: 24 sep 2019)*
|
758 |
-
|
759 |
-
- Added option to specify CDN urls in Alter HTML. Thanks to Gunnar Peipman from Estonia for suggesting this.
|
760 |
-
- Direct Nginx users to Nginx FAQ section on welcome page
|
761 |
-
- Fixed Bulk Conversion halting due to nonce expiry
|
762 |
-
- Fixed unexpected output upon reactivation
|
763 |
-
- Added affiliate link to [Optimole](https://optimole.pxf.io/20b0M) in the "Don't despair - You have options!" message
|
764 |
-
|
765 |
-
## Changes in 0.15.3
|
766 |
-
*(released: 19 sep 2019)*
|
767 |
-
|
768 |
-
* Fixed fatal error upon activation for systems which cannot use document root for structuring (rare)
|
769 |
-
|
770 |
-
## Changes in 0.15.2
|
771 |
-
|
772 |
-
* Fixed the bug when File extension was set to "Set to .webp". It was buggy when file extension contained uppercase letters.
|
773 |
-
|
774 |
-
## Changes in 0.15.1
|
775 |
-
*(released: 17 sep 2019)*
|
776 |
-
|
777 |
-
- Bug alert: Added alert about a bug when destination folder is set to "mingled" and File extension is set to "Set to .webp"
|
778 |
-
- Bugfix: Plugin URL pointed to webpexpress - it should point to parent. This gave trouble with images located in plugins. Thanks to Guillaume Meyer from Switzerland for discovering and reporting.
|
779 |
-
- Bugfix: Images with uppercase chars in extension did not get Vary:Accept
|
780 |
-
- Bugfix: There were issues with "All content" and destination:document-root when webp-realizer is activated
|
781 |
-
|
782 |
-
|
783 |
-
## Changes in 0.15.0
|
784 |
-
*(released: 17 sep 2019)*
|
785 |
-
|
786 |
-
- Provided test-buttons for checking if the redirects works.
|
787 |
-
- You can now choose which folders WebP Express is active in. Ie "Uploads and Themes".
|
788 |
-
- You can now choose an alternative file structure for the webps which does not rely on DOCUMENT_ROOT being available.
|
789 |
-
- WebP Express can now handle when wp-content is symlinked.
|
790 |
-
- The .htaccess rules are now divided across folders. Some rules are needed where the source files are located, some where the webp files are located.
|
791 |
-
- Added option to convert only PNG files
|
792 |
-
- And a couple of bugfixes.
|
793 |
-
|
794 |
-
## Changes in 0.14.12 - 0.14.15
|
795 |
-
- Fixed errors with "redirect to conversion script" on systems with symlinked folders
|
796 |
-
- Fixed errors with "redirect to conversion script" on systems where the filename cannot be passed through an environment variable
|
797 |
-
|
798 |
-
## Changes in 0.14.5 - 0.14.11
|
799 |
-
The following security fixes has been applied in 0.14.0 - 0.14.11:
|
800 |
-
It is urged that you upgrade all of you WebP Express installations!
|
801 |
-
|
802 |
-
- Security fix: Closed a security hole that could be used to view the content of any file on the server (provided that the full path is known or guessed). This is a very serious flaw, which unfortunately has been around for quite a while.
|
803 |
-
- Security fix: Added capability checks to options page.
|
804 |
-
- Security fix: Sanitized user input.
|
805 |
-
- Security fix: Added checks for file paths and directories.
|
806 |
-
- Security fix: Nonces and capability checks for AJAX calls.
|
807 |
-
|
808 |
-
## Changes in 0.14.4
|
809 |
-
- Now bundles with multiple cwebp binaries for linux for systems where 1.0.2 fails.
|
810 |
-
|
811 |
-
## Changes in 0.14.3
|
812 |
-
- Fixed filename of supplied cwebp for linux (bug was introduced in 0.14.2)
|
813 |
-
|
814 |
-
## Changes in 0.14.2
|
815 |
-
- Fixed problem with older versions of cwebp
|
816 |
-
- Fixed that images was not deleted
|
817 |
-
- Fixed cache problem on options page on systems that disables cache busting (it resulted in "SyntaxError: JSON.parse")
|
818 |
-
|
819 |
-
## Changes in 0.14.1
|
820 |
-
- A little something
|
821 |
-
|
822 |
-
## Changes in 0.14.0
|
823 |
-
- Security fix: Closed a security hole that could be used to view the content of any file on the server (provided that the full path is known or guessed). This is a very serious flaw, which has been around for quite a while. I urge you to upgrade to 0.14.0.
|
824 |
-
- Added new "encoding" option, which can be set to auto. This can in some cases dramatically reduce the size of the webp. It is supported by all converters except ewww and gd.
|
825 |
-
- Added new "near-lossless" option (only for cwebp and vips). Using this is a good idea for reducing size of lossless webps with an acceptable loss of quality
|
826 |
-
- Added new "alpha-quality" option (all converters, except ewww and gd). Using this is a good idea when images with transparency are converted to lossy webp - it has the potential to reduce the size up to 50% (depending on the source material) while keeping an acceptable level of quality
|
827 |
-
- Added new conversion methods: Vips and GraphicsMagick
|
828 |
-
- Imagick conversion method now supports webp options (finally cracked it!)
|
829 |
-
- Using MimeType detection instead of relying on file extensions
|
830 |
-
- In "test" converter you now change options and also test PNG files
|
831 |
-
- Added conversion logs
|
832 |
-
- PNGs are now enabled by default (with the new conversion features especially PNGs are compressed much better)
|
833 |
-
|
834 |
-
For more info, see the closed issues on the 0.14.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/9?closed=1
|
835 |
-
|
836 |
-
## Changes in 0.13.2
|
837 |
-
- Fixed Fatal error on image upload in combination with the [Enable Media Replace](https://de.wordpress.org/plugins/enable-media-replace/) plugin. Thanks to Alexander Graef from Germany for reporting.
|
838 |
-
- It seems we finally nailed the blank settings page bug. Thanks to all involved, especially Richard Spenceley from the UK
|
839 |
-
|
840 |
-
## Changes in 0.13.1
|
841 |
-
- Fixed several bugs.
|
842 |
-
|
843 |
-
## Changes in 0.13.0
|
844 |
-
- Bulk Conversion
|
845 |
-
- Fixed problems with Gd converter and PNG
|
846 |
-
- Optinally auto convert upon media upload
|
847 |
-
- Windows fix (thanks, lwxbr!)
|
848 |
-
|
849 |
-
## Changes in 0.12.0
|
850 |
-
- Multisite support (!)
|
851 |
-
- A new operation mode: "No conversion", if you do not want to use WebP Express for converting. Replaces the old "Just redirect" mode
|
852 |
-
- Added capability testing of .htaccess. The .htaccess rules are now tailored to the capabilities on the system. For example, on some platforms the filename of a requested image is passed to the converter script through the query string, but on platforms that supports passing it through an environment variable, that method is used instead
|
853 |
-
- Picturefill.js is now optional (alter html, picture tag)
|
854 |
-
- A great bunch more!
|
855 |
-
|
856 |
-
For more info, see the closed issues on the 0.12.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/12?closed=1
|
857 |
-
|
858 |
-
## Changes in 0.11.0
|
859 |
-
- Alter HTML to point to webp files (choose between picture tags or simply altering all image urls)
|
860 |
-
- Convert non-existing webp-files upon request (means you can reference the converted webp files before they are actually converted!)
|
861 |
-
|
862 |
-
## Changes in 0.10.0
|
863 |
-
- Introduced "Operation modes" in order to keep setting screens simple but still allow tweaking
|
864 |
-
- WebP Express can now be used in conjunction with Cache Enabler and ShortPixel
|
865 |
-
- Cache-Control header is now added in *.htaccess*, when redirecting directly to existing webp
|
866 |
-
|
867 |
-
## Changes in 0.9.0
|
868 |
-
- Optionally make .htaccess redirect directly to existing webp (improves performance)
|
869 |
-
- Optionally do not send filename from .htaccess to the PHP in Querystring, but use other means (improves security and reduces risks of problems due to firewall rules)
|
870 |
-
- Fixed some bugs
|
871 |
-
|
872 |
-
For more info, see the closed issues on the 0.9.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.9.0
|
873 |
|
874 |
## Supporting WebP Express
|
875 |
Bread on the table don't come for free, even though this plugin does, and always will. I enjoy developing this, and supporting you guys, but I kind of need the bread too. Please make it possible for me to continue putting effort into this plugin:
|
92 |
### Verifying that it works (in "Varied image responses" mode)
|
93 |
1. Make sure at least one of the conversion methods are working. It should have a green checkmark next to it.
|
94 |
2. If you haven't saved yet, click "Save settings". This will put redirection rules into .htaccess files in the relevant directories (typically in uploads, themes and wp-content/webp-express/webp-images, depending on the "Scope" setting)
|
95 |
+
3. I assume that you checked at least one of the two first checkboxes in the .htaccess rules section. Otherwise you aren't using "varied responses", and then the "CDN friendly" mode will be more appropriate.
|
96 |
4. Click the "Live test" buttons to see that the enabled rules actually are working. If they are not, it *could* be that the server needs a little time to recognize the changed rules.
|
97 |
|
98 |
The live tests are quite thorough and I recommend them over a manual test. However, it doesn't hurt to do a manual inspection too.
|
677 |
|
678 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
679 |
|
680 |
+
## Changes in 0.18.3
|
681 |
+
*(released: 5 Nov 2020)*
|
682 |
+
* Bugfix: WebP Express uses live tests to determine the capabilities of the server in respect to .htaccess files (using the htaccess-capability-tester library). The results are used for warnings and also for optimizing the rules in the .htaccess files. However, HTTP Requests can fail due to other reasons than the feature not working (ie timeout). Such failures should lead to an indeterminate result, but it was interpreted as if the feature was not working.
|
683 |
+
* The Live test now displays a bit more information if the HTTP request failed.
|
684 |
+
* Changed default value for "destination structure" to "Image roots", as "Document root" doesn't work on hosts that have defined DOCUMENT_ROOT in an unusual way.
|
685 |
+
* Added possibility to change "%{DOCUMENT_ROOT}" part of RewriteCond by adding a line to wp-config.php. THIS IS A BETA FEATURE AND MIGHT BE REVOKED IF NOBODY ACTUALLY NEEDS IT.
|
686 |
+
* Got rid of PHP notice Constant WEBPEXPRESS_MIGRATION_VERSION already defined
|
687 |
+
* Fixed donation link. It now points to https://ko-fi.com/rosell again
|
688 |
|
689 |
+
For more info, see the closed issues on the 0.18.3 milestone on the github repository: https://github.com/rosell-dk/webp-express/milestone/34?closed=1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
690 |
|
691 |
## Supporting WebP Express
|
692 |
Bread on the table don't come for free, even though this plugin does, and always will. I enjoy developing this, and supporting you guys, but I kind of need the bread too. Please make it possible for me to continue putting effort into this plugin:
|
@@ -1,10 +1,10 @@
|
|
1 |
=== WebP Express ===
|
2 |
Contributors: rosell.dk
|
3 |
-
Donate link: https://
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.5
|
7 |
-
Stable tag: 0.18.
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
@@ -91,7 +91,7 @@ If you do not have quality detection working, you can try one of the following:
|
|
91 |
### Verifying that it works (in "Varied image responses" mode)
|
92 |
1. Make sure at least one of the conversion methods are working. It should have a green checkmark next to it.
|
93 |
2. If you haven't saved yet, click "Save settings". This will put redirection rules into .htaccess files in the relevant directories (typically in uploads, themes and wp-content/webp-express/webp-images, depending on the "Scope" setting)
|
94 |
-
3. I assume that you checked at least one of the checkboxes in the .htaccess rules section
|
95 |
4. Click the "Live test" buttons to see that the enabled rules actually are working. If they are not, it *could* be that the server needs a little time to recognize the changed rules.
|
96 |
|
97 |
The live tests are quite thorough and I recommend them over a manual test. However, it doesn't hurt to do a manual inspection too.
|
@@ -136,18 +136,18 @@ Bread on the table don't come for free, even though this plugin does, and always
|
|
136 |
* [Mathieu Gollain-Dupont](https://www.linkedin.com/in/mathieu-gollain-dupont-9938a4a/)
|
137 |
* Ruben Solvang
|
138 |
|
139 |
-
**Persons who contributed with
|
140 |
|
141 |
-
*
|
142 |
-
*
|
143 |
-
*
|
144 |
|
145 |
**Persons who contributed with extra generously amounts of coffee / lifetime backing (>30$) - thanks!:**
|
146 |
|
147 |
* Justin - BigScoots ($105)
|
148 |
* Sebastian ($99)
|
149 |
* Tammy Lee ($90)
|
150 |
-
* Max Kreminsky ($
|
151 |
* Steven Sullivan ($51)
|
152 |
|
153 |
== Frequently Asked Questions ==
|
@@ -733,6 +733,21 @@ If you want to make sure that my coffee supplies don't run dry, you can even buy
|
|
733 |
|
734 |
== Changelog ==
|
735 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
736 |
= 0.18.1 =
|
737 |
*(released: 24 Sep 2020)*
|
738 |
* Bugfix: Bulk Convert failed to show list on systems that did not have the [utf8-encode()](https://www.php.net/manual/en/function.utf8-encode.php) function.
|
@@ -1180,6 +1195,9 @@ For older releases, check out changelog.txt
|
|
1180 |
|
1181 |
== Upgrade Notice ==
|
1182 |
|
|
|
|
|
|
|
1183 |
= 0.18.2 =
|
1184 |
* Fixed bug on settings page
|
1185 |
|
1 |
=== WebP Express ===
|
2 |
Contributors: rosell.dk
|
3 |
+
Donate link: https://ko-fi.com/rosell
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.5
|
7 |
+
Stable tag: 0.18.3
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
91 |
### Verifying that it works (in "Varied image responses" mode)
|
92 |
1. Make sure at least one of the conversion methods are working. It should have a green checkmark next to it.
|
93 |
2. If you haven't saved yet, click "Save settings". This will put redirection rules into .htaccess files in the relevant directories (typically in uploads, themes and wp-content/webp-express/webp-images, depending on the "Scope" setting)
|
94 |
+
3. I assume that you checked at least one of the two first checkboxes in the .htaccess rules section. Otherwise you aren't using "varied responses", and then the "CDN friendly" mode will be more appropriate.
|
95 |
4. Click the "Live test" buttons to see that the enabled rules actually are working. If they are not, it *could* be that the server needs a little time to recognize the changed rules.
|
96 |
|
97 |
The live tests are quite thorough and I recommend them over a manual test. However, it doesn't hurt to do a manual inspection too.
|
136 |
* [Mathieu Gollain-Dupont](https://www.linkedin.com/in/mathieu-gollain-dupont-9938a4a/)
|
137 |
* Ruben Solvang
|
138 |
|
139 |
+
**Persons who contributed with ko-fi within the last 30 days (updated biweekly) - Thanks! **
|
140 |
|
141 |
+
* Mark from Portland, OR
|
142 |
+
* Pradeep Maheepala from Watford, UK
|
143 |
+
* jean
|
144 |
|
145 |
**Persons who contributed with extra generously amounts of coffee / lifetime backing (>30$) - thanks!:**
|
146 |
|
147 |
* Justin - BigScoots ($105)
|
148 |
* Sebastian ($99)
|
149 |
* Tammy Lee ($90)
|
150 |
+
* Max Kreminsky ($80)
|
151 |
* Steven Sullivan ($51)
|
152 |
|
153 |
== Frequently Asked Questions ==
|
733 |
|
734 |
== Changelog ==
|
735 |
|
736 |
+
= 0.18.3 =
|
737 |
+
*(released: 5 Nov 2020)*
|
738 |
+
* Bugfix: WebP Express uses live tests to determine the capabilities of the server in respect to .htaccess files (using the htaccess-capability-tester library). The results are used for warnings and also for optimizing the rules in the .htaccess files. However, HTTP Requests can fail due to other reasons than the feature not working (ie timeout). Such failures should lead to an indeterminate result, but it was interpreted as if the feature was not working.
|
739 |
+
* The Live test now displays a bit more information if the HTTP request failed.
|
740 |
+
* Changed default value for "destination structure" to "Image roots", as "Document root" doesn't work on hosts that have defined DOCUMENT_ROOT in an unusual way.
|
741 |
+
* Added possibility to change "%{DOCUMENT_ROOT}" part of RewriteCond by adding a line to wp-config.php. THIS IS A BETA FEATURE AND MIGHT BE REVOKED IF NOBODY ACTUALLY NEEDS IT.
|
742 |
+
* Got rid of PHP notice Constant WEBPEXPRESS_MIGRATION_VERSION already defined
|
743 |
+
* Fixed donation link. It now points to https://ko-fi.com/rosell again
|
744 |
+
|
745 |
+
For more info, see the closed issues on the [0.18.3 milestone on the github repository](https://github.com/rosell-dk/webp-express/milestone/34?closed=1)
|
746 |
+
|
747 |
+
= 0.18.2 =
|
748 |
+
*(released: 28 Sep 2020)*
|
749 |
+
* Bugfix: Fixed error on the settings page on a handful of setups.
|
750 |
+
|
751 |
= 0.18.1 =
|
752 |
*(released: 24 Sep 2020)*
|
753 |
* Bugfix: Bulk Convert failed to show list on systems that did not have the [utf8-encode()](https://www.php.net/manual/en/function.utf8-encode.php) function.
|
1195 |
|
1196 |
== Upgrade Notice ==
|
1197 |
|
1198 |
+
= 0.18.3 =
|
1199 |
+
* Minor fixes (see changelog)
|
1200 |
+
|
1201 |
= 0.18.2 =
|
1202 |
* Fixed bug on settings page
|
1203 |
|
@@ -1,3 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 0.18.2 =
|
2 |
*(released: 28 Sep 2020)*
|
3 |
* Bugfix: Fixed error on the settings page on a handful of setups.
|
1 |
+
= 0.18.3 =
|
2 |
+
*(released: 5 Nov 2020)*
|
3 |
+
* Bugfix: WebP Express uses live tests to determine the capabilities of the server in respect to .htaccess files (using the htaccess-capability-tester library). The results are used for warnings and also for optimizing the rules in the .htaccess files. However, HTTP Requests can fail due to other reasons than the feature not working (ie timeout). Such failures should lead to an indeterminate result, but it was interpreted as if the feature was not working.
|
4 |
+
* The Live test now displays a bit more information if the HTTP request failed.
|
5 |
+
* Changed default value for "destination structure" to "Image roots", as "Document root" doesn't work on hosts that have defined DOCUMENT_ROOT in an unusual way.
|
6 |
+
* Added possibility to change "%{DOCUMENT_ROOT}" part of RewriteCond by adding a line to wp-config.php. THIS IS A BETA FEATURE AND MIGHT BE REVOKED IF NOBODY ACTUALLY NEEDS IT.
|
7 |
+
* Got rid of PHP notice Constant WEBPEXPRESS_MIGRATION_VERSION already defined
|
8 |
+
* Fixed donation link. It now points to https://ko-fi.com/rosell again
|
9 |
+
|
10 |
+
For more info, see the closed issues on the [0.18.3 milestone on the github repository](https://github.com/rosell-dk/webp-express/milestone/34?closed=1)
|
11 |
+
|
12 |
= 0.18.2 =
|
13 |
*(released: 28 Sep 2020)*
|
14 |
* Bugfix: Fixed error on the settings page on a handful of setups.
|
@@ -8,7 +8,7 @@
|
|
8 |
"rosell-dk/webp-convert": "^2.3.1",
|
9 |
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
|
10 |
"rosell-dk/dom-util-for-webp": "^0.4.0",
|
11 |
-
"rosell-dk/htaccess-capability-tester": "^0.
|
12 |
},
|
13 |
"require-dev": {
|
14 |
},
|
8 |
"rosell-dk/webp-convert": "^2.3.1",
|
9 |
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
|
10 |
"rosell-dk/dom-util-for-webp": "^0.4.0",
|
11 |
+
"rosell-dk/htaccess-capability-tester": "^0.9.0"
|
12 |
},
|
13 |
"require-dev": {
|
14 |
},
|
@@ -4,7 +4,7 @@
|
|
4 |
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
5 |
"This file is @generated automatically"
|
6 |
],
|
7 |
-
"content-hash": "
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "composer/installers",
|
@@ -193,16 +193,16 @@
|
|
193 |
},
|
194 |
{
|
195 |
"name": "rosell-dk/htaccess-capability-tester",
|
196 |
-
"version": "0.
|
197 |
"source": {
|
198 |
"type": "git",
|
199 |
"url": "https://github.com/rosell-dk/htaccess-capability-tester.git",
|
200 |
-
"reference": "
|
201 |
},
|
202 |
"dist": {
|
203 |
"type": "zip",
|
204 |
-
"url": "https://api.github.com/repos/rosell-dk/htaccess-capability-tester/zipball/
|
205 |
-
"reference": "
|
206 |
"shasum": ""
|
207 |
},
|
208 |
"require": {
|
@@ -249,7 +249,7 @@
|
|
249 |
"apache",
|
250 |
"litespeed"
|
251 |
],
|
252 |
-
"time": "2020-
|
253 |
},
|
254 |
{
|
255 |
"name": "rosell-dk/image-mime-type-guesser",
|
4 |
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
5 |
"This file is @generated automatically"
|
6 |
],
|
7 |
+
"content-hash": "0a5dd30cdf271eb73acaef9d3c0519b2",
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "composer/installers",
|
193 |
},
|
194 |
{
|
195 |
"name": "rosell-dk/htaccess-capability-tester",
|
196 |
+
"version": "0.9",
|
197 |
"source": {
|
198 |
"type": "git",
|
199 |
"url": "https://github.com/rosell-dk/htaccess-capability-tester.git",
|
200 |
+
"reference": "2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c"
|
201 |
},
|
202 |
"dist": {
|
203 |
"type": "zip",
|
204 |
+
"url": "https://api.github.com/repos/rosell-dk/htaccess-capability-tester/zipball/2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c",
|
205 |
+
"reference": "2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c",
|
206 |
"shasum": ""
|
207 |
},
|
208 |
"require": {
|
249 |
"apache",
|
250 |
"litespeed"
|
251 |
],
|
252 |
+
"time": "2020-11-04T10:29:38+00:00"
|
253 |
},
|
254 |
{
|
255 |
"name": "rosell-dk/image-mime-type-guesser",
|
@@ -29,8 +29,12 @@ class AdminInit
|
|
29 |
|
30 |
public static function runMigrationIfNeeded()
|
31 |
{
|
32 |
-
//
|
33 |
-
|
|
|
|
|
|
|
|
|
34 |
|
35 |
if (WEBPEXPRESS_MIGRATION_VERSION != Option::getOption('webp-express-migration-version', 0)) {
|
36 |
// run migration logic
|
29 |
|
30 |
public static function runMigrationIfNeeded()
|
31 |
{
|
32 |
+
// For reasons I have not been able to unravel, someone reported a notice that WEBPEXPRESS_MIGRATION_VERSION was already defined.
|
33 |
+
// So we added this "defined" check. #463
|
34 |
+
if (!defined('WEBPEXPRESS_MIGRATION_VERSION')) {
|
35 |
+
// When an update requires a migration, the number should be increased
|
36 |
+
define('WEBPEXPRESS_MIGRATION_VERSION', '12');
|
37 |
+
}
|
38 |
|
39 |
if (WEBPEXPRESS_MIGRATION_VERSION != Option::getOption('webp-express-migration-version', 0)) {
|
40 |
// run migration logic
|
@@ -30,7 +30,7 @@ class Config
|
|
30 |
'image-types' => 3,
|
31 |
'destination-folder' => 'separate',
|
32 |
'destination-extension' => 'append',
|
33 |
-
'destination-structure' => (
|
34 |
'cache-control' => 'no-header', /* can be "no-header", "set" or "custom" */
|
35 |
'cache-control-custom' => 'public, max-age=31536000, stale-while-revalidate=604800, stale-if-error=604800',
|
36 |
'cache-control-max-age' => 'one-week',
|
30 |
'image-types' => 3,
|
31 |
'destination-folder' => 'separate',
|
32 |
'destination-extension' => 'append',
|
33 |
+
'destination-structure' => (PlatformInfo::isNginx() ? 'doc-root' : 'image-roots'),
|
34 |
'cache-control' => 'no-header', /* can be "no-header", "set" or "custom" */
|
35 |
'cache-control-custom' => 'public, max-age=31536000, stale-while-revalidate=604800, stale-if-error=604800',
|
36 |
'cache-control-max-age' => 'one-week',
|
@@ -571,7 +571,7 @@ APACHE
|
|
571 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
572 |
|
573 |
// TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
|
574 |
-
$text = 'WebP Express 0.18.
|
575 |
|
576 |
$logFile = self::getLogFilename($source, $logDir);
|
577 |
|
571 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
572 |
|
573 |
// TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
|
574 |
+
$text = 'WebP Express 0.18.3. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
|
575 |
|
576 |
$logFile = self::getLogFilename($source, $logDir);
|
577 |
|
@@ -11,6 +11,14 @@ use \WebPExpress\State;
|
|
11 |
class HTAccess
|
12 |
{
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
/**
|
16 |
* Must be parsed ie "wp-content", "index", etc. Not real dirs
|
@@ -160,6 +168,9 @@ class HTAccess
|
|
160 |
|
161 |
// Convert to array, because string version has bugs in Wordpress 4.3
|
162 |
$rules = explode("\n", $rules);
|
|
|
|
|
|
|
163 |
$success = insert_with_markers($filename, 'WebP Express', $rules);
|
164 |
|
165 |
// Revert file or dir permissions
|
11 |
class HTAccess
|
12 |
{
|
13 |
|
14 |
+
public static function inlineInstructions($instructions, $marker)
|
15 |
+
{
|
16 |
+
if ($marker == 'WebP Express') {
|
17 |
+
return [];
|
18 |
+
} else {
|
19 |
+
return $instructions;
|
20 |
+
}
|
21 |
+
}
|
22 |
|
23 |
/**
|
24 |
* Must be parsed ie "wp-content", "index", etc. Not real dirs
|
168 |
|
169 |
// Convert to array, because string version has bugs in Wordpress 4.3
|
170 |
$rules = explode("\n", $rules);
|
171 |
+
|
172 |
+
add_filter('insert_with_markers_inline_instructions', array('\WebPExpress\HTAccess', 'inlineInstructions'), 10, 2);
|
173 |
+
|
174 |
$success = insert_with_markers($filename, 'WebP Express', $rules);
|
175 |
|
176 |
// Revert file or dir permissions
|
@@ -27,6 +27,9 @@ class HTAccessCapabilityTestRunner
|
|
27 |
{
|
28 |
$response = wp_remote_get($url, ['timeout' => 10]);
|
29 |
//echo '<pre>' . print_r($response, true) . '</pre>';
|
|
|
|
|
|
|
30 |
if (wp_remote_retrieve_response_code($response) != '200') {
|
31 |
return false;
|
32 |
}
|
27 |
{
|
28 |
$response = wp_remote_get($url, ['timeout' => 10]);
|
29 |
//echo '<pre>' . print_r($response, true) . '</pre>';
|
30 |
+
if (is_wp_error($response)) {
|
31 |
+
return null;
|
32 |
+
}
|
33 |
if (wp_remote_retrieve_response_code($response) != '200') {
|
34 |
return false;
|
35 |
}
|
@@ -27,6 +27,7 @@ class HTAccessRules
|
|
27 |
private static $dirContainsSourceImages;
|
28 |
private static $dirContainsWebPImages;
|
29 |
private static $alterHtmlEnabled;
|
|
|
30 |
|
31 |
private static function trueFalseNullString($var)
|
32 |
{
|
@@ -166,7 +167,9 @@ class HTAccessRules
|
|
166 |
private static function infoRules()
|
167 |
{
|
168 |
|
169 |
-
return "# The rules below
|
|
|
|
|
170 |
"#\n# WebP Express options:\n" .
|
171 |
"# - Operation mode: " . self::$config['operation-mode'] . "\n" .
|
172 |
"# - Redirection to existing webp: " .
|
@@ -301,18 +304,18 @@ class HTAccessRules
|
|
301 |
if (self::$useDocRootForStructuringCacheDir) {
|
302 |
if (self::$config['destination-extension'] == 'append') {
|
303 |
$rules .= " RewriteCond %{REQUEST_FILENAME}.webp -f\n";
|
304 |
-
//$rules .= " RewriteCond
|
305 |
$rules .= " RewriteRule ^/?(.*)\.(" . self::$fileExt . ")$ $1.$2.webp [NC,T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
306 |
} else {
|
307 |
// extension: set to webp
|
308 |
|
309 |
-
//$rules .= " RewriteCond
|
310 |
//$rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . self::$fileExt . ")$ $1.webp [T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
311 |
|
312 |
// Got these new rules here: https://www.digitalocean.com/community/tutorials/how-to-create-and-serve-webp-images-to-speed-up-your-website
|
313 |
// (but are they actually better than the ones we use for append?)
|
314 |
$rules .= " RewriteCond %{REQUEST_URI} (?i)(.*)(" . self::$fileExtIncludingDot . ")$\n";
|
315 |
-
$rules .= " RewriteCond %
|
316 |
$rules .= " RewriteRule (?i)(.*)(" . self::$fileExtIncludingDot . ")$ %1\.webp [T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
317 |
|
318 |
// Instead of using REQUEST_URI, I can use REQUEST_FILENAME and remove DOCUMENT_ROOT
|
@@ -352,7 +355,7 @@ class HTAccessRules
|
|
352 |
$cacheDirRel = Paths::getCacheDirRelToDocRoot() . '/doc-root';
|
353 |
|
354 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
355 |
-
$rules .= " RewriteCond
|
356 |
$rules .= " RewriteRule ^/?(.+)\.(" . self::$fileExt . ")$ /" . $cacheDirRel . "/" . self::$htaccessDirRelToDocRoot .
|
357 |
"/$1.$2.webp [NC,T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
358 |
|
@@ -838,6 +841,10 @@ class HTAccessRules
|
|
838 |
|
839 |
$capTests = self::$config['base-htaccess-on-these-capability-tests'];
|
840 |
|
|
|
|
|
|
|
|
|
841 |
|
842 |
self::$modHeaderDefinitelyUnavailable = ($capTests['modHeaderWorking'] === false);
|
843 |
self::$passThroughHeaderDefinitelyUnavailable = ($capTests['passThroughHeaderWorking'] === false);
|
27 |
private static $dirContainsSourceImages;
|
28 |
private static $dirContainsWebPImages;
|
29 |
private static $alterHtmlEnabled;
|
30 |
+
private static $docRootString;
|
31 |
|
32 |
private static function trueFalseNullString($var)
|
33 |
{
|
167 |
private static function infoRules()
|
168 |
{
|
169 |
|
170 |
+
return "# The rules below have been dynamically created by WebP Express in accordance with the plugin settings\n" .
|
171 |
+
"# DO NOT EDIT MANUALLY (unless you are prepared that your changes might be overridden by WebP Express)" . "\n" .
|
172 |
+
"# The following parameters have been in play to produce the rules:\n" .
|
173 |
"#\n# WebP Express options:\n" .
|
174 |
"# - Operation mode: " . self::$config['operation-mode'] . "\n" .
|
175 |
"# - Redirection to existing webp: " .
|
304 |
if (self::$useDocRootForStructuringCacheDir) {
|
305 |
if (self::$config['destination-extension'] == 'append') {
|
306 |
$rules .= " RewriteCond %{REQUEST_FILENAME}.webp -f\n";
|
307 |
+
//$rules .= " RewriteCond " . self::$docRootString . "/" . self::$htaccessDirRelToDocRoot . "/$1.$2.webp -f\n";
|
308 |
$rules .= " RewriteRule ^/?(.*)\.(" . self::$fileExt . ")$ $1.$2.webp [NC,T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
309 |
} else {
|
310 |
// extension: set to webp
|
311 |
|
312 |
+
//$rules .= " RewriteCond " . self::$docRootString . "/" . self::$htaccessDirRelToDocRoot . "/$1.webp -f\n";
|
313 |
//$rules .= " RewriteRule " . $rewriteRuleStart . "\.(" . self::$fileExt . ")$ $1.webp [T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
314 |
|
315 |
// Got these new rules here: https://www.digitalocean.com/community/tutorials/how-to-create-and-serve-webp-images-to-speed-up-your-website
|
316 |
// (but are they actually better than the ones we use for append?)
|
317 |
$rules .= " RewriteCond %{REQUEST_URI} (?i)(.*)(" . self::$fileExtIncludingDot . ")$\n";
|
318 |
+
$rules .= " RewriteCond " . self::$docRootString . "%1\.webp -f\n";
|
319 |
$rules .= " RewriteRule (?i)(.*)(" . self::$fileExtIncludingDot . ")$ %1\.webp [T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
320 |
|
321 |
// Instead of using REQUEST_URI, I can use REQUEST_FILENAME and remove DOCUMENT_ROOT
|
355 |
$cacheDirRel = Paths::getCacheDirRelToDocRoot() . '/doc-root';
|
356 |
|
357 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
358 |
+
$rules .= " RewriteCond " . self::$docRootString . "/" . $cacheDirRel . "/" . self::$htaccessDirRelToDocRoot . "/$1.$2.webp -f\n";
|
359 |
$rules .= " RewriteRule ^/?(.+)\.(" . self::$fileExt . ")$ /" . $cacheDirRel . "/" . self::$htaccessDirRelToDocRoot .
|
360 |
"/$1.$2.webp [NC,T=image/webp,E=EXISTING:1," . (self::$setAddVaryEnvInRedirect ? 'E=ADDVARY:1,' : '') . "L]\n\n";
|
361 |
|
841 |
|
842 |
$capTests = self::$config['base-htaccess-on-these-capability-tests'];
|
843 |
|
844 |
+
self::$docRootString = '%{DOCUMENT_ROOT}';
|
845 |
+
if (defined('WEBPEXPRESS_DOCUMENT_ROOT_IN_HTACCESS')) {
|
846 |
+
self::$docRootString = constant('WEBPEXPRESS_DOCUMENT_ROOT_IN_HTACCESS');
|
847 |
+
};
|
848 |
|
849 |
self::$modHeaderDefinitelyUnavailable = ($capTests['modHeaderWorking'] === false);
|
850 |
self::$passThroughHeaderDefinitelyUnavailable = ($capTests['passThroughHeaderWorking'] === false);
|
@@ -203,6 +203,8 @@ class SelfTestHelper
|
|
203 |
$wpResult = wp_remote_get($requestUrl, $args);
|
204 |
if (is_wp_error($wpResult)) {
|
205 |
$log[] = 'The remote request errored';
|
|
|
|
|
206 |
return [false, $log, $results];
|
207 |
}
|
208 |
if (!is_wp_error($wpResult) && !isset($wpResult['headers'])) {
|
@@ -549,7 +551,8 @@ class SelfTestHelper
|
|
549 |
$log[] = '- mod_rewrite working?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modRewriteWorking());
|
550 |
$log[] = '- mod_headers loaded?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeadersLoaded());
|
551 |
$log[] = '- mod_headers working (header set): ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeaderWorking());
|
552 |
-
|
|
|
553 |
$log[] = '- Can run php test file in plugins/webp-express/wod/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD());
|
554 |
$log[] = '- Can run php test file in plugins/webp-express/wod2/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD2());
|
555 |
$log[] = '- Directives for granting access like its done in wod/.htaccess allowed?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::grantAllAllowed());
|
203 |
$wpResult = wp_remote_get($requestUrl, $args);
|
204 |
if (is_wp_error($wpResult)) {
|
205 |
$log[] = 'The remote request errored';
|
206 |
+
$log[] = $wpResult->get_error_message();
|
207 |
+
//$log[] = print_r($wpResult, true);
|
208 |
return [false, $log, $results];
|
209 |
}
|
210 |
if (!is_wp_error($wpResult) && !isset($wpResult['headers'])) {
|
551 |
$log[] = '- mod_rewrite working?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modRewriteWorking());
|
552 |
$log[] = '- mod_headers loaded?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeadersLoaded());
|
553 |
$log[] = '- mod_headers working (header set): ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::modHeaderWorking());
|
554 |
+
//$log[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString($capTests['passThroughEnvWorking']);
|
555 |
+
$log[] = '- passing variables from *.htaccess* to PHP script through environment variable working?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::passThroughEnvWorking());
|
556 |
$log[] = '- Can run php test file in plugins/webp-express/wod/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD());
|
557 |
$log[] = '- Can run php test file in plugins/webp-express/wod2/ ?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::canRunTestScriptInWOD2());
|
558 |
$log[] = '- Directives for granting access like its done in wod/.htaccess allowed?: ' . self::trueFalseNullString(HTAccessCapabilityTestRunner::grantAllAllowed());
|
@@ -59,8 +59,13 @@ class SelfTestRedirectToExisting extends SelfTestRedirectAbstract
|
|
59 |
$log = array_merge($log, $remoteGetLog);
|
60 |
|
61 |
if (!$success) {
|
62 |
-
$log[] = 'The request
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
64 |
return [false, $log, $createdTestFiles];
|
65 |
}
|
66 |
//$log[count($log) - 1] .= '. ok!';
|
59 |
$log = array_merge($log, $remoteGetLog);
|
60 |
|
61 |
if (!$success) {
|
62 |
+
$log[] = 'The test cannot be completed, as the HTTP request failed. This does not neccesarily mean that the redirections ' .
|
63 |
+
"aren't" . ' working, but it means you will have to check it manually. Check out the FAQ on how to do this. ' .
|
64 |
+
'You might also want to check out why a simple HTTP request could not be issued. WebP Express uses such requests ' .
|
65 |
+
'for detecting system capabilities, which are used when generating .htaccess files. These tests are not essential, but ' .
|
66 |
+
'it would be best to have them working. I can inform that the Wordpress function *wp_remote_get* was used for the HTTP request ' .
|
67 |
+
'and the URL was: ' . $requestUrl;
|
68 |
+
|
69 |
return [false, $log, $createdTestFiles];
|
70 |
}
|
71 |
//$log[count($log) - 1] .= '. ok!';
|
@@ -20,7 +20,7 @@ class WPHttpRequester implements HttpRequesterInterface
|
|
20 |
//echo '<pre>' . print_r($response, true) . '</pre>';
|
21 |
|
22 |
if (is_wp_error($response)) {
|
23 |
-
return new HttpResponse('0',
|
24 |
} else {
|
25 |
$body = wp_remote_retrieve_body($response);
|
26 |
$statusCode = wp_remote_retrieve_response_code($response);
|
20 |
//echo '<pre>' . print_r($response, true) . '</pre>';
|
21 |
|
22 |
if (is_wp_error($response)) {
|
23 |
+
return new HttpResponse($response->get_error_message(), '0', []);
|
24 |
} else {
|
25 |
$body = wp_remote_retrieve_body($response);
|
26 |
$statusCode = wp_remote_retrieve_response_code($response);
|
@@ -3,7 +3,7 @@
|
|
3 |
<th scope="row">Destination structure<?php
|
4 |
echo helpIcon(
|
5 |
'<p>This setting determines how the converted files are structured within the folder that WebP Express ' .
|
6 |
-
'uses for storing webp images</p>' .
|
7 |
'<p><span style="text-decoration:underline">"document root"</span><br>' .
|
8 |
'When "document root" is selected, the webp images will be stored in:<br>' .
|
9 |
'<span style="white-space:pre-wrap;font-family:monospace">[cache root]/doc-root/[relative path of source image, from document root].</span><br>' .
|
@@ -19,13 +19,17 @@
|
|
19 |
'<span style="white-space:pre-wrap;font-family:monospace"">[cache root]/[image root]/[relative path of source image, from its image root].</span><br>' .
|
20 |
'</p>' .
|
21 |
'<p><span style="text-decoration:underline">Which option is best?</span><br>' .
|
22 |
-
'Well, in most cases it does not matter. However,
|
23 |
-
'
|
24 |
-
'
|
25 |
-
'is outside opendir restriction or an image root is located outside document root. WebP Express automatically detects this and will not allow you to select "document root" in those cases.</p>'
|
26 |
);
|
27 |
?></th>
|
28 |
<td>
|
|
|
|
|
|
|
|
|
|
|
29 |
<select name="destination-structure" id="destination_structure">
|
30 |
<?php
|
31 |
webpexpress_selectBoxOptions($config['destination-structure'], [
|
3 |
<th scope="row">Destination structure<?php
|
4 |
echo helpIcon(
|
5 |
'<p>This setting determines how the converted files are structured within the folder that WebP Express ' .
|
6 |
+
'uses for storing webp images (from here on called "the cache root")</p>' .
|
7 |
'<p><span style="text-decoration:underline">"document root"</span><br>' .
|
8 |
'When "document root" is selected, the webp images will be stored in:<br>' .
|
9 |
'<span style="white-space:pre-wrap;font-family:monospace">[cache root]/doc-root/[relative path of source image, from document root].</span><br>' .
|
19 |
'<span style="white-space:pre-wrap;font-family:monospace"">[cache root]/[image root]/[relative path of source image, from its image root].</span><br>' .
|
20 |
'</p>' .
|
21 |
'<p><span style="text-decoration:underline">Which option is best?</span><br>' .
|
22 |
+
'Well, in most cases it does not matter. However, there are hosts out there that have set the document root up incorrectly, ' .
|
23 |
+
'so I would generally recommend "Image roots". ' .
|
24 |
+
'On Nginx, I however recommend "Document root", as it requires fewer rewrite rules.</p>'
|
|
|
25 |
);
|
26 |
?></th>
|
27 |
<td>
|
28 |
+
<!--
|
29 |
+
The "image roots" option was added to make WebP Express work on systems where the document root is set up incorrectly or
|
30 |
+
is outside opendir restriction or an image root is located outside document root.
|
31 |
+
WebP Express automatically detects this and will not allow you to select "document root" in those cases.
|
32 |
+
-->
|
33 |
<select name="destination-structure" id="destination_structure">
|
34 |
<?php
|
35 |
webpexpress_selectBoxOptions($config['destination-structure'], [
|
@@ -190,17 +190,17 @@
|
|
190 |
},
|
191 |
{
|
192 |
"name": "rosell-dk/htaccess-capability-tester",
|
193 |
-
"version": "0.
|
194 |
-
"version_normalized": "0.
|
195 |
"source": {
|
196 |
"type": "git",
|
197 |
"url": "https://github.com/rosell-dk/htaccess-capability-tester.git",
|
198 |
-
"reference": "
|
199 |
},
|
200 |
"dist": {
|
201 |
"type": "zip",
|
202 |
-
"url": "https://api.github.com/repos/rosell-dk/htaccess-capability-tester/zipball/
|
203 |
-
"reference": "
|
204 |
"shasum": ""
|
205 |
},
|
206 |
"require": {
|
@@ -214,7 +214,7 @@
|
|
214 |
"suggest": {
|
215 |
"php-stan/php-stan": "Suggested for dev, in order to analyse code before committing"
|
216 |
},
|
217 |
-
"time": "2020-
|
218 |
"type": "library",
|
219 |
"extra": {
|
220 |
"scripts-descriptions": {
|
190 |
},
|
191 |
{
|
192 |
"name": "rosell-dk/htaccess-capability-tester",
|
193 |
+
"version": "0.9",
|
194 |
+
"version_normalized": "0.9.0.0",
|
195 |
"source": {
|
196 |
"type": "git",
|
197 |
"url": "https://github.com/rosell-dk/htaccess-capability-tester.git",
|
198 |
+
"reference": "2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c"
|
199 |
},
|
200 |
"dist": {
|
201 |
"type": "zip",
|
202 |
+
"url": "https://api.github.com/repos/rosell-dk/htaccess-capability-tester/zipball/2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c",
|
203 |
+
"reference": "2eb2cf38a9f42fc3aa647d6e9c896e124bfebf4c",
|
204 |
"shasum": ""
|
205 |
},
|
206 |
"require": {
|
214 |
"suggest": {
|
215 |
"php-stan/php-stan": "Suggested for dev, in order to analyse code before committing"
|
216 |
},
|
217 |
+
"time": "2020-11-04T10:29:38+00:00",
|
218 |
"type": "library",
|
219 |
"extra": {
|
220 |
"scripts-descriptions": {
|
@@ -1,2 +1,2 @@
|
|
|
|
1 |
ko_fi: rosell
|
2 |
-
patreon: rosell
|
1 |
+
github: rosell-dk
|
2 |
ko_fi: rosell
|
|
@@ -8,18 +8,18 @@
|
|
8 |
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/htaccess-capability-tester/blob/master/LICENSE)
|
9 |
|
10 |
|
11 |
-
Detect
|
12 |
|
13 |
-
There are cases where the only way to to learn if a given
|
14 |
|
15 |
This is what happens behind the scenes:
|
16 |
-
1. Some test files for a given test are put on the server (at least an
|
17 |
2. The test is triggered by doing a HTTP request
|
18 |
3. The response is interpreted
|
19 |
|
20 |
## Usage
|
21 |
|
22 |
-
To use the library, you must provide a path to where the test files are going to be put and
|
23 |
|
24 |
```php
|
25 |
require 'vendor/autoload.php';
|
@@ -28,7 +28,7 @@ use HtaccessCapabilityTester\HtaccessCapabilityTester;
|
|
28 |
$hct = new HtaccessCapabilityTester($baseDir, $baseUrl);
|
29 |
|
30 |
if ($hct->moduleLoaded('headers')) {
|
31 |
-
// mod_headers
|
32 |
}
|
33 |
if ($hct->rewriteWorks()) {
|
34 |
// rewriting works
|
@@ -40,94 +40,7 @@ if ($hct->htaccessEnabled() === false) {
|
|
40 |
|
41 |
// A bunch of other tests are available - see API
|
42 |
```
|
43 |
-
While having a reliable
|
44 |
-
|
45 |
-
|
46 |
-
## Running your own custom tests using the *customTest* method
|
47 |
-
|
48 |
-
A typical test s mentioned, a test has three phases:
|
49 |
-
1. Writing the test files to the directory in question
|
50 |
-
2. Doing a request (in advanced cases, more)
|
51 |
-
3. Interpreting the request
|
52 |
-
|
53 |
-
So, in order for `customTest()`, it needs to know. 1) What files are needed? 2) Which file should be requested? 3) How should the response be interpreted?
|
54 |
-
|
55 |
-
Here is a definition which can be used for implementing the `headerSetWorks` functionality yourself. It's in YAML because it is more readable like this.
|
56 |
-
|
57 |
-
<details><summary><u>Click here to see the PHP example</u></summary>
|
58 |
-
<p><br>
|
59 |
-
<b>PHP example</b>
|
60 |
-
|
61 |
-
```php
|
62 |
-
<?php
|
63 |
-
require 'vendor/autoload.php';
|
64 |
-
use HtaccessCapabilityTester\HtaccessCapabilityTester;
|
65 |
-
|
66 |
-
$hct = new HtaccessCapabilityTester($baseDir, $baseUrl);
|
67 |
-
|
68 |
-
$htaccessFile = <<<'EOD'
|
69 |
-
<IfModule mod_headers.c>
|
70 |
-
Header set X-Response-Header-Test: test
|
71 |
-
</IfModule>
|
72 |
-
EOD;
|
73 |
-
|
74 |
-
$test = [
|
75 |
-
'subdir' => 'header-set',
|
76 |
-
'files' => [
|
77 |
-
['.htaccess', $htaccessFile],
|
78 |
-
['request-me.txt', "hi"],
|
79 |
-
],
|
80 |
-
'request' => 'request-me.txt',
|
81 |
-
'interpretation' => [
|
82 |
-
['success', 'headers', 'contains-key-value', 'X-Response-Header-Test', 'test'],
|
83 |
-
|
84 |
-
// the next three mappings are actually not necessary, as customTest() does standard
|
85 |
-
// error handling automatically (can be turned off)
|
86 |
-
['failure', 'status-code', 'equals', '500'],
|
87 |
-
['inconclusive', 'status-code', 'equals', '403'],
|
88 |
-
['inconclusive', 'status-code', 'equals', '404'],
|
89 |
-
]
|
90 |
-
];
|
91 |
-
|
92 |
-
if ($hct->customTest($test)) {
|
93 |
-
// setting a header in the .htaccess works!
|
94 |
-
}
|
95 |
-
```
|
96 |
-
|
97 |
-
</p>
|
98 |
-
</details>
|
99 |
-
|
100 |
-
```yaml
|
101 |
-
subdir: header-set
|
102 |
-
files:
|
103 |
-
- filename: '.htaccess'
|
104 |
-
content: |
|
105 |
-
<IfModule mod_headers.c>
|
106 |
-
Header set X-Response-Header-Test: test
|
107 |
-
</IfModule>
|
108 |
-
- filename: 'request-me.txt'
|
109 |
-
content: 'hi'
|
110 |
-
|
111 |
-
request:
|
112 |
-
url: 'request-me.txt'
|
113 |
-
|
114 |
-
interpretation:
|
115 |
-
- [success, headers, contains-key-value, 'X-Response-Header-Test', 'test']
|
116 |
-
- [failure, status-code, equals, '500'] # actually not needed (part of standard error handling)
|
117 |
-
- [inconclusive, status-code, equals, '403'] # actually not needed (part of standard error handling)
|
118 |
-
- [inconclusive, status-code, equals, '404'] # actually not needed (part of standard error handling)
|
119 |
-
- [failure]
|
120 |
-
```
|
121 |
-
|
122 |
-
In fact, this is more or less how this library implements it.
|
123 |
-
|
124 |
-
The test definition has the following sub-definitions:
|
125 |
-
- *subdir*: Defines which subdir the test files should reside in
|
126 |
-
- *files*: Defines the files for the test (filename and content)
|
127 |
-
- *request*: Defines which file that should be requested
|
128 |
-
- *interpretation*: Defines how to interprete the response. It consists of a list of mappings is read from the top until one of the conditions is met. The first line for example translates to "Map to success if the body of the response equals '1'". If none of the conditions are met, the result is automatically mapped to 'inconclusive'.
|
129 |
-
|
130 |
-
For more info, look in the API (below). For real examples, check out the classes in the "Testers" dir - most of them are defined in this "language"
|
131 |
|
132 |
## API overview
|
133 |
|
@@ -136,9 +49,12 @@ For more info, look in the API (below). For real examples, check out the classes
|
|
136 |
All the test methods returns a test result, which is *true* for success, *false* for failure or *null* for inconclusive.
|
137 |
|
138 |
The tests have the following in common:
|
139 |
-
- If the server has been set up to ignore
|
140 |
- If the server has been set up to disallow the directive being tested (AllowOverride), the result is *failure* (both when configured to ignore and when configured to go fatal)
|
141 |
- A *403 Forbidden* results in *inconclusive*. Why? Because it could be that the server has been set up to forbid access to files matching a pattern that our test file unluckily matches. In most cases, this is unlikely, as most tests requests files with harmless-looking file extensions (often a "request-me.txt"). A few of the tests however requests a "test.php", which is more likely to be denied.
|
|
|
|
|
|
|
142 |
|
143 |
Most tests are implemented as a definition such as the one accepted in *customTest()*. This means that if you want one of the tests provided by this library to work slightly differently, you can easily grab the code in the corresponding class in the *Testers* directory, make your modification and call *customTest()*.
|
144 |
|
@@ -343,12 +259,12 @@ interpretation:
|
|
343 |
|
344 |
<details><summary><b>htaccessEnabled()</b></summary>
|
345 |
<p><br>
|
346 |
-
Apache can be configured to ignore
|
347 |
|
348 |
The method works by trying out a series of subtests until a conclusion is reached. It will never come out inconclusive.
|
349 |
|
350 |
How does it work?
|
351 |
-
- The first strategy is testing a series of features, such as `rewriteWorks()`. If any of them works, well, then the
|
352 |
- Secondly, the `serverSignatureWorks()` is tested. The "ServerSignature" directive is special because it is in core and cannot be disabled with AllowOverride. If this test comes out as a failure, it is so *highly likely* that the .htaccess has not been processed, that we conclude that it has not.
|
353 |
- Lastly, if all other methods failed, we try calling `crashTest()` on an .htaccess file that we on purpose put syntax errors in. If it crashes, the .htaccess file must have been proccessed. If it does not crash, it has not. This last method is bulletproof - so why not do it first? Because it might generate an entry in the error log.
|
354 |
|
@@ -688,10 +604,11 @@ This allows you to use another object for lining up the test files than the stan
|
|
688 |
</details>
|
689 |
|
690 |
## Stable API?
|
691 |
-
The 0.
|
692 |
|
693 |
-
Changes in the new 0.
|
694 |
-
-
|
|
|
695 |
|
696 |
Expected changes in the 1.0 release:
|
697 |
- TestResult class might be disposed off so the "internal" Tester classes also returns bool|null.
|
8 |
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/htaccess-capability-tester/blob/master/LICENSE)
|
9 |
|
10 |
|
11 |
+
Detect *.htaccess* capabilities through live tests.
|
12 |
|
13 |
+
There are cases where the only way to to learn if a given *.htaccess* capability is enabled / supported on a system is by examining it "from the outside" through a HTTP request. This library is build to handle such testing easily.
|
14 |
|
15 |
This is what happens behind the scenes:
|
16 |
+
1. Some test files for a given test are put on the server (at least an *.htaccess* file)
|
17 |
2. The test is triggered by doing a HTTP request
|
18 |
3. The response is interpreted
|
19 |
|
20 |
## Usage
|
21 |
|
22 |
+
To use the library, you must provide a path to where the test files are going to be put and the corresponding URL that they can be reached. Besides that, you just need to pick one of the tests that you want to run.
|
23 |
|
24 |
```php
|
25 |
require 'vendor/autoload.php';
|
28 |
$hct = new HtaccessCapabilityTester($baseDir, $baseUrl);
|
29 |
|
30 |
if ($hct->moduleLoaded('headers')) {
|
31 |
+
// mod_headers is loaded (tested in a real .htaccess by using the "IfModule" directive)
|
32 |
}
|
33 |
if ($hct->rewriteWorks()) {
|
34 |
// rewriting works
|
40 |
|
41 |
// A bunch of other tests are available - see API
|
42 |
```
|
43 |
+
While having a reliable *moduleLoaded()* method is a great improvement over current state of affairs, beware that it is possible that the server has ie *mod_rewrite* enabled, but at the same time has disallowed using ie the "RewriteRule" directive in *.htaccess* files. This is why the library has the *rewriteWorks()* method and similar methods for testing various capabilites fully (check the API overview below). Providing tests for all kinds of functionality, would however be too much for any library. Instead this library makes it a breeze to define a custom test and run it through the *customTest($def)* method. To learn more, check out the [Running your own custom tests](https://github.com/rosell-dk/htaccess-capability-tester/blob/master/docs/Running%20your%20own%20custom%20tests.md) document.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
## API overview
|
46 |
|
49 |
All the test methods returns a test result, which is *true* for success, *false* for failure or *null* for inconclusive.
|
50 |
|
51 |
The tests have the following in common:
|
52 |
+
- If the server has been set up to ignore *.htaccess* files entirely, the result will be *failure*.
|
53 |
- If the server has been set up to disallow the directive being tested (AllowOverride), the result is *failure* (both when configured to ignore and when configured to go fatal)
|
54 |
- A *403 Forbidden* results in *inconclusive*. Why? Because it could be that the server has been set up to forbid access to files matching a pattern that our test file unluckily matches. In most cases, this is unlikely, as most tests requests files with harmless-looking file extensions (often a "request-me.txt"). A few of the tests however requests a "test.php", which is more likely to be denied.
|
55 |
+
- A *404 Not Found* results in *inconclusive*
|
56 |
+
- If the request fails completely (ie timeout), the result is *inconclusive*
|
57 |
+
|
58 |
|
59 |
Most tests are implemented as a definition such as the one accepted in *customTest()*. This means that if you want one of the tests provided by this library to work slightly differently, you can easily grab the code in the corresponding class in the *Testers* directory, make your modification and call *customTest()*.
|
60 |
|
259 |
|
260 |
<details><summary><b>htaccessEnabled()</b></summary>
|
261 |
<p><br>
|
262 |
+
Apache can be configured to ignore *.htaccess* files altogether. This method tests if the *.htaccess* file is processed at all
|
263 |
|
264 |
The method works by trying out a series of subtests until a conclusion is reached. It will never come out inconclusive.
|
265 |
|
266 |
How does it work?
|
267 |
+
- The first strategy is testing a series of features, such as `rewriteWorks()`. If any of them works, well, then the *.htaccess* must have been processed.
|
268 |
- Secondly, the `serverSignatureWorks()` is tested. The "ServerSignature" directive is special because it is in core and cannot be disabled with AllowOverride. If this test comes out as a failure, it is so *highly likely* that the .htaccess has not been processed, that we conclude that it has not.
|
269 |
- Lastly, if all other methods failed, we try calling `crashTest()` on an .htaccess file that we on purpose put syntax errors in. If it crashes, the .htaccess file must have been proccessed. If it does not crash, it has not. This last method is bulletproof - so why not do it first? Because it might generate an entry in the error log.
|
270 |
|
604 |
</details>
|
605 |
|
606 |
## Stable API?
|
607 |
+
The 0.9 release is just about right. I do not expect any changes in the part of the API that is mentioned above. So, if you stick to that, it should still work, when the 1.0 release comes.
|
608 |
|
609 |
+
Changes in the new 0.9 release:
|
610 |
+
- Request failures (such as timeout) results in *inconclusive*.
|
611 |
+
- If you have implemented your own HttpRequester rather than using the default, you need to update it. It must now return status code "0" if the request failed (ie timeout)
|
612 |
|
613 |
Expected changes in the 1.0 release:
|
614 |
- TestResult class might be disposed off so the "internal" Tester classes also returns bool|null.
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Running your own custom tests using the *customTest* method
|
2 |
+
|
3 |
+
A typical test s mentioned, a test has three phases:
|
4 |
+
1. Writing the test files to the directory in question
|
5 |
+
2. Doing a request (in advanced cases, more)
|
6 |
+
3. Interpreting the request
|
7 |
+
|
8 |
+
So, in order for *customTest()*, it needs to know. 1) What files are needed? 2) Which file should be requested? 3) How should the response be interpreted?
|
9 |
+
|
10 |
+
Here is a definition which can be used for implementing the *headerSetWorks()* functionality yourself. It's in YAML because it is more readable like this.
|
11 |
+
|
12 |
+
<details><summary><u>Click here to see the PHP example</u></summary>
|
13 |
+
<p><br>
|
14 |
+
<b>PHP example</b>
|
15 |
+
|
16 |
+
```php
|
17 |
+
<?php
|
18 |
+
require 'vendor/autoload.php';
|
19 |
+
use HtaccessCapabilityTester\HtaccessCapabilityTester;
|
20 |
+
|
21 |
+
$hct = new HtaccessCapabilityTester($baseDir, $baseUrl);
|
22 |
+
|
23 |
+
$htaccessFile = <<<'EOD'
|
24 |
+
<IfModule mod_headers.c>
|
25 |
+
Header set X-Response-Header-Test: test
|
26 |
+
</IfModule>
|
27 |
+
EOD;
|
28 |
+
|
29 |
+
$test = [
|
30 |
+
'subdir' => 'header-set',
|
31 |
+
'files' => [
|
32 |
+
['.htaccess', $htaccessFile],
|
33 |
+
['request-me.txt', "hi"],
|
34 |
+
],
|
35 |
+
'request' => 'request-me.txt',
|
36 |
+
'interpretation' => [
|
37 |
+
['success', 'headers', 'contains-key-value', 'X-Response-Header-Test', 'test'],
|
38 |
+
|
39 |
+
// the next three mappings are actually not necessary, as customTest() does standard
|
40 |
+
// error handling automatically (can be turned off)
|
41 |
+
['failure', 'status-code', 'equals', '500'],
|
42 |
+
['inconclusive', 'status-code', 'equals', '403'],
|
43 |
+
['inconclusive', 'status-code', 'equals', '404'],
|
44 |
+
]
|
45 |
+
];
|
46 |
+
|
47 |
+
if ($hct->customTest($test)) {
|
48 |
+
// setting a header in the .htaccess works!
|
49 |
+
}
|
50 |
+
```
|
51 |
+
|
52 |
+
</p>
|
53 |
+
</details>
|
54 |
+
|
55 |
+
```yaml
|
56 |
+
subdir: header-set
|
57 |
+
files:
|
58 |
+
- filename: '.htaccess'
|
59 |
+
content: |
|
60 |
+
<IfModule mod_headers.c>
|
61 |
+
Header set X-Response-Header-Test: test
|
62 |
+
</IfModule>
|
63 |
+
- filename: 'request-me.txt'
|
64 |
+
content: 'hi'
|
65 |
+
|
66 |
+
request:
|
67 |
+
url: 'request-me.txt'
|
68 |
+
|
69 |
+
interpretation:
|
70 |
+
- [success, headers, contains-key-value, 'X-Response-Header-Test', 'test']
|
71 |
+
- [failure, status-code, equals, '500'] # actually not needed (part of standard error handling)
|
72 |
+
- [inconclusive, status-code, equals, '403'] # actually not needed (part of standard error handling)
|
73 |
+
- [inconclusive, status-code, equals, '404'] # actually not needed (part of standard error handling)
|
74 |
+
- [failure]
|
75 |
+
```
|
76 |
+
|
77 |
+
In fact, this is more or less how this library implements it.
|
78 |
+
|
79 |
+
The test definition has the following sub-definitions:
|
80 |
+
- *subdir*: Defines which subdir the test files should reside in
|
81 |
+
- *files*: Defines the files for the test (filename and content)
|
82 |
+
- *request*: Defines which file that should be requested
|
83 |
+
- *interpretation*: Defines how to interprete the response. It consists of a list of mappings is read from the top until one of the conditions is met. The first line for example translates to "Map to success if the body of the response equals '1'". If none of the conditions are met, the result is automatically mapped to 'inconclusive'.
|
84 |
+
|
85 |
+
For more info, look in the API (below). For real examples, check out the classes in the "Testers" dir - most of them are defined in this "language"
|
@@ -7,7 +7,9 @@ interface HttpRequesterInterface
|
|
7 |
/**
|
8 |
* Make a HTTP request to a URL.
|
9 |
*
|
10 |
-
* @return HttpResponse A HttpResponse object, which simply contains body and
|
|
|
|
|
11 |
*/
|
12 |
public function makeHttpRequest($url);
|
13 |
}
|
7 |
/**
|
8 |
* Make a HTTP request to a URL.
|
9 |
*
|
10 |
+
* @return HttpResponse A HttpResponse object, which simply contains body, status code and response headers.
|
11 |
+
* In case the request itself fails, the status code is "0" and the body should contain
|
12 |
+
* error description (if available)
|
13 |
*/
|
14 |
public function makeHttpRequest($url);
|
15 |
}
|
@@ -72,5 +72,4 @@ class HttpResponse
|
|
72 |
}
|
73 |
return false;
|
74 |
}
|
75 |
-
|
76 |
}
|
72 |
}
|
73 |
return false;
|
74 |
}
|
|
|
75 |
}
|
@@ -9,15 +9,17 @@ class SimpleHttpRequester implements HttpRequesterInterface
|
|
9 |
*
|
10 |
* @param string $url The URL to make the HTTP request to
|
11 |
*
|
12 |
-
* @return HttpResponse A HttpResponse object, which simply contains body, status code
|
13 |
-
* and
|
|
|
14 |
*/
|
15 |
public function makeHttpRequest($url)
|
16 |
{
|
17 |
// PS: We suppress the E_WARNING level error generated on failure
|
18 |
$body = @file_get_contents($url);
|
19 |
if ($body === false) {
|
20 |
-
|
|
|
21 |
}
|
22 |
|
23 |
// $http_response_header materializes out of thin air when file_get_contents() is called
|
9 |
*
|
10 |
* @param string $url The URL to make the HTTP request to
|
11 |
*
|
12 |
+
* @return HttpResponse A HttpResponse object, which simply contains body, status code and response headers.
|
13 |
+
* In case the request itself fails, the status code is "0" and the body should contain
|
14 |
+
* error description (if available)
|
15 |
*/
|
16 |
public function makeHttpRequest($url)
|
17 |
{
|
18 |
// PS: We suppress the E_WARNING level error generated on failure
|
19 |
$body = @file_get_contents($url);
|
20 |
if ($body === false) {
|
21 |
+
//$body = '';
|
22 |
+
return new HttpResponse('The following request failed: file_get_contents(' . $url . ')', '0', []);
|
23 |
}
|
24 |
|
25 |
// $http_response_header materializes out of thin air when file_get_contents() is called
|
@@ -43,7 +43,7 @@ class CrashTester extends CustomTester
|
|
43 |
],
|
44 |
'request' => [
|
45 |
'url' => 'request-me.txt',
|
46 |
-
'bypass-standard-error-handling' => ['
|
47 |
],
|
48 |
'interpretation' => [
|
49 |
['success', 'status-code', 'not-equals', '500'],
|
@@ -58,7 +58,7 @@ class CrashTester extends CustomTester
|
|
58 |
],
|
59 |
'request' => [
|
60 |
'url' => 'request-me.txt',
|
61 |
-
'bypass-standard-error-handling' => ['
|
62 |
],
|
63 |
'interpretation' => [
|
64 |
// The suspect crashed. But if the innocent crashes too, we cannot judge
|
43 |
],
|
44 |
'request' => [
|
45 |
'url' => 'request-me.txt',
|
46 |
+
'bypass-standard-error-handling' => ['403', '404', '500']
|
47 |
],
|
48 |
'interpretation' => [
|
49 |
['success', 'status-code', 'not-equals', '500'],
|
58 |
],
|
59 |
'request' => [
|
60 |
'url' => 'request-me.txt',
|
61 |
+
'bypass-standard-error-handling' => ['403', '404', '500']
|
62 |
],
|
63 |
'interpretation' => [
|
64 |
// The suspect crashed. But if the innocent crashes too, we cannot judge
|
@@ -88,6 +88,8 @@ class CustomTester extends AbstractTester
|
|
88 |
private function standardErrorHandling($response)
|
89 |
{
|
90 |
switch ($response->statusCode) {
|
|
|
|
|
91 |
case '403':
|
92 |
return new TestResult(null, '403 Forbidden');
|
93 |
case '404':
|
88 |
private function standardErrorHandling($response)
|
89 |
{
|
90 |
switch ($response->statusCode) {
|
91 |
+
case '0':
|
92 |
+
return new TestResult(null, $response->body);
|
93 |
case '403':
|
94 |
return new TestResult(null, '403 Forbidden');
|
95 |
case '404':
|
@@ -97,7 +97,6 @@ class ResponseInterpreter
|
|
97 |
return (strpos($val, $arg1) === 0);
|
98 |
}
|
99 |
return false;
|
100 |
-
|
101 |
}
|
102 |
|
103 |
|
97 |
return (strpos($val, $arg1) === 0);
|
98 |
}
|
99 |
return false;
|
|
|
100 |
}
|
101 |
|
102 |
|
@@ -86,11 +86,11 @@ class HtaccessEnabledTester extends AbstractTester
|
|
86 |
// (we do this lastly because it may generate an entry in the error log)
|
87 |
$crashTestResult = $hct->crashTest('aoeu', 'htaccess-enabled-malformed-htaccess');
|
88 |
if (is_null($crashTestResult)) {
|
89 |
-
//
|
90 |
-
//
|
91 |
-
//
|
92 |
$status = null;
|
93 |
-
$info = 'all requests
|
94 |
} elseif ($crashTestResult === false) {
|
95 |
// It crashed, - which means .htaccess is processed!
|
96 |
$status = true;
|
86 |
// (we do this lastly because it may generate an entry in the error log)
|
87 |
$crashTestResult = $hct->crashTest('aoeu', 'htaccess-enabled-malformed-htaccess');
|
88 |
if (is_null($crashTestResult)) {
|
89 |
+
// Two scenarios:
|
90 |
+
// 1: All requests fails (without response code)
|
91 |
+
// 2: The crash test could not figure it out (ie if even innocent requests crashes)
|
92 |
$status = null;
|
93 |
+
$info = 'all requests fails (even innocent ones)';
|
94 |
} elseif ($crashTestResult === false) {
|
95 |
// It crashed, - which means .htaccess is processed!
|
96 |
$status = true;
|
@@ -27,6 +27,7 @@ class InnocentRequestTester extends CustomTester
|
|
27 |
],
|
28 |
'interpretation' => [
|
29 |
['success', 'status-code', 'equals', '200'],
|
|
|
30 |
['inconclusive', 'status-code', 'equals', '403'],
|
31 |
['inconclusive', 'status-code', 'equals', '404'],
|
32 |
['failure'],
|
27 |
],
|
28 |
'interpretation' => [
|
29 |
['success', 'status-code', 'equals', '200'],
|
30 |
+
['inconclusive', 'status-code', 'equals', '0'],
|
31 |
['inconclusive', 'status-code', 'equals', '403'],
|
32 |
['inconclusive', 'status-code', 'equals', '404'],
|
33 |
['failure'],
|
@@ -355,7 +355,7 @@ EOD;
|
|
355 |
return new TestResult(false, '.htaccess files are ignored');
|
356 |
} elseif (is_null($htaccessEnabledTest)) {
|
357 |
// We happen to know that if that test cannot establish anything,
|
358 |
-
// then none of the usual weapons works - we can surrender
|
359 |
return new TestResult(null, 'no methods available - we surrender early');
|
360 |
}
|
361 |
|
355 |
return new TestResult(false, '.htaccess files are ignored');
|
356 |
} elseif (is_null($htaccessEnabledTest)) {
|
357 |
// We happen to know that if that test cannot establish anything,
|
358 |
+
// then none of the usual weapons works - we can surrender right away
|
359 |
return new TestResult(null, 'no methods available - we surrender early');
|
360 |
}
|
361 |
|
@@ -36,6 +36,9 @@ class FakeServer implements TestFilesLineUpperInterface, HttpRequesterInterface
|
|
36 |
/** @var bool Returns the php text file rather than "Sorry, this server cannot process PHP!" */
|
37 |
private $handlePHPasText = false;
|
38 |
|
|
|
|
|
|
|
39 |
/** @var array Predefined responses for certain urls */
|
40 |
private $responses;
|
41 |
|
@@ -59,6 +62,10 @@ class FakeServer implements TestFilesLineUpperInterface, HttpRequesterInterface
|
|
59 |
$statusCode = '200';
|
60 |
$headers = [];
|
61 |
|
|
|
|
|
|
|
|
|
62 |
//echo 'Fakeserver request:' . $url . "\n";
|
63 |
if (isset($this->responses[$url])) {
|
64 |
//echo 'predefined: ' . $url . "\n";
|
@@ -131,6 +138,10 @@ class FakeServer implements TestFilesLineUpperInterface, HttpRequesterInterface
|
|
131 |
$this->crashAll = true;
|
132 |
}
|
133 |
|
|
|
|
|
|
|
|
|
134 |
|
135 |
public function handlePHPasText()
|
136 |
{
|
36 |
/** @var bool Returns the php text file rather than "Sorry, this server cannot process PHP!" */
|
37 |
private $handlePHPasText = false;
|
38 |
|
39 |
+
/** @var bool If all requests fail (without response code) */
|
40 |
+
private $failAll = false;
|
41 |
+
|
42 |
/** @var array Predefined responses for certain urls */
|
43 |
private $responses;
|
44 |
|
62 |
$statusCode = '200';
|
63 |
$headers = [];
|
64 |
|
65 |
+
if ($this->failAll) {
|
66 |
+
return new HttpResponse('', '0', []);
|
67 |
+
}
|
68 |
+
|
69 |
//echo 'Fakeserver request:' . $url . "\n";
|
70 |
if (isset($this->responses[$url])) {
|
71 |
//echo 'predefined: ' . $url . "\n";
|
138 |
$this->crashAll = true;
|
139 |
}
|
140 |
|
141 |
+
public function failAllRequests()
|
142 |
+
{
|
143 |
+
$this->failAll = true;
|
144 |
+
}
|
145 |
|
146 |
public function handlePHPasText()
|
147 |
{
|
@@ -124,4 +124,12 @@ class ContentDigestTesterTest extends BasisTestCase
|
|
124 |
$this->assertSuccess($testResult);
|
125 |
}
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
124 |
$this->assertSuccess($testResult);
|
125 |
}
|
126 |
|
127 |
+
public function testRequestFailure()
|
128 |
+
{
|
129 |
+
$fakeServer = new FakeServer();
|
130 |
+
$fakeServer->failAllRequests();
|
131 |
+
$testResult = $fakeServer->runTester(new ContentDigestTester());
|
132 |
+
$this->assertInconclusive($testResult);
|
133 |
+
|
134 |
+
}
|
135 |
}
|
@@ -103,4 +103,12 @@ class CrashTesterTest extends BasisTestCase
|
|
103 |
$this->assertFailure($testResult);
|
104 |
}
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
}
|
103 |
$this->assertFailure($testResult);
|
104 |
}
|
105 |
|
106 |
+
public function testRequestFailure()
|
107 |
+
{
|
108 |
+
$fakeServer = new FakeServer();
|
109 |
+
$fakeServer->failAllRequests();
|
110 |
+
$testResult = $fakeServer->runTester(new CrashTester('aoeu', 'test'));
|
111 |
+
$this->assertInconclusive($testResult);
|
112 |
+
}
|
113 |
+
|
114 |
}
|
@@ -113,4 +113,12 @@ class HtaccessEnabledTesterTest extends BasisTestCase
|
|
113 |
$this->assertInconclusive($testResult);
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
113 |
$this->assertInconclusive($testResult);
|
114 |
}
|
115 |
|
116 |
+
public function testRequestFailure()
|
117 |
+
{
|
118 |
+
$fakeServer = new FakeServer();
|
119 |
+
$fakeServer->failAllRequests();
|
120 |
+
$testResult = $fakeServer->runTester(new HtaccessEnabledTester());
|
121 |
+
$this->assertInconclusive($testResult);
|
122 |
+
}
|
123 |
+
|
124 |
}
|
@@ -246,4 +246,12 @@ class ModuleLoadedTesterTest extends BasisTestCase
|
|
246 |
$this->assertFailure($testResult);
|
247 |
}
|
248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
}
|
246 |
$this->assertFailure($testResult);
|
247 |
}
|
248 |
|
249 |
+
public function testRequestFailure()
|
250 |
+
{
|
251 |
+
$fakeServer = new FakeServer();
|
252 |
+
$fakeServer->failAllRequests();
|
253 |
+
$testResult = $fakeServer->runTester(new ModuleLoadedTester('setenvif'));
|
254 |
+
$this->assertInconclusive($testResult);
|
255 |
+
}
|
256 |
+
|
257 |
}
|
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
-
* Version: 0.18.
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
+
* Version: 0.18.3
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|