46

I have an app where it uses a single ng-view and multiple controllers and views. If I navigate through the root, eg: www.example.com, everything works. Except that if I hit Ctrl+R (Refresh) then it gives me the 404 eror Page not Found. eg: refreshing on this page gives me error. http://example.com/item/1/.

But if I access the page using the hashbang then it works.eg: http://example.com/#!/item/1/

How shall I fix this problem? My .htaccess is empty. And I'm using chrome which support HTML5 hashbang.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109

8 Answers8

52

When the browser calls http://example.com/#!/item/1/, it is calling the index page of http://example.com/, your JS then determines what content to display by analysing the hashtag.

When the browser calls http://example.com/item/1/, your server is attempting to serve the index page of http://example.com/item/1/, which it cannot find and therefore throws a 404 error.

To achieve what you want, you'll either need to:

  • Create a rewrite rule to rewrite the links to your root index page
  • adjust your JS so that it generates the hashtag instead of the URL. If you are using AngularJS then turn off html5 mode with $locationProvider.html5Mode(false);, or
  • put an index page in http://example.com/item/1/ that redirects to http://example.com/#!/item/1/ - however note that this would need to be repeated for every /prettyPath/ you crete.

Assuming you are using Apache and your index file is index.html, try adding the following to your .htaccess file to create a rewrite rule before trying either of the other two solutions.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)       /index.html/#/$1 
</IfModule>

If you are using a pure AngularJS/Ajax solution without a server side logic, change index.php to index.html (or index.htm depending on your root index filename).

PassKit
  • 12,231
  • 5
  • 57
  • 75
  • Thank you PassKit. I can not create index pages and redirecting will slow down the process. So the JS trick sound better. How and where can I adjust the JS so that it generates a correct url? –  Jan 05 '13 at 05:20
  • Can you post your JS or a link to a jsfiddle? – PassKit Jan 05 '13 at 05:22
  • Looks like your URLs are being set in `controllers.js`. Change `redirectTo: '/annonser/1/'` to `redirectTo: '/#!/item/1'` and you should be OK. You'll also need to adjust the other URLs to avoid the same problem with other content. – PassKit Jan 05 '13 at 05:33
  • This is probably not the best solution though. Did your script come with any instructions on how to set up rewrite rules with .htaccess? Your server is capable of rewriting these links automatically. – PassKit Jan 05 '13 at 05:37
  • That didnt actually solve the problem. I think it has something to do with mod_rewrite. Unfortunately I cant find much in google eaither. I still cant refresh. –  Jan 05 '13 at 05:39
  • Try adding the rewrite rule added to the answer above to your .htaccess file – PassKit Jan 05 '13 at 05:50
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22222/discussion-between-passkit-and-socr19991293) – PassKit Jan 05 '13 at 05:53
  • @PassKit I'm with the same problem and tried your solution, but still can't make it work. I posted a question in here: http://stackoverflow.com/questions/31340154/angularjs-page-not-working-when-refresh-share-a-link would you mind to take a look? – celsomtrindade Jul 10 '15 at 13:41
  • it's working but now it also redirects to front side when i try to route on server side using `localhost/front/admin`, i am using laravel as backend of angular. – Haritsinh Gohil Dec 13 '19 at 13:40
22

You need to just add the below script in your .htaccess

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]
Muhammad Azeem
  • 1,129
  • 1
  • 12
  • 16
  • 1
    great solution... thank you so much, i was searching from last few weeks.. :) – Punit Oct 25 '15 at 16:18
  • for me also it did not work. I am working in codeigniter is that the reason – user1187 May 18 '16 at 05:19
  • Thank you. It's very helpful for me! – Kas Elvirov Aug 22 '16 at 14:33
  • This worked for me. But now I'm getting 40e pg3 forbidden error for one of the php pages. – Nikhil Bharadwaj Apr 15 '17 at 03:05
  • 2
    @Shri & Athi Are you sure mod_rewrite is enabled ? Under Debian/Ubuntu, use `sudo a2enmod rewrite`. If it outputs "mod rewrite already enabled", indeed, it "doesn't work", but if the output is like "Mod rewrite is now enabled", it's probably the fix you're expecting. I guess an apache restart will be needed to. (`sudo service apache2 restart`) – Balmipour Apr 26 '17 at 12:50
13

this is the .NET version of URL rewrite (IIS)

<system.webServer>
    <rewrite>
      <!--This directive was not converted because it is not supported by IIS: RewriteBase /.-->
      <rules>
        <rule name="Imported Rule 1" stopProcessing="true">
          <match url="^index\.html" ignoreCase="false" />
          <action type="None" />
        </rule>
        <rule name="Imported Rule 2" stopProcessing="true">
          <match url="." ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
          </conditions>
          <action type="Rewrite" url="/index.html" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
user384080
  • 4,576
  • 15
  • 64
  • 96
3

Great Blog Post on this here... http://ericduran.io/2013/05/31/angular-html5Mode-with-yeoman/

"This is mainly because your AngularJS routes aren't actual html pages. An example would be if you have a route in your angular app to /create-order. This url works fine if you link to it from inside your app but if a user tries to go directly to that page the server will return a 404."

user14604
  • 31
  • 1
1

As of March 2018, Just add these below lines in your .htaccess file.

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^(.front-end*)$ /front-end [NC,L,QSA]
RewriteRule ^(.*)$ /index.html [NC,L,QSA]  

Hope this will be helpful for you.

Pulkit Aggarwal
  • 2,554
  • 4
  • 23
  • 33
0

I couldn't comment but as well as using HTML mode, base href="/", sudo a2enmod rewrite, using .htaccess rewrite. I had to AllowOverride All in both the sites available of your site and the /etc/apache2 apache.conf

Anderson
  • 404
  • 1
  • 7
  • 16
0
    <ifModule mod_rewrite.c>
      RewriteEngine On
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteCond %{REQUEST_URI} !index
      RewriteCond %{REQUEST_URI} !.*\.(css  js|html|png)
      RewriteRule (.*) index.html [L]
    </ifModule>

use this as .htaccess

athulpraj
  • 1,547
  • 1
  • 13
  • 24
0

I had a similar issue when deploying my react app on GitHub and render. I was using react-router for routing. My solution was to use the HashRouter instead of BrowserRouter (provided by the react-router). Unfortunately, I had no access to the .htaccess file while deploying on those platforms, so I couldn't make any edits. I was forced to use HashRouter.

This answer might help someone struggling with the deployment of create-react-app facing a similar issue.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from '../src/components/App/App';
import { HashRouter } from "react-router-dom";


ReactDOM.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>,
  document.getElementById('root')
);
Nishant Kumar
  • 691
  • 1
  • 11
  • 31