.htaccess rewrite url with letters öäå and passing variables - php

Lets say survey name is test.
When completing form it redirects to
www.example.com/survey_thank_you.php?survey_name=test
then rewrites it to www.example.com/test/thank_you and it works as inteded.
But because here we use öäå the issue emerge. If survey name is testä, it redirects allright but rewrites it to
www.example.com/test%25C3%25A4/thank_you (this works)
and it should rewrite to www.example.com/testä/thank_you
also if go straight to www.example.com/testä/thank_you it works.
htaccess:
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
AddCharset UTF-8 .php
AddDefaultCharset utf-8
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=(.*)/?$
RewriteRule ^survey_thank_you\.php$ /%1/thank_you [R,L,QSD]
RewriteRule ^(.*)/thank_you$ survey_thank_you.php?survey_name=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(.*)/?$ survey_form.php?survey_name=$1 [L,NC,QSA]
If i change (.*) to ([0-9a-zA-Z]+) it rewrites it allright /testä/thank_you but then i get error 404. Any suggestions much appreciated.

test%25C3%25A4 would be the result of double URL encoding. One level decoded, leaves test%C3%A4.
You can use the NE flag to try and avoid double encoding in this place, https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_ne

Related

htaccess doesn't work as expected

I have an htaccess rewrite URL as below:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.mywebsite.com$ [NC]
RewriteRule ^(.*)$ http://mywebsite.com/$1 [R=301,L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^my-page\.html$ /my-page.php [L]
RewriteRule ^my-page/([^/]*)\.html$ /level1.php?num=$1 [L]
RewriteRule ^my-page/([^/]*)/([^/]*)\.html$ /level2.php?level1=$1&level2=$2 [L]
RewriteRule ^([^/]*)\.html$ /level3.php?level3=$1 [L]
These rules above rewrite URLs from mywebsite.com/my-page.php to mywebsite.com/my-page.html.
Now, what I want to achieve is mywebsite.com/my-page/ to be redirected to mywebsite.com/my-page.php (which in turn rewrites to mywebsite.com/my-page.html).
What I have tried, I created a directory "my-page" and tried to redirect requests from mywebsite.com/my-page/ to /my-page.html.
I don't know what went wrong. I can see in the network tab that a request is made to /my-page/ and gets rewritten to mywebsite.com/my-page.htmlmy-page/, which gives a 302 Status ☹
Please help! Thank you.
You can try use RedirectMatch to achieve this.
Redirect to my-page.php:
RedirectMatch 301 ^/my-page/ http://mywebsite.com/my-page.php
or straight away to my-page.html if this is your goal:
RedirectMatch 301 ^/my-page/ http://mywebsite.com/my-page.html
or, what will be best - change the code responsible for mywebsite.com/my-page.htmlmy-page/, but I can't see it in question you have asked :)
Please give the following a try. Brief descriptions are found in the comments for each section.
RewriteEngine On
# Trim www.
RewriteCond %{HTTP_HOST} ^www\.mywebsite\.com$ [NC]
RewriteRule ^(.*)$ http://mywebsite.com/$1 [R=301,L]
RewriteBase /
# Redirect /my-page[/] to /my-page.html
# >> Note: change 302 to 301 to make permanent
RewriteRule ^my-page/?$ my-page.html [R=302,L]
# Allow existing files and directories
# Recommended to comment out the first line
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite *.html to respective page
RewriteRule ^my-page.html$ my-page.php [L]
RewriteRule ^my-page/([^/]*).html$ level1.php?num=$1 [L]
RewriteRule ^my-page/([^/]*)/([^/]*).html$ level2.php?level1=$1&level2=$2 [L]
RewriteRule ^([^/]*).html$ level3.php?level3=$1 [L]
The important part here is that you do the required redirect before any other rewrites (except the www. removal).
Also, you previously had the two conditions which stated that if the request was not for a file or directory, then proceed with the next rule, but that wouldn't have accounted for the last two rules. As such, this version tells Apache to stop everything if the request is for an existing file or directory. I would recommend, for security purposes, that you comment out the line that checks for existing directories.

Change ugly query string to a prettier /path/to/page/ pattern

I have a site which uses a custom query string to deliver pages to the visitor. A sample query string looks like /?sec=news&pg=current&bg=203. I'd like to use .htaccess to rewrite the strings into a pattern like /news/current/203.
I know how to take the /news/current/203 URL and make it into a query string that I can parse with PHP. I typically use this bit of htaccess code:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*) /index.php?id=$1 [L]```
And my PHP then explodes id on the / and off we are running.
My question is this... How can I add a few more lines to this htaccess code that will allow the old URL query pattern to continue to work for people that have bookmarks or links that use the /?sec=news... pattern? Basically, it seems like I need to take this old query string and combine the values into one string that I can pass to index.php in the id parameter. I don't want to lose the ability to honor the old pattern, but also need to promote the new cleaner path-based string.
I know there is some regex that can help here, but I am terrible at understanding regular expressions. Any help would be appreciated, and let me know if I am not making any sense.
Update: The answer provided makes my final htaccess file look like this...
RewriteEngine on
# Prevent directory listings
Options All -Indexes
# Rewrite to www
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^sample.com[nc]
RewriteRule ^(.*)$ http://www.sample.com/$1 [r=301,nc]
# WHEN DONE TESTING< CHANGE ALL 302 to 301 !!!
# Honor the old format /index.php?sec=XXX&pg=XXX&bg=XXX and turn it into the new format
RewriteCond %{QUERY_STRING} sec=(\w+)&pg=(\w+)&bg=(\d+)
RewriteRule ^(.*)$ /%1/%2/%3? [R=302,L]
# Turn /path/to/page into index.php?id=path/to/page
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*) /index.php?id=$1 [L]
Add this rule
RewriteCond %{QUERY_STRING} sec=(\w+)&pg=(\w+)&bg=(\d+)
RewriteRule ^(.*)$ /%1/%2/%3? [R=302,L]
Change 302 to 301

htaccess: RewriteCond matched what is in tester unmatched

I have another problem about mod_rewrite. If user wants image (.png, .jpe?g, .gif at end of uri) then redirect to index1.html, otherwise index2.html. Tester (http://htaccess.madewithlove.be/) doesn't match uri without .png,jpe?g,.gif as within what is correct, but my localhost does and that is the problem.
Corrent example:
Input:
localhost/image.png
Output
localhost/index1.html
Input:
localhost/image
Output
localhost/index2.html
But what my localhost really do:
Input:
localhost/image.png
Output
localhost/index2.html
Input:
localhost/image
Output
localhost/index2.html
My htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^(.*)(.png|.jpe?g|.gif)$
RewriteRule ^(.*)$ index2.html
RewriteCond %{REQUEST_URI} ^(.*)(.png|.jpe?g|.gif)$
RewriteRule ^(.*)$ index1.html
Can you help? Thanks.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} (?!.*?\.png|.*?\.jpe?g|.*?\.gif)^(.*?)$
RewriteRule ^(.*)$ index2.html
RewriteCond %{REQUEST_URI} (?=.*?\.png|.*?\.jpe?g|.*?\.gif)^(.*?)(.png|.jpe?g|.gif)$
RewriteRule ^(.*)$ index1.html
Try this.Added a lookahead.Postive for .png and negative for no .png .
Have it this way:
RewriteEngine On
RewriteBase /
RewriteRule \.(png|jpe?g|gif)$ index1.html [L,NC,R]
RewriteRule !^(index[12]\.html|[^.]+\.(png|jpe?g|gif))$ index2.html [L,NC,R]
You're ridiculously abusing RewriteCond. Simplify it to:
RewriteEngine On
RewriteBase /
RewriteRule (\.png|\.jpe?g|\.gif)$ index2.html [L,R=303]
RewriteRule !^index[12]\.html$ index1.html [L,R=303]
The [L] modifier ('Last') ensures no further rules are processed, eliminating the need for a check in the second rule. The [R=303] makes it a 303 (See Other) redirect - alter the HTTP status code if needed.

mod_rewrite and hyperlinks with spaces

So I'm no .htaccess expert, by no means, but I have managed to put this code together for a webiste I'm making:
Options -Indexes +Includes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^\.htaccess$ - [F]
RewriteRule ^$ /%{ENV:BASE}/index.php?id=home
RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]
</IfModule>
It basically changes www.example.com/some/dir/index.php?id=home to www.example.com/some/dir/home while the first few rules are creating some kind of relative path value so I don't have to change the RewriteBase everytime I change the base folder (this is important for this project!).
It works perfectly fine, but now I have encountered a problem where there have to be spaces in the URL like www.example.com/some dir/sub folder/home and this messes everything up.
If you click a link on the page (e.g. "href="home"") it redirects to www.example.com/home instead of www.example.com/some dir/sub folder/home with a 404 error, obviously (even though it works if there are no spaces!). I found out if right click > "copy link to clipboard" it becomes the encoded version www.example.com/some%20dir/sub%20folder/home even if it shows the decoded version in the address bar. BUT if you manually type the decoded version www.example.com/some dir/sub folder/home it still works fine.
There seems to be a problem with spaces and encoding. How do I get my hyperlinks working properly?
-- EDIT --
Thanks to the tutorial posted by elcodedocle, I simply added backslash space: ^([a-zA-Z0-9/ ]*)$ to the regex in the last rule, even if it's not the best method. Then I noticed the [L] flag in the second last rule. I removed it because this shouldn't be the last rule (don't know why it was there in the first place...) and now it works! Well, kind of...
Now, If there is a trailing slash at the end of the URL it sill doesn't work anymore. Probabply because of the removal of the [L] flag in the rule but I don't know how to fix this...
Have your .htaccess like this:
Options -Indexes +Includes -MultiViews
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ %{ENV:BASE}$1 [R=302,L,NE]
RewriteRule ^\.htaccess$ - [F]
RewriteRule ^$ /%{ENV:BASE}/index.php?id=home [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+?)/?$ %{ENV:BASE}index.php?id=$1 [QSA,L]
</IfModule>
This is working fine under all the test cases you have described in your question like handling spaces, trailing slashes etc.
Try changing:
RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]
to
RewriteRule ^([a-zA-Z0-9%]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]
(It's a wild guess but it's the only one of your rules that has problems with %)
[EDIT] Unencoded spaces are not allowed in URIs. The ban on spaces is enforced by all browsers as they will convert every space to %20 before sending the request via the http protocol. A workaround to handle them in mod_rewrite is described on this tutorial:
Since URLs can't have spaces (except as %20), use underlines or
hyphens to replace them. If you ABSOLUTELY have to use spaces (%20) in
your URIs, you can include them in your regex within a range
definition as {space}, i.e., ([a-zA-Z\ ]+). However, this is NOT
advised.
[EDIT2] If that doesn't work, you may have to translate %20 into spaces, then apply the other rules. Here is a hack based on this answer you may try:
sedspace.sh:
#!/bin/sh
sed -u 's/%20/ /g'
.htaccess:
...
RewriteMap sed-space prg:sedspace.sh
RewriteRule ^(.*)$ ${sed-space:$1}
...
(Make sure that sedspace.sh is executable)

Clean URL redirection htaccess

i have a website SongsBar.com , when a query is searched on my website, the url in the browser displays like this - http://songsbar.com/download.php?q={search text}.
i want it be appear like this http://songsbar.com/download/{search text}.html
.htaccess
RewriteEngine On
RewriteRule ^download/([^/]*)\.html$ /download.php?q=$1 [L]
First, you need to make sure Multiviews (mod_negotiation) is turned off, otherwise it'll mess with the /download/ and /download.php stuff.
Then you need to externally redirect requests for download.php
Then you need to internally rewrite the /download/ requests back to the php file (the browser is oblivious to this happening.
Options -Multiviews
RewriteEngine On
RewriteCond %{THE_REQUEST} \ /+download.php\?q=([^&\ ]+)
RewriteRule ^ /download/%1.html? [L,R=301,NE]
RewriteRule ^download/(.+)\.html$ /download.php?q=$1 [L,B,QSA]
The B flag may not be necessary. It depends on what kind of stuff you plan on putting in the parameter. The flag ensures that special characters get encoded.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
Something like : RewriteCond %{REQUEST_FILENAME}
You can achieve this with something along the lines of:
RewriteEngine On
RewriteBase /download/
RewriteCond %{REQUEST_FILENAME} !-f #if the file actually exists don't rewrite
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.html$ /download.php?q=$1 [L]

Categories