Links goes wrong with an htaccess file [duplicate] - .htaccess

I am using WAMP Server on my PC as a local host. I want to re-write my URL without PHP extension and remove query string(but readable) as from http://myproject/post.php?page=page_slug to http://myproject/post/page_slug and I should be able to read "page_slug" via echo $_GET['page']; on "post.php" page. FOr this purpose, I have a project with a simple hierarchy is shared below.
Project_Folder:
->css/style.css
->image/logo.jpg
->js/script.js
->.htaccess
->index.php
->about.php
->contact.php
->blog.php
->post.php
->page.php
Now I want to remove all .PHP extensions from my URL so I used the below .htaccess code and it is working fine.
# Options is required by Many Hosting
Options +MultiViews
#Remove .PHP Extension And Force Redirect To Without .PHP File Name In URL
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [NC,L]
#RewriteCond %{THE_REQUEST} \s([^?]*)\?p=(\S+)\s [NC]
#RewriteRule ^ %1/%2? [R=301,L]
After the above code, I am able to re-write my URLs from http://myproject/post.php?page=page_slug to http://myproject/post?page=page_slug means .PHP extension is now removed successfully.
Now to make my URL free from query string pattern, I used the below code after the above code in my .htaccess file.
RewriteCond %{THE_REQUEST} \s([^?]*)\?p=(\S+)\s [NC]
RewriteRule ^ %1/%2? [R=301,L]
After the above code, I am able to re-write my URLs from http://myproject/post?page=page_slug to http://myproject/post/page_slug means query string is now removed successfully but my JS and CSS are broken now as shown below.
But my every file is perfect as when I remove the upper second code set then it is working properly. Also, they are loading fine as shown below.
I noticed one thing that my CSS and JS files data is now changed with my PHP file data as shown below. Why this is happening...???
So what is the fix for this...??? Also, remember that I need to read QUERY STRING parameters also in my file.

The "problem" is that you appear to be using relative URL-paths to your static resources (CSS, JS and images). So this is a client-side URL resolution issue. You should be using root-relative (starting with a slash) or absolute (with scheme + hostname) URLs to your assets so they can be located regardless of URL-path depth. (Note that any requests that your JS makes, eg. AJAX, should also be root-relative or absolute.)
The problem is not so much with .htaccess, but when you change the URL from /post.php?page=page_slug to /post/page_slug then any client-side relative URLs are going to resolve relative to /post/, not / (the document root) as before.
The request for the JS (and CSS) files result in a 404, so the 404 HTML error document is most probably being parsed as JS and failing (ie. "Uncaught SyntaxError: Unexpected token: '<'" - due to a <!DOCTYPE html> or opening <html> tag).
A possible workaround (to avoid changing your URLs) is to use a base HTML element in the head section to indicate what any relative URLs should be resolved relative to, overriding the URL of the current document. However, this has some additional caveats if you are using in-page anchors of the form href="#element" - since they will now be resolved relative to the document stated in the base element and not the current document.
See also my answer to the following question on the Webmasters stack that goes into more detail on this:
https://webmasters.stackexchange.com/questions/86450/htaccess-rewrite-url-leads-to-missing-css

Related

htaccess directory management

im going to ask a really simple question. i dont want my link to show this when i run my page :
http://localhost/example/assets/gallery.php
what i want is :
http://localhost/example/assets/
so how to do it in .htaccess file ?
i would really appreciate it if you can help because im so confused after reading forums .
my htaccess is like this right now but you know it only helps to remove extension :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
How to make assets/gallery.php -> assets/
In the assets folder make a .htaccess file
Paste in this code :
DirectoryIndex gallery.php
This code changes the Directory Index (like a index.php file) to the gallery.php file meaning gallery.php is now like the index.php file.
The DirectoryIndex method that #RyanTheGhost suggests in his answer should have worked for the specific example you posted (where you request a directory and are serving a file from within that directory). However, the mod_rewrite directives you currently have in the document root1 will conflict with any requests for directories2 (although the DirectoryIndex should take priority).
However, the DirectoryIndex method is not very practical if you have many such files. And if you are not requesting a directory then this method naturally won't work anyway.
You could instead rewrite the URL using mod_rewrite in your existing .htaccess file, before your current directives.
1 I'm assuming your .htaccess file is in the document root.
For example:
# Rewrite "/example/assets/" to "/example/assets/gallery.php"
RewriteRule ^example/assets/$ example/assets/gallery.php [L]
Or, to avoid repitition:
# Rewrite "/example/assets/" to "/example/assets/gallery.php"
RewriteRule ^example/assets/$ $0gallery.php [L]
Where the $0 backreference contains the entire URL-path that is matched by the RewriteRule pattern. ie. example/assets/ in this case. NB: There is no slash prefix on the RewriteRule pattern or the substitution string.
Note that since you are requesting a directory (ie. /example/assets/) you need to ensure there is no DirectoryIndex document in that directory (eg. index.html or index.php), otherwise this will be served (by mod_dir) instead, overriding your internal rewrite above.
2 Your current directives that append the .php extension are arguably incorrect:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
This rule appends the .php extension to any request that does not map to a physical file, even if the file with a .php extension does not exist either. This can result in the incorrect URL being reported back to the user in the 404 error document (depending on how this is implemented). For example, the default Apache 404 error document will report that /foo.php does not exist, when the user requested /foo.
This rule will also rewrite directories (since they are "not files") which will result in a 404 (as opposed to a 403 or directory listing, if enabled). Although a DirectoryIndex document will override this.
Additionally, the NC flag is superfluous and there is no need to backslash-escape the literal dot inside a character class.
You could instead check that the corresponding .php file exists before rewriting, instead of checking that the requested URL does not map to a file.
For example:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
The request is now only rewritten when the corresponding .php file exists, which naturally avoids any conflicts with directories.

htaccess rule to consider double slashes as single

I am working on a project built using codeigniter. And the mistake I have made is that I have added "/" after the base_url() method in many links(href) I have given on the project files as shown below.
<? echo base_url();?>/about
So the URLS are looking like
http://myproject.com//about
in place of
http://myproject.com/about
And because of that, it is resulting to 404 error.
Now the situation is that the site is ready but I am only allowed to update the .htaccess file of the project to fix this.
So is there any rule I can write in .htaccess file so that it considers the double slashes in the URL as single slash and open the specific page?
Funny thing is, it was already considering double slashes as single slash somehow and opening the "About" page on the development server. But now as the server is changed, I have started facing the 404 issues.
You can use this rule as very first rule in your DOCUMENT_ROOT/.htaccess file to remove multiple //:
RewriteEngine On
RewriteCond %{THE_REQUEST} //
RewriteRule ^(.+?)/?$ /$1 [R=302,L,NE]
actually you have set the base url as
$config['base_url'] = 'http://myproject.com/';
and when u are using it like this
<? echo base_url();?>/about
it is adding to // so you have to change your page like this
<? echo base_url();?>about
and if you cant change your path then you can set your htaccess as
RewriteEngine On
RewriteCond %{THE_REQUEST} //
RewriteRule ^(.+?)/?$ /$1 [R=302,L,NE]

htaccess - rewrite URL to include CSS and JS

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(.*)\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico)$ [NC]
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
This .htaccess redirects everything to index.php?path=SOMETHING where I can pick it up (SOMETHING path) and show appropriate content (views).
The problem is with including .css/.js files.
If I use www.website.com/something everything works (css path is like /css/style.css and it's searching in the www.website.com/css/style.css). But if I use www.website.com/something/2 everything crashes because it's searching in www.website.com/something/css/style.css folder.
How to set root (?) everytime to www.website.com (whatever path is)? So I should still have acccess to my 'path' variable but everything should point to the website root and not /some/... path when including my files.
The problem is in the way how you write links to css/js/image files.
Instead of including css/js/images using relative URLs to the current page:
href="css/style.css"
you should use URLs relative to the root (notice the leading slash):
href="/css/style.css"
or use absolute URLs (that will include domain name -- much less preferred approach).
This is a typical mistake when designing website (html part) when site uses Nice URLs/URL Rewritting. This is -- it's now that rewrite engine breaks URLs -- it's browser that sends them like that (/something/css/style.css) in first place.

Redirect to fallback file if first attempt fails

I have this in my .htaccess:
RewriteRule ^images/([^/\.]+)/(.+)$ themes/current/images/$1/$2 [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^images/([^/\.]+)/(.+)$ modules/$1/images/$2 [L,NC]
The idea is that it does the following:
// Rewrite this...
images/calendar/gear.png
// ... to this
themes/current/images/calendar/gear.png
// HOWEVER, if that rewritten path doesn't exist, rewrite the original URL to this:
modules/calendar/images/gear.png
The only things that change here are calendar and gear.png, the first of which could be any other single word and the latter the file name (possibly with path) to an image file.
I can rewrite the original URL to the first rewrite as shown in the example just fine, but what I cannot do is get my .htaccess to serve up the file from the other, fallback location if the first location 404s. I was under the impression that not using [L] in my first RewriteRule would rewrite the URL for RewriteCond.
The problem I'm having is that instead of serving the fallback file, the browser just shows a 404 to the first rewritten path (themes/current/calendar/gear.png), instead of falling back to modules/calendar/gear.png. What am I doing wrong?
Please note that my regex isn't perfect, but I can refine that later. Right now I'm concerning myself with the rewrite logic itself.
Fallthrough rules are fraught with bugs. My general recommendation is than any rule with a replacement string other than - should trigger an internal redirect to restart the .htaccess parse. This avoids the subrequest and URI_PATH bugs.
Next once you go to 404, again in my experience this is unrecoverable. I have a fragment which does something similar to what you are trying to do:
# For HTML cacheable blog URIs (a GET to a specific list, with no query params,
# guest user and the HTML cache file exists) then use it instead of executing PHP
RewriteCond %{HTTP_COOKIE} !blog_user
RewriteCond %{REQUEST_METHOD}%{QUERY_STRING} =GET [NC]
RewriteCond %{ENV:DOCUMENT_ROOT_REAL}/blog/html_cache/$1.html -f
RewriteRule ^(article-\d+|index|sitemap.xml|search-\w+|rss-[0-9a-z]*)$ \
blog/html_cache/$1.html [L,E=END:1]
Note that I do the conditional test in filesystem space and not URI (Location) space. So this would map in your case to
RewriteCond %{DOCUMENT_ROOT}/themes/current/images/$1/$2l -f
RewriteRule ^images/(.+?)/(.+)$ themes/current/images/$1/$2 [L]
Though do a phpinfo() to check to see if your hosting provider uses an alternative to DOCUMENT_ROOT if it is a shared hosting offering e.g an alternative environment variable as mine uses DOCUMENT_ROOT_REAL.
The second rule will be picked up on the second processing past after the internal redirect.

CSS trouble with Pretty URLs

I have an index.php, profile.php files in localhost/project
I've written following code in my .htaccess file to have localhost/project/profile.php?u=sam by visiting localhost/project/sam
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^([a-zA-Z0-9_-]+)$ profile.php?u=$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ profile.php?u=$1
When I visit http://localhost/project/sam it diplays what I want without errors. But when I visit http://localhost/project/sam/ (with trailing / ) it displays the page with plain text, that means the css file is not attached.
Anyone know the reason for this? And help me to solve this?
You are probably using relative URI paths to reference those external resources. And relative URIs are resolved on a base URI that is the URI of the current document if not specified otherwise.
So when using a relative URI path like css/style.css on /project/sam it is resolved to /project/css/style.css; but when used on /project/sam/ it is resolved to /project/sam/css/style.css.
You could fix this by either using the absolute URI path /project/css/style.css or by changing the base URI with the BASE element. But note that the latter will affect all relative URIs and not just relative URI paths.
You're using a relative link to your css.
How do you include that css file? If you generate the path from PHP, it might contain a double '/' if your request contains a trailing '/'. Please check your HTML output and moidify the path of the CSS.
Either require the slash, or forbid it, or you'll never know whether relative links need to go uplevel or not. For example to forbid the slash:
RewriteRule ^(.*)/$ $1 [R]
which will redirect the client to the same page without the slash included. It's best to have a single canonical URI for an object anyway.

Resources