{"id":1377,"date":"2023-11-19T17:30:27","date_gmt":"2023-11-19T23:30:27","guid":{"rendered":"https:\/\/www.nathanhunstad.com\/blog\/?p=1377"},"modified":"2023-11-19T17:30:27","modified_gmt":"2023-11-19T23:30:27","slug":"fun-with-mod_security-htaccess-and-php-updates","status":"publish","type":"post","link":"https:\/\/www.nathanhunstad.com\/blog\/2023\/11\/fun-with-mod_security-htaccess-and-php-updates\/","title":{"rendered":"Fun with mod_security, htaccess, and PHP updates"},"content":{"rendered":"\n<p>It all started with an updated PHP version. This website had been running on PHP 7.4, which went end of life a year ago. I had requested several times that my hosting provider update to a supported version of PHP for security reasons, but was rebuffed. A week ago I decided to ask yet again, and this time HostGator migrated my site to a server with PHP 8, probably to get me to stop complaining. Post-migration, I changed my site to use PHP 8.1 because trying 8.2 broke everything, clicked around some to make sure everything still appeared to be working, and moved on from what I thought was a successful upgrade.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Problems Found<\/h2>\n\n\n\n<p>Today, I get an email from Google Search Console stating that some of my pages were returning 4XX errors. I am certainly not an expert on Google Search Console, but if you have a website, it&#8217;s a very good idea to use it to find these kinds of errors. When I looked at the pages that were being flagged as unreachable, I noticed that they were photos from the photo side of my site, which runs on ZenPhoto. All of the affected URLs ended in &#8220;jpg.php&#8221;, and all of them had a 406 error with the message &#8220;Not Acceptable!<br>An appropriate representation of the requested resource could not be found on this server. This error was generated by Mod_Security.&#8221;<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"881\" height=\"134\" src=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image.png\" alt=\"\" class=\"wp-image-1378\" style=\"width:610px;height:auto\" srcset=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image.png 881w, https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-300x46.png 300w, https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-768x117.png 768w\" sizes=\"auto, (max-width: 881px) 100vw, 881px\" \/><\/a><figcaption class=\"wp-element-caption\">No, YOU&#8217;RE not acceptable!<\/figcaption><\/figure>\n\n\n\n<p>It appeared that all of the individual photo pages in my albums had this problem, and that meant that phots were pretty much inaccessible. Not good! I did some searching and came across <a href=\"https:\/\/forum.zenphoto.org\/discussion\/1410754\/how-to-fix-mod-security-error-message-on-image-pages\" target=\"_blank\" rel=\"noopener\" title=\"\">this forum post<\/a>, which suggested changing the URL options mod_rewrite suffix under &#8220;Options&#8230;General&#8221; to .html from .php:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"476\" height=\"137\" src=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-1.png\" alt=\"\" class=\"wp-image-1379\" srcset=\"https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-1.png 476w, https:\/\/www.nathanhunstad.com\/blog\/wp-content\/uploads\/2023\/11\/image-1-300x86.png 300w\" sizes=\"auto, (max-width: 476px) 100vw, 476px\" \/><\/a><figcaption class=\"wp-element-caption\">URL Options in ZenPhoto<\/figcaption><\/figure>\n\n\n\n<p>Changing this option did solve the 406 Not Acceptable error, and my images were being served up again, with a .jpg.html URL instead of .jpg.php. However, as that forum post stated, changing this option will change your URLs and can mess with SEO. That&#8217;s exactly how I became aware of the problem in the first place: the URLs that Google indexed were using the old .jpg.php URLs, and although this website is certainly not popular enough to be getting a lot of traffic to random photos from Google, the fact that this would break URLs in Google search results just annoyed me.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">301 To The Rescue<\/h2>\n\n\n\n<p>The correct way to deal with this kind of issue is to set up a 301 Moved Permanently redirect on the old URLs to point to the new ones. This is something you can do by using rewrite rules in your .htaccess file. But first, I had to fix the 406 error that caused the issue in the first place.<\/p>\n\n\n\n<p>HostGator controls the mod_security rules, but per <a href=\"https:\/\/www.hostgator.com\/help\/article\/secfilterengine-and-secfilterscanpost\" target=\"_blank\" rel=\"noopener\" title=\"\">this article<\/a>, you can reach out to them to selectively disable rules if they are causing any problems with your website. So I did this, and they very quickly removed the rule that was causing that error. Once that error was gone, I could add this very simple rewrite rule to rewrite anything that ended with &#8220;.jpg.php&#8221; to &#8220;.jpg.html&#8221;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  RewriteRule ^(.*)\\.jpg\\.php    $1.jpg.html &#91;R=301,L]<\/code><\/pre>\n\n\n\n<p>With this rule in place in the .htaccess file in my photo folder, all of my old URLs would redirect to the new one and display properly, something I validated by trying one of the URLs that Google had alerted me on.<\/p>\n\n\n\n<p>I then regenerated my <a href=\"https:\/\/www.nathanhunstad.com\/photo\/cache_html\/sitemap\/sitemapindex.xml\" title=\"\">sitemap<\/a> files so that going forward Google will get the correct URLs for all content, and will monitor those URLs going forward. I also triggered a recheck of the URLs that were throwing errors so Google can validate that the redirect works. And that was that!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Do It The Harder Way<\/h2>\n\n\n\n<p>Now, if you were paying attention, at this point you would likely ask &#8220;Couldn&#8217;t you have skipped most of this by asking HostGator to just fix the mod_security rule and keep the URLs ending in php?&#8221; And yes, that would have solved the immediate problem of broken URLs. However, .html is the preferred value for that option now, and it&#8217;s one I also prefer. Plus, had I stopped there, I would never have learned how to create those rewrite rules, which is a handy skill to have.<\/p>\n\n\n\n<p>It took a bit more work, but I did learn a few things about .htaccess files and mod_security along the way. And sometimes, you just need to bite the bullet on breaking changes!<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After upgrading my website to PHP 8.1, Google alerted me to some URLs that were being blocked by mod_security. Learn how I fixed that error and set up rewrite rules to fix the old URLs on the fly.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[127],"tags":[301],"class_list":["post-1377","post","type-post","status-publish","format-standard","hentry","category-security","tag-php","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1377","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/comments?post=1377"}],"version-history":[{"count":1,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1377\/revisions"}],"predecessor-version":[{"id":1380,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1377\/revisions\/1380"}],"wp:attachment":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/media?parent=1377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/categories?post=1377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/tags?post=1377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}