Replacing a portion of a query string in htaccess - .htaccess

I'm pretty green when it comes to rewriting URL's with htaccess, though I can do the basics.
In this case I have a series of query strings returned from a vendor to one of my scripts. That's all fine and dandy, except for when it includes a URL with 'http' or 'https' in it. When it detects that, Apache throws a 403 Forbidden error. I thought that I could craft a RewriteRule that would rewrite the 'http' portion of the query string into something could get past Apache's rules.
This will eventually be installed on a client's machine so I can't change any server settings.
An example URL would be:
http://mysite.com/gocardless_confirm.php?resource_uri=https%3A%2F%2Fsandbox.gocardless.com%2Fapi%2Fv1%2Fbills%2F07F56ERHRT
Here's the settings I was trying to use:
RewriteCond ${QUERY_STRING} ^(.*)$resource_uri=http^(.*)$
RewriteCond %{REQUEST_URI} ^gocardless_confirm.php
RewriteRule ^(.*)$ gocardless_confirm.php?$1resource_uri=hllp$2 [L]
How can I rewrite this portion so I can simply get to the script?
Thanks!

Try:
RewriteCond %{QUERY_STRING} ^(.*)resource_uri=http(.*)$
RewriteRule ^gocardless_confirm.php$ gocardless_confirm.php?%1resource_uri=hllp%2 [L]
Subpattern in RewriteCond are referenced %# in the RewriteRule.
^ is the begin of the hole string the pattern is matched against.
$ is matches its end.

Related

HTACCESS How to "cut" URL at one point

I am new to .htaccess and I don't understand it well. Recently I have built the following code:
RewriteEngine On
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /api/v2/
RewriteRule ^api/v2(.*) /api/v2/api.php?input=$1
This was in the root public folder (example.com/.htaccess). But now I have to create second Rewrite and I want to make .htaccess file in example.com/api/v2/ folder. I tried to remove /api/v2/ part in each Rewrite Rule, but only thing I got was error 500.
What I want to achieve:
If someone uses this link: https://example.com/api/v2/test/test/123, I'd like to make it into https://example.com/api/v2/api?input=test/test/123 with .htaccess located in example.com/api/v2 folder.
Addressing your existing rule first:
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /api/v2/
RewriteRule ^api/v2(.*) /api/v2/api.php?input=$1
The first RewriteCond (condition) is entirely superfluous and can simply be removed. The second condition simply asserts that there is a slash after the v2 and this can be merged with the RewritRule pattern. So, the above is equivalent to a single RewriteRule directive as follows:
RewriteRule ^api/v2(/.*) /api/v2/api.php?input=$1 [L]
This would internally rewrite the request from /api/v2/test/test/123 to /api/v2/api.php?input=/test/test/123 - note the slash prefix on the input URL parameter value.
However, unless you have another .htaccess file in a subdirectory that also contains mod_rewrite directives then this will create a rewrite loop (500 error).
Also note that you should probably include the L flag here to prevent the request being further rewritten (if you have other directives).
If someone uses this link: https://example.com/api/v2/test/test/123, I'd like to make it into https://example.com/api/v2/api?input=test/test/123 with .htaccess located in example.com/api/v2 folder.
I assume /api? is a typo and this should be /api.php?. Note also that the slash is omitted from the start of the URL parameter value (different to the rule above).
I tried to remove /api/v2/ part in each Rewrite Rule, but only thing I got was error 500.
This is the right idea, however, you need to be careful of rewrite loops (ie. 500 error response) since the rewritten URL is likely matching the regex you are trying to rewrite.
Try the following instead in the /api/v2/.htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_URI} !api\.php$
RewriteRule (.*) api.php?input=$1 [L]
The preceding RewriteCond directive checks that the request is not already for api.php, thus avoiding a rewrite loop, since the pattern .* will naturally match anything, including api.php itself.
You could avoid the additional condition by making the regex more specific. For example, if the requested URL-path cannot contain a dot then the above RewriteCond and RewriteRule directives can be written as a single directive:
RewriteRule ^([^.]*)$ api.php?input=$1 [L]
The regex [^.]* matches anything except a dot, so avoids matching api.php.
Alternatively, only match the characters that are permitted. For example, lowercase a-z, digits and slashes (which naturally excludes the dot), which covers your test string test/test/123:
RewriteRule ^([a-z0-9/]*)$ api.php?input=$1 [L]
Or, if there should always be 3 path segments, /<letters>/<letters>/<digits>, then be specific:
RewriteRule ^([a-z]+/[a-z]+/\d+)$ api.php?input=$1 [L]

.htaccess url rewriting and redirect 301

At the moment we have one page which shows a list of links
each link has got its own ID number
each link gets opened with the file info.php?ID=X
for example:
www.mysite.com/info.php?ID=1 shows the link "weather italy"
www.mysite.com/info.php?ID=2 shows the link "weather france"
Since we have several links for "weather italy" and "weather france" we would like to rewrite new urls (weather-italy and weather-france) in .htacces
Whith the new urls we would have the folowing structure:
www.mysite.com/weather-italy/info.php?ID=1
www.mysite.com/weather-france/info.php?ID=2
With the following code we tell the server to rewrite the urls and call the original file:
RewriteRule ^weather-italy/info.php?$ info.php [NC,L]
RewriteRule ^weather-france/info.php?$ info.php [NC,L]
This works fine.
To avoid double indexing we want to redirect 301 the old link to the new link.
We have achieved that with the following code:
RewriteCond %{THE_REQUEST} \?ID=1
RewriteRule ^info\.php$ http://www.touristinfo.fr/weather-italy/info\.php [L,R=301]
RewriteCond %{THE_REQUEST} \?ID=2
RewriteRule ^info\.php$ http://www.touristinfo.fr/weather-france/info\.php [L,R=301]
This also does the job but combined with the first part of the script is produces a never ending loop.
What is wrong with our code?
Thanks a lot for your help :)
%{THE_REQUEST} is supposed to only match if the url you want to match is an external request. Your problem is that the regex you made is not specific enough.
Let's examine what happens. You go to example.com/info.php?ID=2. The first two rules don't match, but the 4th one does. You end up with a redirect to example.com/weather-france/info.php?ID=2.
This goes through your .htaccess again. The second rule matches, and internally rewrites it to info.php?ID=2. The [L] flag doesn't make a difference here, because the url will be pulled through .htaccess until it stops changing. On the second cycle through .htaccess, the url will now match the 4th rule, even though the external request contained /weather-france/info.php?ID=2. ID=2 is in the external request too, and the internal rewrite is now info.php again.
The fix is to make %{THE_REQUEST} match enough so that the rewritten url doesn't match it anymore.
On a further note: Familiar yourself with the difference between regex and strings in RewriteRules and RewriteConds. You escaped a dot in a string, while leaving a dot in a regex unescaped. The ? is "match the previous character 0 or 1 times", not a question mark literal. The query string cannot be matched in the first argument of RewriteRule.
You'll end up with:
RewriteRule ^weather-italy/info\.php$ info.php [NC,L]
RewriteRule ^weather-france/info\.php$ info.php [NC,L]
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /info\.php\?ID=1
RewriteRule ^info\.php$ http://example.com/weather-italy/info.php [L,R]
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /info\.php\?ID=2
RewriteRule ^info\.php$ http://example.com/weather-france/info.php [L,R]

.htaccess not working even though other rules work

I am trying to do a redirect to another site. The following rule works perfectly for all the other rules within my .htacces but the following rule does not seem to work and i can'r figure out why, after lots of try and error.
RewriteCond %{HTTP_HOST} ^www.oldexample.com$
RewriteRule ^folder3/page.php?value=(.*)$ http://newexample.com/folder1/page.php?value=$1 [L,R=301,NC]
I tried the following which redirected but without the value within (.*) added
RewriteCond %{HTTP_HOST} ^www.oldexample.com$
RewriteRule ^folder3/page.php?(.*)$ http://newexample.com/folder1/page.php?$1 [L,R=301,NC]
Could this be an issue with the = symbbol? I tried escaping it and escaping the . also but to no avail
You can't match against the query string (everything after the ?) in a rewrite rule, you need to use a RewriteCond and match against the %{QUERY_STRING}. However, it looks like you're just trying to pass the query string along, unchanged. So you don't need to mess with any of it:
RewriteCond %{HTTP_HOST} ^www.oldexample.com$
RewriteRule ^folder3/page.php$ http://newexample.com/folder1/page.php [L,R=301,NC]
The query string will get appended automatically. You need to make sure this rule is above any routing rules as it needs to take place before any internal rewrites.

htaccess rewrite querystring and remove empty value

first, sorry for my bad English.
I try to rewrite url generated from Form Get and redirect that.
my url is like this:
http://www.mysite.com/properties?action=search&agreement=for-rent&category=my-category&type=&zone=my-zone&city=my-city
and I have this .htaccess configured:
11. RewriteCond %{QUERY_STRING} ^action=(?:[a-zA-Z\-]*)&(?:.*)=([a-zA-Z\-]*)&(?:.*)=([a-zA-Z\-]*)&(?:.*)=([a-zA-Z\-]*)&(?:.*)=([a-zA-Z\-]*)&(?:.*)=([a-zA-Z\-]*)$
12. RewriteRule (.*) %{REQUEST_URI}/%1/%2/%3/%4/%5/? [R=301,L]
So basically all my request are direct to index.php.
21. RewriteCond %{REQUEST_URI} !index\.php|resources|hidden
22. RewriteRule ^(.*)$ index.php/$1 [L]
All works, but the problem is when I have an empty value in query string, the rule add double slash and the above url (for example whit &type=&zone=my-zone... type have empty value) will translate like that:
http://www.mysite.com/for-rent/my-category//my-zone/my-city/
The question is: How can i remove in .htaccess the double slash generated if i have one or more empty value in query string?
Thanks
Easiest is to do another redirect (not real pretty as it requires two 301's).
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301,L]
The fun part is that when the url is loaded with a double slash in it, mod_rewrite will automatically remove this. So as you can see above you'll just have to rewrite the url to itself, kind of.

htaccess ReWriteCond ReWriteRule - redirect occurs even when URL includes nonsense characters

We've just finished a major re-structuring our website and I'm trying to write a set of redirect rules of varying specificity. The redirects are half working:
They correctly re-route old URLs
They incorrectly also allow and re-route URLs that include text not specified in the
ReWriteCond statements (when instead I would expect to see a "Not Found" error message displayed in the browser.)
Statements in the .htaccess file (located in the root of the web site) include:
RewriteBase /
RewriteCond %{REQUEST_URI} /company/company-history.html
RewriteRule (.*)$ http://www.technofrolics.com/about/index.html
RewriteCond %{REQUEST_URI} /press
RewriteRule (.*)$ http://www.technofrolics.com/gallery/index.html
The above correctly executes the desired redirect
but also works when I enter the following after the domain name:
/youcanenteranytext/hereatall/anditstillworks/press
In other words, any text following the domain and preceding the conditional string seems to be allowed/ignored. Any advise on how to restrict the condition or rewrite rule to prevent this would be much appreciated!
Thanks, Margarita
You need to including bounds in your regular expressions when you try to match against %{REQUEST_URI}, the ^ indicates the beginning of the match.
RewriteCond %{REQUEST_URI} ^/company/company-history\.html
Will make it so requests for /garbage/stuff/comapny/company-history.html won't match. And likewise:
RewriteCond %{REQUEST_URI} ^/press
Will make it so requests for /youcanenteranytext/hereatall/anditstillworks/press won't match. You can additionally employ the $ in your regular expression to indicate the end of the match, so something like this:
RewriteCond %{REQUEST_URI} ^/press$
Will ONLY match requests for /press and not /something/press or /press/somethingelse or /press/.

Resources