Understanding difference between redirect and rewrite .htaccess - apache

I'd like to understand the difference between redirecting and rewriting a URL using .htaccess.
So here's an example: Say I have a link like www.abc.com/ index.php?page=product_types&cat=88 (call this the "original" url)
But when the user types in abc.com/shoes (let's call this the "desired" url), they need to see the contents of the above link. To accomplish this, I would do this:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule ^(.*)shoes(.*)$ index.php?page=product_types&cat=88
Nothing wrong with this code and it does the trick. However, if I type in the original url in the address bar, the content comes up, but the url does not change. So it remains as www.abc.com/index.php?page=product_types&cat=88
But what if I wanted the desired url (/shoes) to show up in the address bar if I typed in www.abc.com/ index.php?page=product_types&cat=88? How would this be accomplished using .htaccess? Am I running into a potential loop?

Some of the explanation can be found here: https://stackoverflow.com/a/11711948/851273
The gist is that a rewrite happens solely on the server, the client (browser) is blind to it. The browser sends a request and gets content, it is none the wiser to what happened on the server in order to serve the request.
A redirect is a server response to a request, that tells the client (browser) to submit a new request. The browser asks for a url, this url is what's in the location bar, the server gets that request and responds with a redirect, the browser gets the response and loads the URL in the server's response. The URL in the location bar is now the new URL and the browser sends a request for the new URL.
Simply rewriting internally on the server does absolutely nothing to URLs in the wild. If google or reddit or whatever site has a link to www.abc.com/index.php?page=product_types&cat=88, your internal server rewrite rule does absolutely nothing to that, nor to anyone who clicks on that link, or any client that happens to request that URL for any reason whatsoever. All the rewrite rule does is internally change something that contains shoes to /index.php?page=product_types&cat=88 within the server.
If you want make it so a request is made for the index.php page with all of the query strings, you can tell the client (browser) to redirect to the nicer looking URL. You need to be careful because rewrite rules loop and your redirect will be internally rewritten which will cause a redirect which will be internally rewritten, etc.. causing a loop and will throw a 500 Server Error. So you can match specifically to the request itself:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\?page=product_types&cat=88
RewriteRule ^/?index.php$ /shoes [L,R=301]
This should only be used to make it so links in the wild get pointed to the right place. You must ensure that your content is generating the correct links. That means everything on your site is using the /shoes link instead of the /index.php?page=product_types&cat=88 link.

Related

mod_rewrite, redirect and set a cookie, preventing redirection loop

i´m stuck here now for hours... any help will be appreciated!
What I need to do:
There is a application where in need to "protect". This means that I need to show a "disclaimer" page, which is not part of the protected application itself, but under the very same domain/server. This disclaimer page needs to be shown to every visitor every 8 hours.
My concept:
In Apache, on every request, check if there is a specific cookie "intercepted" present.
If there is a cookie, just process the requested url without any changes.
If there is no cookie, and the url is not catch.html, redirect to /catch.html?intercepted_url={requerst_uri_with_params}. in same step, set the cookie.
The browser will set the cookie, follow the redirection and load the catch.html (the cookie is present already), the user will see a disclaimer on this page.
On catch.html, using JavaScript, the cookie "intercepted" will be updated with a lifespan of 8 hours
On catch.html, using JavaScript, a link will be rendered, pointing to the intercepted url.
User will click the created link and issue an new request to the previously intercepted request
GOTO: 1
What I´ve tried so far:
Apache Configuration:
# Exclude the catch destination in order to prevent a redirect loop
RewriteCond %{REQUEST_URI} !/catch.html
# Check if the cookie "intercepted" is missing
RewriteCond %{HTTP_COOKIE} !intercepted
# Redirect and append the original url as request parameter, preserving params, and setting the cookie
RewriteRule ^(.*)$ /catch.html?intercepted_url=$1 [QSA,R=301,CO=intercepted:TRUE:%{HTTP_HOST}]
Current Outcome:
Opening http://local.example.com/foo/bar/baz.html?a=b&x=z&1=2 results i a redirection, as expected, OK
Retrying the first url should now pass, as the cookie is set, but no, im´m stuck on the disclaimer page :(
Any ideas how to fix this? Thank you all in advance!
the concept works as expected. the redirection is executed as described but the browser had cached the redirection as it was a permanent one (301). the solution was to use a temporarily redirection (302).
i've ended up to store also the intercepted url in the cookie in order to keep the url clean. but i did not managed to set the livetime of the cookie with the redirection. there seems to be no way to calculate it within the rewrite rule.
i have used some javascript to rewrite the cookie on the catch page.

htaccess redirect url with anchor tag

I am trying to redirect a URL to a page with an anchor tag. The redirect works but how do I keep the original URL after the redirect rather than the redirected one.
I want to redirect www.example.com/caves/ to www.example.com/trips.html#caves.
When I redirect I get the URL www.example.com/trips.html#caves but want it to keep www.example.com/caves/.
I have spent ages looking for answers but no luck, any help would be appreciated
Here is my code in htaccess
RewriteEngine on
RewriteRule ^Caves/(.*) /trips.html#Caves [NE,L,R]
I doubt it can be done. Anchor is a client side directive and you can't "hide" it with server side rewrite (the browser can't jump to anchor if it doesn't see one), so the anchor has to be in address bar URL.
...how do I keep the original URL after the redirect rather than the redirected one.
You want an internal rewrite, as opposed to an external redirect - which is what you are currently doing with the use of the R (redirect) flag on the RewriteRule.
RewriteRule ^Caves/(.*) /trips.html#Caves [NE,L,R]
Ordinarily you could simply remove the R flag to keep the original URL in the address bar. The request is internally rewritten to /trips.html.
However, the fragment identifier (ie. #Caves - or strictly everything after the #) is lost. The request is rewritten to /trips.html, not /trips.html#Caves. The fragment identifier is evaluated by the client, not the server and is no doubt being used by your client-side JavaScript to display the appropriate content. Because of the internal rewrite, the client-side JavaScript never gets to see the fragment identifier.
However, if you are internally rewriting the request (ie. /Caves/ is still present in the address bar) then your client-side code doesn't need the #Caves fragment identifier. It can simply look at the original URL, ie. /Caves/ instead. But this will require a small change to your client-side code.
(Aside... Note that you are using Caves (capital first letter) in your code, but referring to caves (all lowercase) in your description. The directive you have written is case-sensitive, so it should be /Caves/, not /caves/ in your description?)

How to hide part of a URL from clients using htaccess?

I'm working on a website running on an Apache server. The PHP factory makes and takes URLs that look like this:
site.com/page/view/[id]/[vanity-url]
However, the client wants to hide part of the URL from view, so in the browser it appears as:
site.com/[vanity-url]
The server still needs to see the full URL.
I've tried various RewriteRules after hours of searching, and the closest I seem to have come is:
RewriteRule ^page/view/(.*)/(.*)$ /$2 [R,L]
...but that doesn't seem to be doing anything. I know for sure that my .htacces is working.
What am I doing wrong?
Unfortunately, this isn't possible. Let me explain why:
You state that the server needs to see the full URL. Specifically, this includes the id segment, which I am sure your framework needs (it wouln't need it if the server only needs to see the vanity segment). The code you have provided redirects the full URL to the vanity URL, thus making the full URL invisible to the server for the next request.
So, navigating to /page/view/2/about-us would redirect to /about-us, and the address bar would change to reflect that. This causes a new request to be sent to the server, containing only the /about-us vanity URL.
As a result, you would need to rewrite the vanity URL back to the full URL (without redirecting, so that the /about-us stays in the address bar as-is), but you wouldn't be able to do this, as the vanity URL does not contain the id segment, which seems to be a requirement for the framework to serve the correct response. Keep in mind that Apache cannot guess the ID for that particular vanity URL.

Manipulate user's address bar with mod_rewrite

I have a page at example.com/themizer.php, but I want it to appear that it's actually located at example.com/themizer/ (or example.com/themizer/index.php) for all practical purposes. I know how to basically make an alias for it with mod_rewrite, but how do I make it appear that users are being redirected to that alias? Example: a user requests example.com/themizer.php and the address in their browser turns into example.com/themizer/ without actually redirecting. Is this possible?
With server-sided configuration, you can only accomplish this with a redirect. This does not necessarily need to be a problem. Just make sure that the urls on your site point to the fancy url and not to the internal url. Otherwise you generate a lot of requests that have to be redirected, instead of just redirecting the odd request that came in in an other way (e.g. through an external old url or old bookmark). You do it like this:
#External redirect
RewriteCond %{THE_REQUEST} ^GET\ /themizer\.php\ HTTP
RewriteRule ^themizer\.php$ /themizer/ [R,L]
#Internal rewrite
RewriteRule ^themizer/?$ themizer.php [L]
If you really must, you can use javascript to 'push' a new window state into the history, updating the address bar. This causes the "go to previous page" button in your browser to contain bogus though. In other words: Going to the previous page does not work as expected, which I would not recommend since there is a better option available. You can do it with the following javascript statement in browsers that support it:
window.history.pushState( null, document.title, "/themizer" );

Apache mod_rewrite/mod_proxy - re-write last part of URI as query string?

We have a web resource that can be accessed with a URL/URL of the form:
http://[host1]:[port1]/aaa/bbb.ccc?param1=xxx&param2=yyy...
However, we are working with an external (i.e., not developed by us, so not under our control, i.e., we can't change it) client app that is attempting to access our resource with a URL that looks like:
http://[host2]/[port2]/ddd/fff/param1=xxx&param2=yyy...
In other words, the client is including the "query string" (the ?param1=xxx&param2=yyy... part) as if it's part of the URI, instead of as a proper query string.
We have a separate Apache proxy instance, and we're thinking that we could use that with some RewriteCond/RewriteRule to take the incoming requests (the ones with the query string at the end of the "URI", and without the "?") and rewrite the URI to a "proper" URI with a "proper" query string and then use that modified/re-written URI to access our resource via proxy.
We'd also like to do that without having an HTTP re-direct (e.g., 30x) going back to the client, because it appears that they may not be able to handle such a re-direct.
I've been trying various things, but I'm not that familiar with Apache mod_rewrite, so I was wondering if someone could tell me (1) if this is possible and (2) suggest what RewriteCond/RewriteRule would accomplish this?
P.S. I have gotten some progress. The following re-writes the URL correctly, but when I test, I'm seeing a 302 redirect to the re-written URL, instead of Apache just proxying immediately to the re-written URL. Is it possible to do this without the re-direct (302)?
<Location /test/users/>
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/(.*)/param1=
RewriteRule ^/(.*)/param1=(.*) http://192.168.0.xxx:yyyy/aaa/bbbbb.ccc?base=param1=$2
</Location>
Thanks, Jim