3

I’m using Apache 2.4.6 with mod_alias and have a website which is receiving traffic from a link on another website that I have no control over. The other site’s link is poorly formed and it causes visitors that come to my site from the external site to receive an immediate 400 error. The url ends in a literal % sign for some reason: domain.com/news/october_news.pdf%

(Side note: Suffice it to say that the originating website cannot be contacted and will not change the URL for reasons unknown.)

My site heavily uses mod_alias and the Redirect directive, so I was hoping to maintain consistency and use the same directive for the benefit of future webmasters. From my reading of the documentation it would seem possible, but I’ve been unable to get it to work. I’m attempting to 301 redirect anyone that goes to the URL domain.com/news/october_news.pdf% to domain.com/news/october_news.pdf. Basically I need to hack off the percentage sign. How would I go about that with mod_alias and Redirect? Or perhaps it simply cannot be done and I need to use RedirectMatch.

I’ve currently attempted each of the following in an .htaccess file:

redirect “/news/october_news.pdf%” “/news/october_news.pdf”
redirect “/news/october_news.pdf%25” “/news/october_news.pdf”
redirect “/news/october_news.pdf\%” “/news/october_news.pdf”

All of which have not changed the 400 Bad Request error that Apache returns to the browser.

1

You can't use a mod_alias Redirect (or even mod_rewrite RewriteRule - which executes before mod_alias) to catch a 400 "bad request". This applies to directives in both .htaccess and in the server config. The "bad request" is simply triggered much earlier in the request.

In fact, you can't do anything in .htaccess to trap the bad request. .htaccess is never even processed - it's too late.

However, as @Stephen suggested in comments, you can define a custom 400 error document in the server config and examine such requests using your server-side script (eg. PHP) to then issue an overriding redirect. But this error document must be defined in a server or virtualhost context; .htaccess (or <Directory> containers) is too late. For example, directly in your <VirtualHost> container:

ErrorDocument 400 /errordocs/e400.php

Then, in the case of PHP, you can examine the requested URL (containing the trailing %) using the REDIRECT_URL (or REQUEST_URI) indices of the $_SERVER superglobal and issue the appropriate redirect.

Make sure your default 400 response returns a reasonable / user friendly message with appropriate links, otherwise you'll likely get a browser default.


redirect “/news/october_news.pdf%” “/news/october_news.pdf”

Aside: You should not be using curly quotes .. to surround the arguments - the request will never match (for this reason also). If you need/want to surround the arguments then you must use straight double quotes, ie. ".

This is also a 302 (temporary) redirect (maybe you did this just to test?). This should ultimately be a 301 (permanent) redirect.

  • 1
    Ah, I wasn't thinking about the order of execution when a URL is requested from Apache. This makes sense now. Looks like I'll need to whip up a 400 app on this server for things like this. I'll server a pretty 400 for generic errors, and have special logic for known bad requests like this rogue external site with awful links. As for the curly quotes, those are artifacts my Mac inserted into my post, not actually on the server. And yes, the 302 was intentional because I got tired of having to force Chrome DevTools to ignore the 301 that it cached while testing. – Wesley Apr 29 '18 at 2:35

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.