rewriting URLs from .json to .php - mod-rewrite

I want http://server/path/app.json?a=foo&b=bar to map to http://server/path/foo.php?a=foo&b=bar using mod_rewrite. I have the following incantation in my .htaccess which doesn't give any joy
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php$2 [L]
Suggestions?
Update: Adding rewrite.log and error.log output (comments don't allow formatting)
I get the following in the rewrite.log
strip per-dir prefix: /Users/user/Sites/dir/app.json -> app.json
applying pattern '^([^.?]+).json(.*)$' to uri 'app.json'
rewrite 'app.json' -> 'app.php'
add per-dir prefix: app.php -> /Users/user/Sites/dir/app.php
internal redirect with /Users/user/Sites/dir/app.php [INTERNAL REDIRECT]
and the apache server log says
The requested URL /Users/user/Sites/dir/app.php was not found on this server.

If I read your question correctly you want:
http://server/path/app.json?a=foo&b=bar
Going to:
http://server/path/foo.php?a=foo&b=bar
Sowhen you capture (app).json $1 is app and $2 is your second parenthesis, it's ... nothing (the part between json and the ?). As everything after the question mark is the QUERY STRING and cannot be captured here. Your rewriteRule is working on the requested file, not on the QUERY STRING. So you didn't captured foo anywhere. For the QUERY_STRING you could use the [QSA] flag on the rewriteRule, that would simply append a=foo&b=bar after your rewrite.
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php$2 [L]
Here you tell apache to reuse $1 (the filename without .json), so app.json will get redirected to app.php, not foo.php.
RewriteEngine On
RewriteRule ^([^.?]+).json(.*)$ $1.php [L,QSA]
Will redirect app.json?a=b&z=r to app.php?a=b&z=r.
Now if you really need to capture foo as the first QUERY_STRING parameter the rule will become harder. But you could do it like that (here instead of the first parameter I detect the parameter 'a=' and capture his value in %4):
RewriteCond %{QUERY_STRING} (.*)(^|&|%26|%20)a(=|%3D)([^&]+)(.*)$
RewriteRule ^([^.?]+).json$ %4.php? [L,QSA]

Related

Replace key-value pair in query string with Apache2

I am trying to set a simple replacement in my URL query strings.
I have an absolute path in my query string I would like to be replaced by a custom string.
FROM http://acme.com/a/path?file=DIR/this.file&foo=2
TO http://acme.com/a/path?file=/long/absolute/path/to/this.file&foo=2
These are my directives:
# [sudo a2enmod rewrite]
RewriteCond %{QUERY_STRING} ^(.*)file=DIR(.*)$
RewriteRule ^/a/path /a/path?%1file=/long/absolute/path/to%2
With such a configuration, replacement does not work, DIR passes through.
I configured a LogLevel to trace1 in my Apache2 configuration but I get nothing in my access.log and no useful feedback in error.log.
The question is:
References:
https://wiki.apache.org/httpd/RewriteQueryString
https://httpd.apache.org/docs/current/rewrite/remapping.html
This works for me(I've added flags R and L):
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)file=DIR(.*)$
RewriteRule ^/a/path /a/path?%1file=/long/absolute/path/to%2 [R,L]
See also https://httpd.apache.org/docs/2.4/rewrite/flags.html

What's up with this simple mod-rewrite rule?

As part of Google's approach to crawling AJAX-populated content, I've got the following in a .htaccess file:
RewriteEngine on
#snapshot requests
RewriteCond %{QUERY_STRING} _escaped_fragment_=([^&]+)
RewriteRule ^.*$ system/snapshot_mode.php?project=%1
I trigger the rule with a URL like
http://myserver.co.uk/?_escaped_fragment_=token
...but it fails to go to the page specified. It does, however, if I remove the query string part of the redirect, i.e. change it to
RewriteRule ^.*$ system/snapshot_mode.php
What's up with that?
[EDIT]
I added a [R-302] to the rule and it now tries to redirect me to the script BUT via a mangled, local machine filepath, i.e.
http://localhost/C:/xampp/htdocs/docula/system/snapshot_mode.php?project=token
...and gives me a 403 access denied error.
Try this:
RewriteEngine on
RewriteCond %{QUERY_STRING} _escaped_fragment_=([^&]+)
RewriteRule ^.*$ system/snapshot_mode.php?project=%1 [L,QSA]
RewriteRules and Query String:
By default, a RewriteRule does not change the query string. Therefore, QueryString is not required in the RewriteRule. If you are not adding a parameter to the replacement URL, RewriteRule passes on the incoming query string unchanged.
If you are adding new parameters, the original query string will be discarded and the rewritten URL will get only the new parameters.
If you want to combine the original query string and the new parameters, you can append it using the Query String Append [QSA] flag.
In your code, you have a new parameter project=%1 without the [QSA] flag and therefore the _escaped_fragment_=([^&]+) parameter is discarded, making the RewriteCondition fail.
Also Note:
[R-302] is incorrect syntax. It should be [R=302]
[QSD] - Query String Discard flag is not something we would want in this case.

mod_rewrite: transform = and & in slashes

I was just looking for a solution to transform any =,?,& found in a query string into a simple slash /.
To be more specific, my link is something like:
http://www.mydomain.com/product.php?c=1&sc=12&products_id=15
and I would it like this:
http://www.mydomain.com/product.php/c/1/sc/12/products_id/15
whatever the master page could be (in this case is product.php, but it could be foo.php, bar.php...or else).
I have googled a lot but didn't find any good solution to achieve what i'm looking for.
I have found complex rewrite rules, but they all include the "page name" into them:
i.e.
RewriteRule ^/?index/([^/]+)/([^/]+)$ /index.php?foo=$1&bar=$2 [L,QSA]
That rule is only applicable to index.php and to known variables like foo, bar.
I need a more general one, whatever the master page is, whatever the variables are.
Can this be done?
Any suggestion?
Thanks
I assume you're using apache >= 2.2. Add this to your apache conf:
<IfModule mod_rewrite.c>
RewriteEngine On
# you absolutely need to use RewriteBase if this snippet is in .htaccess
# if the .htaccess file is located in a subdirectory, use
# RewriteBase /path/to/subdir
RewriteBase /
RewriteCond %{QUERY_STRING} ^(=|&)*([^=&]+)(=|&)?(.*?)=*$
RewriteRule ^(.*)$ $1/%2?%4= [N,NE]
RewriteCond %{QUERY_STRING} ^=$
RewriteRule ^(.*)$ $1? [R,L]
</IfModule>
The first RewriteCond/RewriteRule pair repeatedly matches a token delimited by & or = and adds it to the path. The important flag is the [N] that causes the whole ruleset to start over again, as often as the rule matches. Additionally, a = is appended to the end of the query string. This is to create a mark in the URL that at least one rewrite has happened.
The second ruleset checks for the = mark that remains after the URL has been rewritten completely and issues a redirect.
Have a look at http://wiki.apache.org/httpd/RewriteQueryString for some useful hints.

Need help removing part of filename from url with mod_rewrite

I'm trying to reformat my url to be a bit shorter. Right now the links end up as this: website.com/image?id=name.jpg
What I want to have the link come out as is m.website.com/name, without the file exension or image.php file in the url. I figure mod_rewrite is the way to do it, so any help will be greatly appreciated.
In order to make it so someone accessing the URL http://m.website.com/name gets served the content for http://website.com/image?id=name.jpg, you first need to check the hostname for m.website.com, then match the name part of the URI. Using that match, you can proxy the request (using a [P]) or, if both website.com and m.website.com are hosted on the same server, just simply internally rewrite. Try putting this in your .htaccess file in your document root:
RewriteEngine on
# check the host (NC = no case)
RewriteCond %{HTTP_HOST} ^m\.website\.com$ [NC]
# don't rewrite /image
RewriteCond %{REQUEST_URI} !^/image
# Match the first non-slash word and rewrite
RewriteRule ^([^/]+)$ /image?id=$1 [L]
This will rewrite http://m.website.com/name to /image?id=name.jpg, but it will not rewrite http://m.website.com/path/name. If you want paths (and everything else) to be included in the id parameter, change the ([^/]+) to (.*) in the RewriteRule.

Problem redirect CodeIgniter URLs to WWW

I have a CI application that uses .htaccess for URL routing. My basic setup is as follow:
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
These rules are pretty standard for CI apps. They rewrite all URLs (except for those in the exception list) to the index.php front controller. The lines above also hide index.php, as it would normally appear as part of every URL.
So far, so good. Everything works just fine. Now, for the sake of SEO I would like to force all traffic to www. So I extended the rules as follow:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
rewritecond %{http_host} ^jungledragon.com [nc]
rewriterule ^(.*)$ http://www.jungledragon.com/$1 [r=301,nc]
These last two lines rewrite http://jungledragon.com/anything URLs to http://www.jungledragon.com/anything URLs. This kind of works, but it brings back the index.php part back: http://jungledragon.com/anything becomes http://www.jungledragon.com/index.php/anything.
How exactly do I combine these rules so that they do not interfere with each other? I tried doing the WWW rewrite before the CI rules. That shows an Apache 301 page with an error, rather than doing the actual redirect.
Additionally, I would like to also include rules to get rid of trailing slashes, but for now let's keep the question simple. Note that I did find useful post here and elsewhere yet for some reason I still can't find the correct exact syntax for my situation.
Edit: Thanks for the help. This works:
Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^jungledragon.com [nc]
rewriterule ^(.*)$ http://www.jungledragon.com/$1 [r=301,nc,L]
RewriteRule ^$ /var/www/html/ferdy/jungledragon/index.php [L]
RewriteCond $1 !^(index\.php|images|img|css|js|swf|type|themes|robots\.txt|favicon\.ico|sitemap\.xml)
RewriteRule ^(.*)$ /var/www/html/ferdy/jungledragon/index.php/$1 [L]
mod_rewrite processes rules in a linear fashion. Rules at the top of the file are processed first.
The [nc] and [L] at the end of the rules are the options for how to process rules.
nc - nocase: case insensative
L - last: last rule in the execution (if you hit this, stop processing)
You need to put your www redirect rules above your CI rules so it will first add the www, THEN apply the CI rules to the newly re-written url. **And also use either the C or N flag with your www redirect rule so it will parse the next rule.
http://mysite.com/blah ==becomes==> http://www.mysite.com/blah ==becomes==> http://www.mysite.com/index.php/blah (Executed, not redirected)
What's happening currently is:
http://mysite.com/blah ==becomes==> http://mysite.com/index.php/blah (STOP)
Browser goes to http://mysite.com/index.php/blah and a second re-write pass is done since your exceptions stop /index.php urls from being processed
http://mysite.com/index.php/blah ==becomes==> http://www.mysite.com/index.php/blah (Redirected)
As Suggested, here is a link to mod_rewrite's documentation if you want to look further.
#LazyOne: Brainfart, sorry.
Here's an excerpt from the docs outlining the flags you'll probably need:
'chain|C' (chained with next rule)
This flag chains the current rule with the next rule (which itself can be chained with the following rule, and so on). This has the following effect: if a rule matches, then processing continues as usual - the flag has no effect. If the rule does not match, then all following chained rules are skipped. For instance, it can be used to remove the .www'' part, inside a per-directory rule set, when you let an external redirect happen (where the.www'' part should not occur!).
'next|N' (next round)
Re-run the rewriting process (starting again with the first rewriting rule). This time, the URL to match is no longer the original URL, but rather the URL returned by the last rewriting rule. This corresponds to the Perl next command or the continue command in C. Use this flag to restart the rewriting process - to immediately go to the top of the loop.
Be careful not to create an infinite loop!
'nocase|NC' (no case)
This makes the Pattern case-insensitive, ignoring difference between 'A-Z' and 'a-z' when Pattern is matched against the current URL.
'noescape|NE' (no URI escaping of output)
This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', '%24', and '%3B', respectively); this flag prevents this from happening. This allows percent symbols to appear in the output, as in

Resources