Getting 404 error when I do refresh on angular page. HTTP Status 404 - /product/P12345
Below is the my route configuration
MyApp.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/product', {
templateUrl: 'components/product/product.html',
controller: 'ProductCtrl'
});
First time i'm hitting url as http://localhost:8080/index.html#/product/P12345 In the browser url get converted into http://localhost:8080/product/P12345
when i click on refresh button getting 404 error.
Not sure what causing the issue, any help is greatly appreciated.
Related
So I needed to change my URL so that google analytics could track it. Google analytics wouldn't accept it with the "/#/" (hash) in the link. That said, I used Angular's locationProvider and revised my app routing with:
(function() {
'use strict';
angular
.module('mbapp')
.config(routerConfig);
/** #ngInject */
function routerConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
});
$stateProvider
.state('steps', {
url: '/steps',
templateUrl: 'app/steps/steps.html',
controller: 'StepsController',
controllerAs: 'steps'
});
// use the HTML5 History API
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
}
})();
My URL is fine and changes it to http://website.com/steps rather than http://website.com/#/steps. However, now, if a user refreshes (f5) the link it then throw a 404 error and not sure why. Additionally, it seems that somehow this gets injected as the URL when the refresh is called "http://website/steps#/steps".
Any ideas on this?
Thanks much.
The problem is probably on the server side. You have to configure your server so it responds to every request with your html file. For example in express:
var app = require('express')();
app.configure(function(){
// static - all our js, css, images, etc go into the assets path
app.use('/assets', express.static('/assets'));
app.get('/api/users/:id', function(req, res){
// return data for user....
});
// This route deals enables HTML5Mode by forwarding missing files to the index.html
app.all('/*', function(req, res) {
res.sendfile('index.html');
});
});
When you reload the page, the request goes to the server side of your application, and it tries to resolve the url but it probably can't, because those routes only exists on the client side of your application.
Also it is a good idea to prefix every server side route with an /api route prefix, so you can easily distinguish between client side and server side routes.
I am using $stateProvider to set-up my states like so:
constructor($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider.
state("something", {
url: "/index.html"
})
// many more
}
I am not using $urlRouterProvider.otherwise('default-something');, so when I type /invalidstate, I was expecting a 404. Instead, I'm getting a 200 response.
What I'm trying to do is set up a 404 interceptor, but in order for me to intercept, I have to get a 404. I can't fathom for the life of me why a state that's not handled would result in a 200.
You are getting a 200 response because so far as the server is concerned, that is a valid route.
I want to use angularjs routing, I'm using but it's making extra requests in server side. Anyone know the solution of this problem, or I'm doing something wrong?
Client app.js
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode({enabled: true, requireBase: false})
$routeProvider.
when('/', {
templateUrl: '/tpl/main.tmp.html',
controller: 'MainCtrl'
})
.otherwise({redirectTo: '/'})
}])
//routes.js
app.get('/', function(req, res) {
console.log("test")
res.render(__dirname+'/public/tpl/index.html', siteConfig)
})
//output
//test
//test
//test
//test
Files:
models
public
|-css
|-js
|--app.js
|--angular.js
app.js
A few things may cause this, a closer inspection of both request packets might narrow down the cause. Some ideas to check for:
The browser keeps trying to fetch the site favicon because it can't find one
Fetching an image with a # in the URL (i.e. <img src="#"/>)
Meta refresh tag in the HTML
Web browsers may retry requests when the connection is closed before receiving a response
Using ui-router in Angularjs users can accesses resources from my DB with a unique code in the URL like this:
http://example.com/abc123
with the state:
.state('show', {
url: '/:resourceID',
templateUrl: '/views/resource.html',
controller: 'ResourceController'
})
However, I'm not sure how to render the 404.html when a resource isn't found in the DB. At the moment I am returning a 404 error from Expressjs and I have an interceptor that then redirects using:
//detect 404 and redirect url
$window.location.href = "/error/404";
but this isn't ideal - you have to wait for the redirect and the URL changes.
How can I show a static 404.html and not affect the URL in the browser?
I think I've missed something but I have problem with implementing for example users activation process with use of links sent to users' e-mails.
I have page for signing up. After filling form request is sent to backend where some logic is done and also mail is sent to user's mailbox. In this mail there is activation link.
And here my problem starts - I want user to click that link and be moved to my page but I want to pass this token directly to backend to check its validity, activate account and at the end redirect user to login page.
How to implement that correctly?
That's my current routing configuration for AngularJS app:
$routeProvider.when('/', {
templateUrl: 'views/main.html',
controller: 'appController'
}).when('/login', {
templateUrl: 'views/login.html',
controller: 'userController'
}).when('/signup', {
templateUrl: 'views/signup.html',
controller: 'userController'
}).when('/activate/:activationToken', {
templateUrl: 'views/activate.html',
controller: 'userController'
}).otherwise({
redirectTo: '/'
});
That's my current backend routing configuration for node.js:
router.post('/users/login', userHelper.shouldNotBeLoggedIn, authentication.login);
router.post('/users/signup', userHelper.shouldNotBeLoggedIn, authentication.signup);
router.get('/users/logout', userHelper.shouldBeLoggedIn, authentication.logout);
router.get('/users/activate/:token', userHelper.shouldNotBeLoggedIn, authentication.activate);
Here is how I return data from backend to frontend:
if (err) {
logger.error(util.inspect(err));
res.status(403).json({message: err.code});
} else {
res.status(200).json({message: 'accountActivated'});
}
One way is to use a pure back-end URL + view that handles the account activation if the token is correct, then 302 redirect to a regular URL where the Angular app lives. If the token is incorrect, redirect to a URL that displays an error message.
Update:
In userController, when the URL matches the URL sent in the activation email (this may already exist at /activate/:activationToken), sent the token to your back-end like this:
// Make sure to inject $http and $routeParams in your controller.
$http.post('/users/activate/' + $routeParams.activationToken, {}).success(function(response) {
console.log('Yay');
}).error(function(response) {
console.error(response.data.message)
});