Cannot GET - Error After refresh using Ionic - javascript

I'm using Ionic framework to build a hybrid mobile application and I have html5Mode set to true, Ui-Router, and gulp to provide me with livereload, sass compiling, css and javascript minifying.
The problem is whenever I navigate to a state directly from the index, everything works fine, requests are being made to my server, but when I refresh that same state, I get Cannot GET error.
I am treating my Ionic application as a separate thing from my Express.JS app.
Here's some code:
States
$stateProvider
.state('faculties', {
url: '/',
templateUrl: 'views/main/main.html',
controller: 'MainCtrl as main'
})
.state('faculty', {
url: 'faculties/:faculty',
templateUrl: 'views/faculty/faculty.html',
controller: 'FacultyCtrl as v'
})
So, if I opened the page and clicked on the button that takes me to the 'faculty' state, It's all good. But if I refresh that page, it's giving me that Cannot GET error.
Here's the code from the 'faculty' state controller:
app.controller('FacultyCtrl', function ($http, $stateParams, appConfig) {
var v = this;
var api = appConfig.api;
v.faculty = {};
$http.get( api + '/faculties/' + $stateParams.faculty)
.then( res => {
v.faculty = res.data;
}).catch( error => {
console.log(error);
});
});

The problem you are having is that you do not route all possible urls to the same index.html
When you first load the page, say, the URL being http://example.com/, your web server will serve the static file index.html from your root. When changing the route, your URL ends up as (for example) http://example.com/some_page. This works because the URL is "faked", there is no such file on the server. When refreshing (or going to that URL directly), that URL is requested from the server, which fails (since, as before, that file/folder does not exist).
What you need to do is route all requests (excluding API and whatnot) to the same static index.html, this is standard behavior of all single-page apps:
The routing is done clientside.

Related

Moving Passport Google strategy authenticate method from route to controller breaks

I am using the 'passport-google-oauth' strategy from Passport with Nodejs based Express app to provide authentication. This worked great when I had the logic inside the route file as follows:
router.route('/auth/google')
.get(passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile']
});
);
When I moved everything into a controller to make the app more manageable, it stopped working. Specifically, no error is being thrown. The GET request succeeds and the debug method outputs the string, but then it just loads forever and I'm not being redirected to the Google page to select which account to log in with. Any ideas what is going on here and what I need to change to make it flow like fine wine?
// route file
router.route('/auth/google')
.get(backendController.googleAuthenticate);
// controller file
exports.googleAuthenticate = () => {
debug('attempting Google authentication');
passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile'],
failWithError: true
});
}

Could not get the pages while refreshing the browser using ui-router Angular.js

I need some help.I am facing some issues. I could not get the pages after refreshing again using Angular.js. I am explaining my code below.
route.js:
var app=angular.module('demo',['ui.router']);
app.run(function($rootScope, $state) {
$rootScope.$state = $state;
});
compliance.config(function($stateProvider, $urlRouterProvider,$locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('/', {
url: '/',
templateUrl: 'View/demo1.html',
controller: 'demoController'
})
.state('demo2', {
url: '/demo2',
templateUrl: 'View/demo2.html',
controller: 'demo2Controller'
})
$locationProvider.html5Mode({
enabled: true,
requireBase: true
});
});
index.html:
<div ui-view></div>
demo1.html:
demoController.js:
$scope.goToAuditDetailPage=function(){
$state.go('demo2',{}, { reload: true });
}
Here when user will open the link http://localhost/NABH/ the demo1.html page will come and inside that page there is one click event, when user will click on that link the demo2.html page is coming and the URL is http://localhost/NABH/demo2. But In this case when user will refreshing that link http://localhost/NABH/demo2 again this The requested URL /NABH/demo2 was not found on this server. error is coming. Here I need after refreshing also that page should work as per expected.Please help.
You are using html5mode with your routes, therefore the browser changes the routes of your app as they are come from the server, when ever the user press on the refresh button, the browser sends a request with your client route, and your server doesn't aware of it.
One of the simplest solution is to make the server "answer" to all the routes with your client app, in that way, the request with your client rout with be answered with index.html shell (as it answered when you navigate to /), and the client app will check the current route and render the proper page (it's done automatically).

Loading different controllers with the same conditional URL

I'm using MEAN and I'm trying to redirect the user to different pages (different controllers as well) using a conditional URL like www.domain.com/#!/:path
I'll explain myself a little more better.
I've got three different packages (users, organizations and events), but all the packages can be accessed by the same parametrized URL (www.domain.com/#!/:path). Path is a field stored in database and each record belonging to each package has its own path. Path is unique, of course.
What i want to do is to detect if the URL the user is visiting belongs to users, organizations or events, for loading the proper page. For that, I have to query the database for checking if that :path is stored in users, organizations or events model. According to the result of that query, just redirecting to the proper controller/page.
I don't know how to accomplish that exactly in AngularJS side. Any suggestion?
Thanks in advance!
SOLUTION:
Finally, i got it working doing something like this:
// states for my app
$stateProvider
.state('home', {
url: '/',
templateUrl: 'system/views/index.html'
})
.state('entity', {
url: '/:path',
template: 'Loading...',
controller: function ($scope, Global, $http, $state, $stateParams) {
$http({
method: 'GET',
url: '/checkUrl/' + $stateParams.path
})
.then(function (result) {
$scope.global = Global;
// Doing entity information accesible globally
$scope.global.entity = result.data.info;
// Redirecting to the proper controller/template
switch ( result.data.type ) {
case 'users':
$state.go('user', {reload: true});
break;
case 'organizations':
$state.go('organization', {reload: true});
break;
default:
};
});
}
})
.state('user', {
url: '',
templateUrl: 'users/views/index.html'
})
.state('organization', {
url: '',
templateUrl: 'organizations/views/index.html'
});
Through /checkUrl/:path a request is made to server side for checking if :path belongs to users, organizations or events. The response contains the info of that entity and the kind (user, organization, event).
From there, it's just redirecting according to the entity matched.

Angular load partial based on data sent by server

I have an <ng-view></ng-view> that is filled with a partial html file when a button is clicked i.e Sign In
myApp.js
var myApp = angular.module("myApp", ['ngRoute']);
//Define Routing for app
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/signin', {
templateUrl: 'signin.ejs'
}).
when('/signup', {
templateUrl: 'signup.ejs'
}).
when('/myAccount', {
templateUrl: 'myAccount.ejs'
}).
otherwise({
//home page
});
}]);
What I want to know is, how can fill this ng-view based on data that is sent by the server. For example, if the server renders the index.html with data {page: '/signin'} how can I let Angular know that I want to to populate the ng-view with 'signin.ejs'??
Any help is appreciated. Thank you!!
EDIT:
I have someone logged in to the site and on a page I provide a "switch account" button. So what I want to do is, when that is clicked, post to the server /logout route so the session can be cleared, and then change the page to the signin page (partial html file) and populate the username field with the account that they are switching to
Your ejs needs to be rendered by nodejs so you need to apply your the routing there.
You need to come up with a way to identify the route path like '/partials/:filename'
app.route('/partials/:filename').get(funcs.partials);
Then you handle the request and render your ejs or plain you just send(html) and you use the path module to locate and manipulate the url string.
exports.partials = function(req, res, next, filename) {
res.render(filename, vars);
};
Then your angular is like, though signin is probably not the best example.
$routeProvider.
when('/signin', {
templateUrl: '/partials/signin'
})

Angularjs: Interceptor redirection creates double rendering

I am stuck with this strange behaviour. None of the Google hits seem to return any mention of a similar case so I am assuming that I am doing something seriously wrong.
My interceptor does react on the 401 status and redirects to the appropriate route but at the same time it renders the previous route too. So I have a very ugly flash of one template then the other. I am simply trying to test my authentication: if authenticated then render the table, otherwise render the login form. It does redirect to the login form but still flashes the table template for a fraction of a second.
angular.module('Basal', ['ngRoute', 'Basal.users'])
.config(function($routeProvider, $locationProvider, $httpProvider) {
$locationProvider.html5Mode(true);
$httpProvider.interceptors.push('authInterceptor');
$routeProvider.
when('/', {
templateUrl: '/tpl/table.html',
controller: 'MainCtrl'
}).
when('/login', {
templateUrl: '/tpl/login-form.html',
controller: 'MainCtrl'
}).
otherwise({
redirectTo: '/'
});
});
angular.module('Basal.users', [])
.controller('MainCtrl', function($scope, getJson) {
getJson.fetch(function (d){
$scope.computers = d;
});
})
.factory('getJson', function($http, $location) {
return {
fetch: function (c) {
$http.get("/json")
.success(function(data) {
console.log("getJson: Success!");
c(data);
})
.error(function() {
console.log("getJson: Failure!");
});
}
}
})
.factory('authInterceptor', function($q, $location) {
return {
'responseError': function(response) {
if (response.status === 401) {
$location.path('/login');
}
return $q.reject(response);
}
}
});
Now, when I hit '/' on the browser Angular does two requests on the background: one is to fetch the table template and insert it in to the view and the other is to get the JSON data.
On the server side I put session restriction only on the data request! The template is just a static file. To put restriction on the template I need to drag it through the server routing and this is not, I believe, how Angular does things. But if I do create server side route for the template and put session restriction on it then double rendering disappears.
I am confused about how this works. Fetching the template and fetching the data is done asynchronously in parallel. So while JSON request triggers 401 and redirects to the login template, the original table template is still going through and being rendered empty. Hence I get all the ugly double rendering. This is a race of some kind. How do I stop it? Maybe my interceptor is wrong? Isn't the Angular interceptor supposed to stop any further processing?
As a related issue, the otherwise function on the $routeProvider does not work either. If I put a non-existent URL, I get 404 from the server but Angular routing does not catch it. Is this how it is supposed to be? If a URL change happens in Angular and then I hit reload on the browser, I get an ugly 404 instead of a nice redirect. Am I supposed to handle 404 in an interceptor too? Then what is the point of otherwise?
Thanks.

Categories

Resources