I'm trying to redirect my content removing the .php extension from all the files using this .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
and when I try to include any other redirect like this one give me a 404 error:
RewriteRule ^create/(.*)$ ./create.php?app=$1
I'm trying to use something like https://myurl.com/create/37744e17-98ff-58a9-8996-7cf746e508b9 instead of https://myurl.com/create.php?id=37744e17-98ff-58a9-8996-7cf746e508b9, but looks like the start of my .htaccess it's giving the main issue, there's a way to solve this?
You've not stated where you are putting that rule. It would need to go first. The order is important.
Try it like this instead:
# Disable MultiViews
Options -MultiViews
RewriteEngine On
RewriteRule ^create/([a-f0-9-]+)$ create.php?id=$1 [L]
# General extensionless ".php" URLs
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
Note that you used an id URL parameter in your example, but used app in your rule? I've changed this to id.
Based on your example URL, the id URL parameter can consist of the characters a-z, 0-9 and hyphens only.
The RewriteBase directive is not required. The ./ prefix on the substitution string is not required and should be removed.
In your original rule that appends the file extension there is no need to check that the request does not map to a directory before checking that it does map to a file (with a .php extension). You were also potentially checking a different file-path to the one being rewritten to.
Note that you need to ensure that MultiViews is disabled, otherwise create.php is called but without the URL parameter.
Related
I currently have a CRUD that has the following file structure:
The index.php file redirects to the add-product.php, delete.php and other files. The problem is, the URL looks like: myapp.com/resources/views/add-product but I want it to look like myapp.com/add-product. I found other StackOverflow posts similar to this, but it redirects to the desired link, instead of redirecting to the correct link but showing the desired one, and because of that the site doesn't work ("The requested URL was not found on this server"). The .htaccess file looks like this:
Options +FollowSymLinks +MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
RewriteRule ^resources/(.*)$ /$1 [L,NC,R]
I'm also using the file to be able to remove the .php from the URLs. The last line is the one handling the wrong redirection. How can I go about this? Thank you for your time.
You may use it like this:
Options +FollowSymLinks +MultiViews
RewriteEngine On
RewriteBase /myapp/
# external redirect to remove /resources/views/ from URLs
RewriteRule ^resources/views/(.+)\.php$ $1 [L,NC,R=302]
# internal rewrite to add /resources/views/ and .php to show content
RewriteCond %{DOCUMENT_ROOT}/myapp/resources/views/$1.php -f
RewriteRule ^(.+?)/?$ resources/views/$1.php [END]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.
I'm new to .htaccess and I've been working on a site where I have used URL slugs. Everything is working perfectly fine with slugs that have hyphens in them, but I get 404 error when I have a one word slug.
https://www.example.com/blog/example-blog works fine but https://www.example.com/blog/example throws a 404 error.
Below is the .htaccess code I'm currently using:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^([a-z]+)\/?$ $1.php [NC]
RewriteRule ^([a-zA-Z0-9-]+)\/?$ index.php?url=$1 [NC]
RewriteRule ^([a-zA-Z0-9-]+)\/season\/([0-9]+)\/?$ index.php?url=$1&season=$2 [NC]
</IfModule>
I've searched everywhere on Search Engine but got no luck. Any help is highly appreciated.
Summary:
I'm looking for ways for .htaccess to accept a slug without a hyphen as those with hyphens are working fine.
RewriteRule ^([a-z]+)\/?$ $1.php [NC]
This rule will catch the request /example and unconditionally rewrites it to example.php. Whereas /example-blog (with a hyphen) is ignored by this rule (because the regex ^([a-z]+)\/?$ does not match).
If this rule is required then add an additional condition that checks for the existence of the .php file before rewriting (otherwise this rule should be removed altogether). For example:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([a-z]+)/?$ $1.php [NC,L]
Now, only requests that actually map to .php files are rewritten.
UPDATE:
I've added the L flag to the above rule, although it will still work without.
So, in summary, your complete set of rules should look like this:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([a-z]+)/?$ $1.php [NC,L]
RewriteRule ^([a-zA-Z0-9-]+)/?$ index.php?url=$1 [L]
RewriteRule ^([a-zA-Z0-9-]+)/season/([0-9]+)/?$ index.php?url=$1&season=$2 [L]
There's no need to backslash-escape slashes in the regex, so I've removed the unnecessary backslashes. The NC flag is superfluous on the last two rules since you are already matching a-zA-Z in the RewriteRule pattern. And I've added the L flag, since you want processing to stop after the rewrite.
The <IfModule> container is also not required.
I'm creating an htaccess with which I want to achieve 3 things:
remove trailing slash
redirect all requests that aren't css, ico, jpg, js, php or png files to index.php
redirect all files to view.php if the query string doesn't begin with a
At the moment it looks like this
RewriteEngine On
RewriteBase /test/
RewriteRule ^(.*)/$ $1 [N] # remove trailing slash
RewriteCond %{REQUEST_URI} !\.(css|ico|jpg|js|php|png)$ # if it isn't one of the files
RewriteRule . "index.php" [L] # then redirect to index
RewriteCond %{QUERY_STRING} !^a($|&) # if query doesn't start with a
RewriteRule . "view.php" [L] # then redirect to view
This way, the following test cases should be true:
http://127.0.0.1/test/contact -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact/ -> http://127.0.0.1/test/index.php
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a
When I try these out on this site, it shows me exactly these results.In practice, however, when I'm trying out URLs, It completely breaks:
http://127.0.0.1/test/contact -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact/ -> Error 500
http://127.0.0.1/test/contact.png -> http://127.0.0.1/test/view.php
http://127.0.0.1/test/contact.png?a -> http://127.0.0.1/test/contact.png?a
It seems as if the script always looks at the query-related part first, although with that in mind, it still doesn't make much sense to me that /contact/ breaks. When I remove the query-related part though, the rest does work.
Did I forget about something? Is there a rule concerning the order of operation that I'm not aware of? Did I make a typo?
All input is appreciated!
P.S. I know that I will have to add a query that starts with an a for all local images, stylesheets, scripts and AJAX-calls. I'm doing this so that when people view media in a separate tab, I can create a fancy page around it, allowing people to navigate through all the media that is publicly present on the server.
Issues with your code:
First all non-css/js/image requests are routed to index.php and then anything without ?a is routed to view.php so eventually index.php won't be used at all. You need to use a negated condition in last rule for anything that doesn't have .php extension..
mod_rewrite syntax doesn't allow inline comments.
You need R flag in first rule to change URL in browser.
You can use this code in /test/.htaccess:
RewriteEngine On
RewriteBase /test/
# if not a directory then remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,NE,R=301]
RewriteCond %{REQUEST_URI} !\.(css|ico|jpe?g|js|php|png)$
RewriteRule . index.php [L]
RewriteCond %{QUERY_STRING} !(^|&)a [NC]
RewriteRule !\.php$ view.php [L,NC]
I'm in desperate need of a quick tip.
Trying to use htaccess to change this not so lovely url
http://localhost/test/index.php?page=Article&articleID=61
to
http://localhost/test/article/2015-09-21-this-is-the-headline
From what I've gathered I need to send the last part to a php script which can then get the matching id from the database. Knowing that I should be able to send the user to the original url up top.
RewriteRule ^(.*)\/article\/(.*)$ redirect/article.php [L]
# RewriteRule ^(.*)$ index.php
As of right now I'm not passing the information to the script yet. redirect/article.php only contains a print statement to let me know once I get that far.
However, despite my brain and every regex debugger saying otherwise, it won't match the url provided in the second code box. All I'm getting is the good old 404. If I activate the second rule it is applied to my url, telling me that the first one is simply being skipped.
What am I missing?
.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
# rename individual pages
RewriteRule ^(.*)\/article\/(.*)$ redirect/article.php [L]
# RewriteRule ^(.*)$ index.php
# resize images
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.)*\/([0-9]+)\-(([0-9]|[a-z])+)\.(prev)$ filePreview.php?id=$2&size=$3 [L]
php_value upload_max_filesize 20M
php_value post_max_size 21M
</IfModule>
The location of a .htaccess file informs how you must list paths for mod_rewrite. Inside .htaccess, paths for RewriteRule are not received with a leading /. Since yours was residing in /test, the (.*) at the start of your rule wasn't matching anything and harmless. Since that was followed by /, the article/ path was expecting a / it would never receive. The simplest fix is to change this rule to match article at the start via:
RewriteRule ^article/(.*) redirect/article.php [L]
Assuming you'll use that as a lookup in the PHP script, add a parameter to use the $1 captured pattern like:
RewriteRule ^article/(.*) redirect/article.php?article=$1 [L]
I believe it might be a possible duplicate. But I tried my best to search for such a thing that will suit my needs and I found, none.
So here's basically what I have so far, and I will explain what I need modified.
# Forbidden Access
ErrorDocument 403 /403.php
# Not Found
ErrorDocument 404 /404.php
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
</IfModule>
<IfModule mod_rewrite.c>
# Strip off .php extension if it exists
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L,NC]
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ /403.php$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]
</IfModule>
Now this seems to be working flawlessly. But it has one error. Let me explain first.
1) It does automatically strip-off .php extension if it exists. Not sure if it strip off .php if it is url of an external request. Forgot to check, but maybe you already know so you can tell me ?
2) When I type this... "http://website.dev/img/" it does give me an "403 Forbidden Access". So that's all good.
3) When I try this... "http://website.dev/index" it does load the page even if there is .php extension manually added it will strip it off. So All good in here too...
4) When I try random path like this... "http://website.dev/asdasd" it does give me an "404 Not Found". So we're good in here as well.
But the main problem is here...
5) When I try following... "http://website.dev/dashboard/index" it give me an 404 Not Found even tho it should be loading without issues. It appears for all pages within dashboard directory.
Can you help me to modify that htaccess above please ? I am really tired of searching and I don't know regex at all.
That is because of the faulty regex used in your very last rule to silently add .php extension. Change last rule to:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}\.php -f [NC]
RewriteRule ^(.+?)/?$ /$1.php [L]
Here's my translation of you rules:
# Strip off .php extension if it exists
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
Bad comment. You regexp means: strip off all files that have 3 uppercase first and and dot php in it. Maybe you've forgotten the ending $?
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ /403.php$1 [R=301,L]
Why is that? Just do a redirect, and Apache will handle the 301 it for you:
RewriteRule .* - [L,R=403]
And then last question: why you strip off .php extension, if you re-add it later on? (°_o)
So here's what you should do, with some examples, and adapt them you fit your needs:
First test if the file has no special treatment. If so, stop immediately, like this:
RewriteRule ^/(robots\.txt|404\.php|403\.php)$ -
Then test if someone is trying to hack. If so, redirect to whatever you want:
RewriteRule (.*)test.php - [QSA,L]
RewriteRule (.*)setup.php http://noobs.land.com/ [NC,R,L]
RewriteRule (.*)admin(.*) http://noobs.land.com/ [NC,R,L]
RewriteRule (.*)trackback(.*) http://noobs.land.com/ [NC,R,L]
Then, only after this, forbid the php extension:
RewriteRule (.*)php$ - [L,R=404]
Then, accept all static "known" file extension, and stop if it matches:
RewriteRule (.*)(\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico|mpg|mp3|ogg|wav|otf|eot|svg|ttf|woff)){1}$ $1$2 [QSA,L]
Now you can do some testing. If the URI ends with a 'aabb/', test if you have a file named aabb.php, and if so, go for it:
RewriteCond %{REQUEST_URI} (\/([^\/]+))\/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule (.*) %{DOCUMENT_ROOT}/%1.php [QSA,L]
If nothing is handled, and you get here, it's a problem, so stop it:
RewriteRule .* - [L,R=404]
FYI, all those sample rules are deeply tested on a production server.
And now with that, you have all what you need to do something good & working.