pathlocationstrategy angular 2 and laravel and .htaccess - angularjs

I have trouble setting up the .htaccess for laravel and angular 2.
When I refresh the browser window I get a 404 page and try to avoid the html5 hashbang strategy.
I use routing from both Angular 2 and Laravel. The Laravel routing is used for retrieving templates (templateUrl in angular).
I started with https://github.com/sanex3339/laravel-5-angular-2-example
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

I found out another way to solve it:
App\Http\routes.php
Prefix all your Angular routes with '/api'
// Angular 2 base route resolving
Route::get('/', [
'uses' => 'JSControllers\AngularRoutesController#index',
'as' => 'home'
]);
Route::group(array('prefix' => 'api'), function()
{
// Angular 2 base `/edit` route resolving
Route::get('/edit', 'JSControllers\AngularRoutesController#index');
// Angular 2 templates route
Route::get('/templates/{template}', 'JSControllers\AngularTemplatesController#index');
// API route
Route::post('/api/upload-file', 'JSControllers\UploadController#uploadFile');
// Angular 2 templates route
Route::get('/blogdata', 'JSControllers\AngularDataController#blog');
});
App\Exceptions\Handler.php
public function render($request, Exception $e)
{
if($e instanceof NotFoundHttpException)
{
return Response::view('backend.content');
}
return parent::render($request, $e);
}

Related

angularjs laravel page refresh gives 404 error

Could you kindly tell me how can fix the issue of 404notfoundexception when I am trying to reload urls that was found using ngRouteProvider?
For example..
$routeProvider.when('/about',{
templateUrl:'partials/about.php',
controller: 'pageController'
});
if i click /about from a url, it displays the about page. However when I reload the page, it gives 404 error. I saw i will need to edit my .htaccess file. However I am not entirely sure what code to add.
Here is my current .htaccess file. Notice i tried to add something which did not work.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
#Options +FollowSymLinks
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#handle angular route
#RewriteCond %{REQUEST_URI} !index
#RewriteRule (.*) index.html [L]
Laravel Routes :
/****** Api *******/
Route::group([
'prefix' =>'/api',
'middleware' => 'web'
], function(){
Route::get('/post/{id?}',[
'uses'=>'postApiController#getPost',
'as'=>'apiPost'
]);
Route::get('/slug/{slug?}',[
'uses'=>'postApiController#getOnePost',
'as'=>'apiPostSlug'
]);
Route::get('/addition/{slug?}',[
'uses'=>'postApiController#getOnePostAddition',
'as'=>'apiAdditionSlug'
]);
Route::get('/posts',[
'uses'=>'postApiController#getAllPost',
'as'=>'api.allPost'
]);
Route::get('/contacts',[
'uses'=>'ContactController#getContactList',
'as'=>'api.getContactList'
]);
Route::get('/nextslug/{id}',[
'uses'=>'postApiController#getNextRowSlug',
'as'=>'api.getNextSlug'
]);
Route::post('/mail',[
'uses'=>'ContactController#postContact',
'as'=>'api.postContact'
]);
});
/***** Api ends *****/
Route::get('/',[
'uses'=>'siteController#index',
'as'=>'index'
]);
Thanks in advance :)
Edit
I added following code on my laravel route:
/***** Handle missing ****/
Route::get('/pages/{slug?}',function($slug){
return view('index');
});
Its working well now !! I think that solves it
For all routes in angular you need to route to index action in Laravel.
So you need to add:
Route::get('/about',[
'uses'=>'siteController#index',
'as'=>'index'
]);
All this urls will be redirected to same entrypoint, view renderered by action siteController#index and then angular router will handle routing to right location.
UPDATE
You avoid boilerplate you could do something like this:
foreach(['/', '/about', '/something'] as $route){
Route::get($route,[
'uses'=>'siteController#index',
'as'=>'index'
]);
}
You can add the following code in web.php after all routes.
Route::get('/{any}', function () {
return view('welcome');})->where('any', '.*');
The welcome is the main view file (view file - resources/views/welcome.blade.php) in Laravel.
This may help someone.

Angular $routeProvider.html5Mode route crashes after manual refresh

After enabling $locationProvider.html5Mode(true); and <base href="/" /> in the index.html routes began crashes after manual reload.
Looking up for solutions I found that .htaccess rules will fix this problem, but different configurations didn't help.
Maybe this is because my index.html is in the subdirectory /views/index.html
.htaccess:
Options +FollowSymLinks
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L] # /views/index.html doesn't work as well
</ifModule>
route config
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: 'home.html',
controller: 'AddTaskCtrl',
controllerAs: 'AddTask'
})
.when('/chat', { //this route breaks on manual refresh
templateUrl: 'chat.html',
controller: 'ChatCtrl',
controllerAs: 'chat'
})
}]);
step 1: use only $locationProvider.html5Mode(true);
step 2: Change your .htaccess
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
When index.html is start load point your app, or see more methods https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode

Prerender.io not caching my pages

So I'm trying to set up prerender.io for my AngularJS application with a ExpressJS backend following this tutorial. I have done exactly as instructed, the only difference being I have enabled HTML5mode. I have included the meta(name="fragment" content="!") in my index.jade and the prerender token to my server.js file (using the prerender-node package) but somehow my pages do not seem to be cached or generate any crawl stats.
config.coffee
angular.config ['$stateProvider','$urlRouterProvider','$locationProvider','toastrConfig',($stateProvider, $urlRouterProvider,$locationProvider,toastrConfig)->
$stateProvider
.state 'home',
url:'/'
templateUrl: 'html/main.html'
controller:'mainController'
$urlRouterProvider.otherwise '/'
$locationProvider.html5Mode
enabled: true
requireBase: false
$locationProvider.hashPrefix '!'
]
Server.JS
// Here we require the prerender middleware that will handle requests from Search Engine crawlers
// We set the token only if we're using the Prerender.io service
app.use(require('prerender-node')
.set('prerenderServiceUrl', 'http://www.mydomain.co.com/')
.set('prerenderToken', 'my-token'));
// HTML5MODE settings
// ------------------------------------------------------
app.use('/js', express.static(__dirname + '/public/js'));
app.use('/css', express.static(__dirname + '/public/css'));
app.use('/html', express.static(__dirname + '/public/html'));
// Routes
// ------------------------------------------------------
require('./app/js/routes/routes.js')(app);
app.all('/*', function(req, res, next) {
// Just send the index.html for other files to support HTML5Mode
res.sendFile('/public/index.html', { root: __dirname });
});
You should remove this line from your config:
.set('prerenderServiceUrl', 'http://www.mydomain.co.com/')
The service URL should point to a Prerender server, so you shouldn't set that to your website URL.
I think you should make sure that you have implemented the correct prerender.io configuration in your Angular App.
I tested the below code and correctly cached it in the prerender.io dashboard.
File: ../static/routes.json content
["/","/content/terms-conditions","/content/about-us",..]
File: /config/webpack.production.js
const axios = require('axios');
const routesData = require('../static/routes.json'),
console.log("PRERENDER.io caching start for Crawler Bots to SEO indexing");
const host = 'your domain name with http or https';
const prerenderToken = '****';
const prerenderUrl = 'https://api.prerender.io/recache';
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime = date+' '+time;
console.log("Start date time : "+dateTime);
for (const route of routesData) {
const fullRoute = host + route + '/index.html';
console.log(`Caching URL ${fullRoute}`);
var prerednerData = {
'prerenderToken': prerenderToken,
'url': fullRoute
};
axios.post(prerenderUrl, prerednerData)
.then((response) => {
console.log('Product URL: '+prerednerData['url']);
console.log('Status Code: '+response.status);
})
.catch((error) => {
console.log('Product URL: '+prerednerData['url']);
console.log('Error: '+error);
});
}
File: .htaccess
Options -Indexes
<IfModule mod_headers.c>
RequestHeader set X-Prerender-Token "****"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# Pre-render HTML for search crawler bots to indexing
<IfModule mod_proxy_http.c>
RewriteCond %{HTTP_USER_AGENT} googlebot|bingbot|yandex|baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\ link\ preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator [NC,OR]
RewriteCond %{QUERY_STRING} _escaped_fragment_
# Only proxy the request to Prerender.io if it's a request for HTML
RewriteRule ^(?!.*?(\.js|\.css|\.xml|\.less|\.png|\.jpg|\.jpeg|\.gif|\.pdf|\.doc|\.txt|\.ico|\.rss|\.zip|\.mp3|\.rar|\.exe|\.wmv|\.doc|\.avi|\.ppt|\.mpg|\.mpeg|\.tif|\.wav|\.mov|\.psd|\.ai|\.xls|\.mp4|\.m4a|\.swf|\.dat|\.dmg|\.iso|\.flv|\.m4v|\.torrent|\.ttf|\.woff|\.svg))(.*) http://service.prerender.io/https://www.globalshop.com.au/$2 [NE,L,R=301]
</IfModule>
RewriteCond %{HTTP_HOST} www.domainname.com$ [NC]
RewriteRule ^(.*)$ https://www.domainname.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^robots\.txt$ robots-disallow.txt [L]
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html
</IfModule>
Cheers!

Angular html5Mode with ui-router and browserify

First time using browserify and module exports with Angular, and my usual setup for html5Mode is not working.
app.js
.config(function myAppConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
})
index.html
<head>
...
<base href="/">
</head>
What the above code is doing wrong...
The routing works until the app is refreshed, and then the page assets disappear. Also if an in-correct url is given the app won't redirect to '/' like I'm intending.
Any thoughts/solutions?
Update: I'm having the same issue with and without the .htaccess that is rewriting the /index.html from the url, so I kinda thought that it wasn't related to the web server. If you think that it might be related to the web server, here is the .htaccess:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L]
</ifModule>

angularJS, prerender.io and ZF2: testing locally returns 304 access forbidden

I am a n00b with this stuff, I am trying to set up a testing environment for prerender.io.
I've downloaded prerender here: https://github.com/prerender/prerender.git and I've run this from the commandline:
$ npm install
$ node server.js
I read the documentation here: https://github.com/zf-fr/zfr-prerender
Instead of:
return array(
'zfr_prerender' => array(
'prerender_url' => 'http://myprerenderservice.com'
)
);
I did this:
return array(
'zfr_prerender' => array(
'prerender_url' => 'http://localhost'
)
);
This is my angular router:
var ListerApp = angular.module('ListerApp',[
'ListerAppFilters',
'sharedFactoryApp',
'sharedServiceApp',
'ListerAppController',
'infinite-scroll',
'angular-inview',
'ngRoute',
'itemsReady'
]);
ListerApp.config(['$routeProvider', '$httpProvider', '$locationProvider', function($routeProvider, $httpProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('!');
$routeProvider
.when('/list/:page?',
{
templateUrl : '/assets/services/partials/list.html',
controller : 'ListerCtrl',
reloadOnSearch : false,
js : ['/assets/min/shoplist_js.min.js', '/assets/min/bootstrap-typeahead.min.js'],
resolve : {
sharedServiceAppData: function($sharedData){
return $sharedData.promise();
}
}
}
)
.when('/detail/:id?',
{
templateUrl: '/assets/services/partials/detail.html',
controller: 'DetailCtrl',
css : ['/assets/min/star-rating.min.css'],
resolve : {
sharedServiceAppData: function($sharedData){
return $sharedData.promise();
}
}
}
).otherwise({ redirectTo: '/list/1' });
}]);
This url works fine: http://localhost/shop/api/list
This url returns "Access Forbidden!": http://localhost/shop/api/list?_escaped_fragment_=/list
The error.log contrains:
[core:error] [pid 5952:tid 1864] (20024)The given path is misformatted or contained invalid characters: [client ::1:50262] AH00127: Cannot map GET /http://localhost/shop/api/list?_escaped_fragment_=/list HTTP/1.1 to file
My .htaccess file:
RewriteEngine On
RewriteRule ^\.htaccess$ - [F]
RewriteCond %{REQUEST_URI} =""
RewriteRule ^.*$ /public/index.php [NC,L]
RewriteCond %{REQUEST_URI} !^/public/.*$
RewriteRule ^(.*)$ /public/$1
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^public/.*$ /public/index.php [NC,L]
Are you seeing any console output on the Prerender server?
First, the URL you probably want to use is http://localhost/shop/api/list?_escaped_fragment_=
but you probably don't want to prerender an API call. That should really probably be http://localhost/shop/list/1?_escaped_fragment_= or whatever your url structure is for an actual page.

Resources