Problems with mod_rewrite and GET - regex

So, I had a question earlier about mod_rewrite which you find here mod_rewrite changing /subpage/ to /subpage
But now I have a whole new problem with this... How do I make GET work?
Like if I need to pass some variables with GET, ex: mypage.com/subpage/?name=Jamie
My mod_rewrite looks like this:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^([A-Za-z0-9-]+)/?$ ?p=$1 [L]
I understand that the problem probably has to do with that I already pass and rewrite one GET request. So how do i tweak this to accept any other GET-request i might need to process?
UPDATE:
To clarify the problem a bit. If I try the url mypage.com/subpage/?name=Jamie page loads as if i used url mypage.com/subpage/ and "name" is never passed. Using my original url mypage.com?p=subpage&name=Jamie works as it should.
I guess i need to tweak this somehow... but how?
Thank you for taking your time reading my probably easy question!

Use the QSA flag — Query String Append:
RewriteRule ^([A-Za-z0-9-]+)/?$ ?p=$1 [L,QSA]
'qsappend|QSA' (query string append)
This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule.

try
RewriteRule ^([A-Za-z0-9-]+)/\?$ ?p=$1 [L]
as '?' is a meta character in regex, it needs to be escaped

Related

htaccess match after ~ and pass as url parameter

i want rewrite my url with htaccess. So, i want for example that
https://sample.com/~X6y2
has a match and it passes all behind the '~' as parameter to https://sample.com/req.php?id=[here]
is it possible with the '~'-character? so, if not, i need an alternative. Maybe '#'-Charakter, like tiktok.
So, it should match e.g.
https://sample.com/~AZaz09,
https://sample.com/~0123
but not
https://sample.com/0123,
https://sample.com/AZaz09,
https://sample.com/XY/~Z1234,...
I've tried several regex but nothing has provided the desired function :(
Best of these is (but not working, idk why):
RewriteEngine on
RewriteRule ^.*\/[\~]([a-z][^.]*)$ req.php?id=$1 [NC,L]
I'm new to regex and htaccess, so it's a bit difficult for me. I would be grateful if someone would provide a working htaccess including regex. Thx ✌🏼️
You want this solution
Check this solution
Demo: https://regex101.com/r/GJPZym/1
After a lot of trying, I've found a solution that is workin just fine.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*[\~]([A-Za-z0-9_-]*)$ req.php?id=$1 [L,NC]
where ~ can be replaced with anything u want :)

Apache Rewrite to remove index.php?

I am trying to rewrite my URL's to remove index.php? but I'm struggling a little to get it to work. The closest I can get is the answer here: remove question mark from 301 redirect using htaccess when the user enters the old URL
I need to convert the URLs to pretty URLs on the way out, and rewrite them back to the proper URL on the way in. The structure of the URLs is as follows:
https://sub.domain.com/index.php?/folder1/folder2-etc
Using the code from the referenced answer results in a double forward slash:
https://sub.domain.com//folder1/folder2-etc
The rewrite rules I'm using from the referenced answer are:
RewriteEngine On
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php$ /$1 [L,R=301,NC,NE]
RewriteCond %{THE_REQUEST} \s/+\?([^\s&]+) [NC]
RewriteRule ^ /%1? [R=301,L]
# internal forward from pretty URL to actual one
RewriteRule ^((?!web/)[^/.]+)/?$ /index.php?$1 [L,QSA,NC]
I suspect I know how to solve the first bit, but I'm struggling to understand the second rule for the internal forward.
Additionally, I'm wondering if this is the best way to do this. I'm currently running an Apache backend behind an Nginx reverse proxy. Would I be better doing the rewrite on the Nginx side and the internal forward on Apache?
EDIT:
Complication: I've noticed an additional structure to complicate things. Some URLs appear to have https://sub.domain.com/picture.php?/folder1/folder2-etc
For these, I'd be quite happy to keep 'picture' and just remove the .php? bit.
I'm guessing that for the first bit, Id need to do something like the following:
RewriteCond %{THE_REQUEST} \s/+index\.php\?/([^\s&]+) [NC]
RewriteRule ^ /%1? [R=301,L]
RewriteCond %{THE_REQUEST} \s/+picture\.php\?/([^\s&]+) [NC]
RewriteRule ^(.*)$ /picture/%1 [R=301,L]
But have no idea where to start with the opposite.... ie converting pretty urls back to standard. It would help if the following section could be explained to me?
^((?!web/)[^/.]+)/?$ /index.php?$1 [L,QSA,NC]
RewriteRule ^/*picture/(.*)$ /picture.php?/$1 [L]
RewriteRule ^/*(?!/*index\.php$)(.*)$ /index.php?/$1 [L]
should do the trick. I wasn't able to test it yet though.
I only used the [L] last flag to stop applying rules on match. The QSA query string append flag doesn't seem to make sense as you don't seem to use ?key=value&... syntax anyway. Also dunno if you actually need the NC case-insensitive flag...
Side note:
I hope your php files don't serve paths with .. in them, as that would allow people to read arbitrary files from disk, e.g. /picture/../../../etc/passwd
Apologies, but as it turns out, the main reason I can't get anything to work is due to the use of relative URLs and dynamically generated links within the PHP. Not something I can change unfortunately. The not perfect URLs are something I'm going to have to live with. For reference, the app I'm using is Piwigo

URL Regex for Apache Mod Rewrite

I have been trying to work the regex out for this for a while now and I am struggling. Was hoping someone could help.
I have a website using apache mod_rewrite converting directories into get variables to 1 level. I am wanting to change this or add a seperate rule for the following
example.com/portfolio/plugins/jquery-tester
becoming
example.com/portfolio/handler.php?area=plugins&item=jquery-tester
I am trying to currently build up on php live regex but coming up trumps.
Try this:
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/portfolio/(.+)/(.+)$ /portfolio/handler.php?area=$1&item=$2 [L]
Having the handler in the same directory as what you're matching can cause potential problems though (that's why the RewriteCond is there to check so you don't end up with an infinite loop).
If you have other rewrite rules, you may need to check that there aren't any conflicts.
RewriteRule ^/portfolio/[a-zA-Z\-_]+/[a-zA-Z\-_]+$ /portfolio/handler.php?area=$1&item=$2 [L]

Rewrite URL, regex help

I am using the following Rewrite URL:
RewriteRule /([^/?.]+) /somedir/somefile.aspx\?Name=$1 [NC,L]
which works great for my use, but I need to restrict it to only act on text that does not contain a filename... for example, if I use the url www.somedomain.com/SomeName it works fine, but it also fires if I use www.somedomain.com/TestPage.aspx
So I am not sure if I need an additional Rewtire rule, or if the current one can be modified to disallow any text with an extension, for example.
Any help with this regular expression would be greatly appreciated.
try adding this before the rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
this condition check if the file requested exists and returns true if it doesn't (as it's negated with a !).
if you need not to fire the rule also for the directories, then add also this line:
RewriteCond %{REQUEST_FILENAME} !-d

Is there a better way to do this regex?

I finally figured out a good/easy way to make clean URLs with regex on my site in this format below, however it will require a very large .htaccess file, I know from the post on here that it is supposed to not be to bad on performance to use mod_rewrite but I have never really seen it used where the way I am, with a seperate entry for almost every page of my site.
Below is an example of an entry, there is 2 entries for 1 page, the first entry re-writes
http://www.example.com/users/online/friends/
to
http://www.example.com/index.php?p=users.online.friends
It works great but if the user is not on the first page then there is another thing added to the URL for paging and I had to write another entry to rewrite when this happens, is this the correct way or should these be combined somehow?
RewriteRule ^users/online/friends/*$ ./index.php?p=users.online.friends&s=8
RewriteRule ^users/online/friends/(\d+)/*$ ./index.php?p=users.online.friends&s=8&page=$1
The second one would do this
http://www.example.com/users/online/friends/22/
to
http://www.example.com/index.php?p=users.online.friends&page=22
It depends what you think is more readable, but here's how you could do it with a single rule:
RewriteRule ^users/online/friends(/(\d+))?/*$ ./index.php?p=users.online.friends&s=8&page=$2
(Edited to be more faithful to treatment of trailing slash in original question. Was: RewriteRule ^users/online/friends/((\d+)/*)?$ ./index.php?p=users.online.friends&s=8&page=$2)
Here I've just put "(...)?" around the final part of the url to make it an optional match, and changed the backreference to $2.
Of course, this actually rewrites http://www.domain.com/users/online/friends/ as:
http://www.domain.com/index.php?p=users.online.friends&page=
So your PHP code would have to check whether the page parameter is non-empty.
Yes, that's fine. I guess they could be combined into a single rule but there's not really any need.
You might consider leaving page as part of the URL so instead of:
http://www.domain.com/users/online/friends/22/
just have:
http://www.domain.com/users/online/friends?page=22
and then have one rule something like:
RewriteRule ^users/online/friends/?$ ./index.php?p=users.online.friends&s=8 [L,QSA]
to append the query string
Edit: There are a couple of ways of reducing the number of rewrite rules you have.
Firstly, use wildcards in the search terms, like:
RewriteRule ^users/(\w+)/(\w+)$ /index.php?p=users.$1.$2 [L,QSA]
will reduce quite a number of rules.
Secondly, if you're passing everything through /index.php just consider delegating all requests there:
RewriteRule ^(users/*)$ /index.php/$1 [L,QSA]
That rule uses a third technique: instead of passing the path information via a query string parameter, pass it via the extra path info. That can be accessed via $_SERVER['PATH_INFO'].
That being said, lots of rules isn't necessarily bad. At least it's explicit about all your actions. The thing you have to watch out for is creating a maintenance nightmare however.
# Initial step
RewriteCond %{QUERY_STRING} !(?:^|&)p=
RewriteRule ^([^/]+)/(.+) /$2?p=$1 [QSA]
# Subsequent steps
RewriteCond %{QUERY_STRING} ((?:[^&]*&)*?)p=([^&]*)(.*)
RewriteRule ^([^/]+)/(.+) /$2?%1p=%2.$1%3
# Last step with page number
RewriteRule ^(\d+)/?$ /index.php?page=$1 [QSA,L]
# Last step without page number
RewriteCond %{QUERY_STRING} (?:((?:[^&]*&)*?)p=([^&]*))?(.*)
RewriteRule ^([^/]+)/?$ /index.php?%1p=%2.$1%3 [L]
This would rewrite the URL in several steps:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/online/friends/22/?p=users
http://www.domain.com/friends/22/?p=users.online
http://www.domain.com/22/?p=users.online.friends
http://www.domain.com/index.php?p=users.online.friends&page=22
An easier method would be the following, but would require you to change your scripts:
RewriteRule ^(.*?)(?:/(\d+))?/?$ /index.php?p=$1&page=$2 [QSA,L]
It would do everything in one step, with a little difference:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/index.php?p=users/online/friends&page=22
Adding the s=8 query argument would require more work:
Creating a text-file with the menu numbers for each page.
Adding a RewriteMap directive.
Changing the second-last rule to use the same RewriteCond as the last rule has.
Adding &s=%{menumap:%2|0} to the last two rules.