Intelligent redirection - apache

I am a newbie using Apache 2.4.18.
I have URLs with the following form that I'd like to redirect.
Current URL: https://www.example.org/page/10/
Desired URL: https://www.example.org/index.php/page/10/
If I use the following rule, I can modify a request, eg for page 2:
Redirect permanent /page/2/ /index.php/page/2/
However, I want to redirect without having to hardcode all the pages on my site. I have tried the following, my browser fails after many redirects:
RedirectMatch /page/(.*)/$ /index.php/page/$1/
And using the following fails, I don't know why:
RedirectMatch "https://www.example.org/page/(.*)/$" "https://www.example.org/index.php/page/$1/"
What am I doing wrong?

In your line
RedirectMatch /page/(.*)/$ /index.php/page/$1/
/page/2/ will in fact redirect to /index.php/page/2/, but this new URL will still match your RedirectMatch’s regex and will produce another redirect. That’s why it redirects endlessly until the browser gives up (see this example).
I’d try with RedirectMatch ^/page/(.*)/$ /index.php/page/$1/, so when redirected, /index.php/page/2/ will no longer match ^/page/(.*)/$ and will not produce the recursive redirects.
As an aftertought, why not use RewriteRule instead? It’d save an additional HTTP request to the client, as redirects are usually used when you need to send the client to a different server.

Related

RedirectMatch without last part of URL

I have this RedirecMatch
RedirectMatch 301 ^/en/products/(.*)/(.*)/(.*)$ https://www.example.com/en/collections/$2/
If I visit
https://www.example.com/en/products/sofas/greyson/greyson-sofa
I'm redirected to
https://www.example.com/en/collections/greyson/greyson-sofa
What I want is
https://www.example.com/en/collections/greyson/
How do I accomplish this?
There's nothing obvious in what you have posted that would produce the specific output you are seeing, however, there are other errors in the directives and you may be seeing a cached response. 301s are cached persistently by the browser, so any errors are also cached.
The Redirect directive is prefix-matching and everything after the match is copied onto the end of the target URL. So, the redirect you are seeing would be produced by a directive something like this:
Redirect 301 /en/products/sofas/greyson https://www.example.com/en/collections/sofas/greyson
When you request /en/products/sofas/greyson/greyson-sofa, the part after the match, ie. /greyson-sofa, is copied onto the end of the target URL to produce /en/collections/sofas/greyson/greyson-sofa
You can resolve most of these issues by reordering your rules (but also watch the trailing slashes). You need to have the most specific redirects first. RedirectMatch before Redirect. For example, take the following two redirects:
Redirect 301 /en/products/accessories https://www.example.com/en/products/complements/
Redirect 301 /en/products/accessories/bush/ https://www.example.com/en/collections/bush-on/
Since the Redirect directive is prefix-matching, a request for /en/products/accessories/bush/ will actually be caught by the first rule, not the second and end up redirecting to /en/products/complements//bush-on/ - note the erroneous double-slash (since you have a mismatch of trailing slashes on the source and target URLs.)
You need to reverse these two rules. (But also watch the trailing slash.)
The same applies to the Redirect directives that follow. You also have some duplication, ie. You have two rules for /en/products/chairs-and-bar-stools/piper/?

Prevent wildcard in htaccess 301 redirect

I have setup a htaccess 301 redirect to redirect an indexed page to a new page, however this is also acting as a wildcard redirect for child pages which I do no what to happen.
Old structure
example.com/faq
example.com/faq/question-1
example.com/faq/question-2
etc etc
New structure
example.com/faqs
example.com/faq/question-1
example.com/faq/question-2
etc etc
htaccess redirect in place :
Redirect 301 /faq/ https://example.com/faqs/
This is working with no issues to send /faq to /faqs however it is also sending /faq/* to /faqs/* which I do not want to happen.
For example going to example.com/faq/question-1 causes a to many redirects error and finally lands on example.com/faqs/question-1
Is there anything i can add to the single redirect line to prevent this happening, or is their a more complex use of RewriteRule I could use instead. Research into the matter initially seem to confirm that this should/would happen, and if it does what can be added to prevent it. After a prompt to the apache docs I can see why they would redirect as a wildcard.
After suggests from CBroe an implementation of using RedirectMatch worked.
RedirectMatch 301 ^/faq/$ https://example.com/faqs
This now redirects /faq to /faqs, however doesn't redirect /faq/question-1 to /faqs/question-1 etc

.htaccess rewriting URLs that don't exist

Currently, I'm working with some guys that love short URLs for marketing purposes when posting to social media.
They have https://www.example.com/folder/subfolder
For their marketing, they would like https://www.example.com/mysuperbuzzword which would point to the first URL but in the browser, you would still see the shorter URL.
My first thought was "I'll just add a rewrite rule in the .htaccess"
Something like Redirect 301 /mysuperbuzzword /folder/subfolder/ which would work but then the URL changes.
I did some reading and discovered the [P] flag. Then I tried this:
RewriteCond %{REQUEST_URI} ^/vanityurl
RewriteRule ^(.*)$ /folder/subfolder [P]
The issue I have now is that because /vanityurl doesn't exist, instead of rewriting, I just get a 404 error.
I've been testing my rule using a .htaccess rule checking tool and the URL it spits out looks correct, but again, I just get a 404.
Also, if you use the flag [PT] the resource is found but the URL is changed in the address bar.
You tested with a permanent redirect. Never do that. It is cached by the browser, and the browser will no longer do requests to the server. This is possible, because such a redirect is supposed to be... well... permanent. If you must test redirects, test them with a temporary redirect (302) and change them later if everything turns out to be fine.
With mod_rewrite you can do three things:
Do an internal rewrite. If you internally rewrite url a to url b, then the user sees url a, but url b is being executed on the server.
Do an external redirect. If you externally redirect url a to url b you send back a response: "Please request url b instead.". The browser then sends another request to the server with url b and changes the url in the address bar accordingly.
Do a proxy request. If you proxy url a to url b, the user requests url a. The server then opens a http connection and requests url b. It then waits for the response and channels that back to the client. It is very expensive to do such a thing via mod_rewrite.
What you simply want to do is:
RewriteRule ^vanityurl$ /folder/subfolder [L]
It as a simple internal rewrite.

Rewrite URL .htaccess - Apache server

On my website, I would rename the URL on address bar, from
domain.com/economy/article.php?id=00
to
domain.com/economy/id-name-article.html
I wrote this .htaccess file:
RewriteEngine On
RewriteRule ^([0-9]+)-([^\.]*)\.html$ http://domain.com/economy/article.php?id=$1 [L]
I have an anchor with this href: href="economy/id-name-article.html" and when I click on it, the server is redirected on article.php, it runs the script in the correct way and I can view the article, but on the address bar is still written domain.com/economy/article.php?id=00 instead domain.com/economy/id-name-article.html. Why?
This happens only on my online server, while locally it's all right.
The mod_rewrite module is issuing a redirect to your browser rather than transparently rewriting the url, causing you to see the new url in your browser.
Try removing the http://domain.com portion from your RewriteRule to see if it avoids the redirect to your browser by changing the rule to:
RewriteRule ^([0-9]+)-([^\.]*)\.html$ /economy/article.php?id=$1 [L]
If that fails, you could also use the proxy flag [P] to force apache to transparently fetch the page and return it to your users without the redirect. I don't recommend this approach since it can have security implications but it should work if the above doesn't.
EDIT: To clarify, rewriting the url with a fully-qualified domain rather than a relative uri tells apache that the redirect is on a different server, and therefore it doesn't know that the new url is accessible on the same host without redirecting the client.

Apache Mod_Rewrite - Redirect losing POST data - 405 error

Stackoverflow users,
I have an Apache application that needs to accept data POSTed to the following paths:
/sample/HostChange/Submit
/sample/HostChange/SubmittoAPI
I'm currently using the following 301 redirect rules. This is not what I want as as the POST gets redirected and the second request is a GET loosing all the data. I am seeing the 301 request go the correct url but the second request is a GET and causes a 405 response code.
.htaccess:
RewriteEngine On
Redirect 301 /sample/HostChange/Submit /event
Redirect 301 /sample/HostChange/SubmittoAPI /date
I'm sure using a Redirect is the issue. Can someone help me figure out the correct RewriteCondition I need to be using to redirect these POST hits to the new paths but keep the data being submitted to the application.
Thank you mucho.
I don't think you can redirect a POST (as a POST). Browsers just won't POST the data again.
You'd have to output some HTML with Javascript to make the browser rePOST the data to the new URL.
Or instead of redirecting, have some server-side code accept the POST data first and then dispatch it somehow (maybe be redirecting with an indentifying token in the URL) internally.
Or if the data is short, re-write the URL to include the data as query parameters.
Something along the lines of following should work, I'm not around an apache instance at the moment so regex is not tried but please check the rewrite log and see how it behaves.
RewriteEngine On
RewriteLog /var/log/httpd/rewrite.log
RewriteLogLevel 9
RewriteCond %{REQUEST_URI} /sample/HostChange/Submit
RewriteRule ^/sample/HostChange/Submit(.*) /event/$1 [P,L]
I some kind of the same problem, for me it helped not to really redirect the request, but to rewrite it. I don't now if this is applicable to your problem.
Here are the details and it worked for me:
PHP Rewrite url and preserve posted data