I have Apache and want to implicitly redirect http request to a file.
That is, when a user hits http://example.com/foo/bar, I wish a user to see a content on .xml file under /some/folder/file.xml and at the same time a user must see http://example.com/foo/bar in the address bar.
Redirect instruction in httpd.conf makes a URL being changed once it gets redirected, but I want to keep the URL same.
Try this.
RewriteEngine on
RewriteRule "/foo/bar$" "/some/folder/file.xml" [PT]
you can even specify mime-type.
RewriteRule "/foo/bar$" "/some/folder/file.xml" [PT,H=application/xml]
You need internal remapping.
Related
Been trying to play with mod_rewrite through .htaccess in one Xampp virtualhost, but I am not getting the results that I am looking for.
What I am tring to do is to rewrite the following: www.example.com/name/billy.html to: www.example.com/billy
Without trying to rewrite the URLs the virtualhost is working fine, I have access to all pages. However, when I add the .htaccess with the corresponding rewrite rule I get a 404 page not found. The regex is working as expected though. I see that the request to www.example.com/name/billy.html it's been rewritten to www.example.com/billy, but the page doesn't load.
The name folder exists in the file structure and the .htaccess is inside the example folder.
Currently, my vh configuration looks like this:
<VirtualHost *:80>
DocumentRoot "/Applications/XAMPP/xamppfiles/htdocs/example"
ServerName www.example.com
<Directory "/Applications/XAMPP/xamppfiles/htdocs/example">
Options Indexes FollowSymLinks ExecCGI Includes
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
And this is the content of the .htaccess file:
RewriteEngine On
RewriteRule ^name\/([a-z]+).html$ /$1 [L,NC,R]
What is missing?
What I am tring to do is to rewrite the following: www.example.com/name/billy.html to: www.example.com/billy
You seem to have the process the wrong way round and possibly mixing up "rewrites" and "redirects"?
You should be internally rewriting from the visible "friendly" URL to the underlying file-path that actually handles the request. You are trying to do the opposite here. How is your system expected to handle a request for /billy? (It doesn't, and generates a 404.)
You may be thinking you can change the URL using .htaccess (mod_rewrite) alone? But no, that is not how this works.
RewriteRule ^name\/([a-z]+).html$ /$1 [L,NC,R]
You mention "rewrite", but this directive is in fact a "redirect" (as indicated by the R flag). Specifically, a 302 (temporary) redirect in this instance.
(You might actually want to implement a redirect like this, if you are changing an existing URL structure, but more on that later*1)
A URL "rewrite" is entirely internal to the server. The user only sees the public URL, they do not see the URL that it might be rewritten to. You (the user) can't "see" a rewrite.
A "redirect" on the other hand, usually refers to an external redirect, ie. a 3xx response sent back to the client with an instruction to make a new request to a different URL. The URL being redirected to is visible to the user. This is used when content has moved to a different URL.
So, following your example, you should be requesting/linking to (in your HTML source) the short/friendly URL /billy and internally rewriting the request to /name/billy.html that actually handles the request.
For example:
RewriteEngine On
# Rewrite from "billy" to "name/billy.html"
RewriteRule ^[a-z]+$ name/$0.html [NC,L]
The $0 backreference contains the entire URL-path that is matched by the RewriteRule pattern.
Only use the NC flag if you do need to match uppercase letters as well. But a request for /Billy won't serve /name/billy.html on a case-sensitive OS.
And that's really it, with regards to the URL-rewritting, you can stop reading here.
*1 Redirect from old to new
Regarding the external "redirect" mentioned above. You might choose to implement a redirect (in the opposite direction) if you are changing an existing URL structure and the old URLs have been indexed by search engines and/or linked (or bookmarked) to by external third parties - in order to preserve SEO and keep users happy.
For example, say your original URLs were of the form /name/billy.html and you later decided to change your URLs to /billy instead. You first change the URLs in the HTML source and implement the "rewrite" as mentioned above so the new URLs now work. You then might implement an external redirect from the old /name/billy.html URL to the new /billy URL.
For this, you would use a directive like you had initially, except you have to be careful of redirect-loops because you are already rewriting the request in the opposite directive. You only want to redirect "direct/initial" requests and not rewritten requests by the earlier rewrite (that is actually later in the file). An easy way to check for "direct" requests is to check against the REDIRECT_STATUS environment variable, which is empty on the initial request and set to 200 (as in 200 OK status) when the request is rewritten.
For example, the following "redirect" would go before the above "rewrite", immediately after the RewriteEngine directive:
# Redirect from "name/billy.html" to "/billy"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^name/([a-z]+)\.html$ /$1 [R=301,NC,L]
This should ultimately be a 301 (permanent) redirect since the URL has presumably changed permanently. However, always test with 302 (temporary) redirects to avoid potential caching issues.
Further reading:
Reference: mod_rewrite, URL rewriting and "pretty links" explained
By using the following .htaccess
RewriteEngine On
RewriteRule ^([0-9]+)/([0-9]+)$ /api/web/index.html#$1/$2 [R=301,NC,L]
When user types the following URL at their browser.
http://localhost:8080/1/2
I'm expecting, Apache will perform internal redirection, and change the displayed URL at browser too (through R=301).
http://localhost:8080/api/web/index.html#1/2
Changing the displayed URL at browser is important. This is to ensure index.html's JavaScript can parse the url correctly.
However, what I really get is
http://localhost:8082/api/web/index.html%231/2
I will get Apache error.
Apache false thought that, I wish to fetch a file named 2 located in directory api/web/index.html%231/
Is there anything I can solve this through modifying .htaccess only?
The # is getting encoded as %23. Try using the NE flag in your rule:
RewriteRule ^([0-9]+)/([0-9]+)$ /api/web/index.html#$1/$2 [R=301,NC,L,NE]
the NE flag tells mod_rewrite not to encode the URI.
I have a site that's coded mainly in PHP, but I'm trying to rewrite my dynamic php URL's into static HTML URL's.
But I want the address bar to still remain as the static HTML link.
I'm trying to accomplish this through .htaccess (I have no access to httpd.conf as I'm hosted on a shared account). Here is what's written in my .httaccess file:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule ^inventory-search-([^.]+)-by-([^.]+).html$ http://www.pianostudiosandshowcase.com/inventory.php?search=$1&by=$2 [R]
But I can't get the address bar to remain as the static HTML link.
Here is a link to show you what I mean:
http://www.pianostudiosandshowcase.com/inventory.php?search=manufacturer&by=1
What am I missing?
You need to remove both the R flag in your rewrite rule as well as the protocol/domain name:
RewriteRule ^inventory-search-([^.]+)-by-([^.]+).html$ /inventory.php?search=$1&by=$2 [L]
Both will cause the server to externally redirect the browser, telling it "what you were looking for is not at that URL, you need to go to this entirely different URL". The forces the browser to display the new location in its address bar.
If you internally rewrite it, the browser has no idea the URI that it sent as a request had been changed, therefore the address bar remains unchanged.
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.
Is the following possible?
A user requests the url http://example1.com/example.php and the apache opens http:// example1.com/example.php?id=1
A user requests the url http://example2.com/example.php and the apache opens http:// example2.com/example.php?id=2
But the user should not see the id in his browser adress bar (the user should only see http://example1.com/example.php or http://example2.com/example.php).
You can say the id is invisible for the user but transfered to the example.php.
How can I implement this?
Is that the correct solution?
RewriteEngine On
RewriteRule ^/example.php http://example1.com/example.php$1 [P]
ProxyPassReverse /example.php?id=1 http:// example1.com/example.php
RewriteEngine On
RewriteRule ^/example.php http://example2.com/example.php$1 [P]
ProxyPassReverse /example.php?id=2 http:// example2.com/example.php
You have to understand several concept.
Once the server received the user requested url he can do several things
Take the requested path from the url and use it without modifications. That's the default solution
Map the requested path to any other physical path, things that can be done via Alias, AliasMatch or RewriteRules.
Map the requested path to another website while hiding the fact thtat another website is requested. That's the proxy solution, thta mod_proxy or mod_rewrite could handle (but you do not need that)
Redirect the user to another path, sending him a new url to use, making another client/server roundtrip, with Redirect instructions or mod_rewrite (the swiss knife). But you do no need that.
So you want a server-side only remapping of the requested path.
Let,s say we will use mod rewrite to make this mapping. If you check all tags available in RewriteRule (summary here) the interesting ones are:
passthrough|PT : Forces the resulting URI to be passed back to the URL mapping engine for processing of other URI-to-filename translators, such as Alias or Redirect.
qsappend|QSA: Appends any query string from the original request URL to any query string created in the rewrite target
last|L: Stop the rewriting process immediately and don't apply any more rules. Especially note caveats for per-directory and .htaccess context (see also the END flag)
nocase|NC: Makes the pattern comparison case-insensitive.
details on the PT flag shows that:
The target (or substitution string) in a RewriteRule is assumed to be a file path, by default.
Well, that,s maybe enough for you. But using PT is a good thing, if you have other apache configusation elements you should try to let them apply after mod_rewrite job.
So... assuming you may need to handle some query strings arguments and that this id argument is based on the domain name in the request, and that only the example.php script needs this behavior; you should start your research with such rules (untested):
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example1.com$ [nocase]
RewriteRule ^example\.php$ example.php?id=1 [passthrough,qsappend,last]
RewriteCond %{HTTP_HOST} ^example2.com$ [nocase]
RewriteRule ^example\.php$ example.php?id=2 [passthrough,qsappend,last]