I am trying to make Play2 to play nice with AngularJS. Play2 will have no knowledge of AngularJS because I use Yeoman for frontend dev.
The only part I want to get down is to rewrite the url in case the user refresh in HTML5MODE. I have in my routes file in the last line
GET /*path controllers.Default.redirect(to = s"#!/$path")
However, this does not work. First of all, it seems that in routes file, using string interpolation is not allowed as $path cannot be resolved. Moreover, using # in string gives error, too, because # is the start of comment.
I can create a controller action for this route just to append "#!" to the path like this:
GET /*path controllers.Application.redirect(path: String)
/* in Application controller */
def redirect(path: String) = Action {
Redirect(s"#!/$path")
}
But I prefer to keep it very clear in the routes file, like in Ruby on Rails, I can just do
get '/*path' => redirect("/#!/%{path}")
Could you share with me your tricks and best practices?
Thanks
You're probably better off doing this rewriting in Apache or Nginx - a web server's URL rewriting capabilities are much more robust than Play's. See the Play documentation for how to set up a web server in front of Play, and then check the docs for the web server for how to set up the rewriting you want.
Related
So, I have a single page angular app that is opened when I navigate to a URL. If I use the links, moving around within the app is fine - new URLs load just fine. However, if I enter a new URL in the browser URL window and hit enter, the back end framework - Laravel in my case - tries to resolve the URL.
How do I either
Intercept the URL change so that I can simple direct it to the appropriate state in the app
Tell Laravel to ignore the new URL and let the angular app handle it
Thanks
If I understand your question correctly, you don't want Laravel handles it because the routes is defined in javascript, not in server side. If that's the case, you can simply solve it by using wildcard.
Let's say in your laravel's routes you have this line to load your app, views, javascripts etc:
Route::get('/', 'PagesController#index');
You can use the wildcard modifier to ignore whatever url that has appended, and always serve your index view instead:
Route::get('/{any?}', 'PagesController#index')->where('any', '.*');
I'm not sure why it's not in the latest documentation, but you can find the docs at Laravel 5.2 doc regarding regular expression constraints
I tried using OWASP in my angularjs web app, however.. none of my routing pages ever get lists in the spider.. can someone give me a detailed explanation on how to do this? I just want to see the vulnerabilites of all routing URLS in my angularjs app
ZAP will spider from the base URL you give it. Make sure that it can get to your routing pages by traversing the paths of available links that start on your base URL. If ZAP can't get to them by traversing your site from the base URL, create a simple sitemap or listing of all of your URLs and link/insert that on your home page.
Also, this is a handy way to get ZAP up and running via Docker.
https://github.com/zaproxy/zaproxy/wiki/Docker
HTH
AngularJS makes heavy use of JavaScript, which the 'traditional' spider doesnt handle very well.
Instead use the ajax spider: https://github.com/zaproxy/zap-core-help/wiki/HelpAddonsSpiderAjaxConcepts this is slower but will handle any JS as it launches browsers to crawl the site.
I have a Django application with an AngularJS frontend. The application sends notification emails, which it renders using Django templates.
ITEM: {{article.title}}
DATE: {{article.date}}
SOURCE: {{article.link}}
{{article.body}}
The issue is article.link. The previous version of the application didn't use Angular, so it was simple to find the link. In urls.py we had
url(r'article/(?P<article>\d+)/$', views.ArticleView.as_view(), name='show-article')
which meant that we could reverse a URL to a particular article with
django.core.urlresolvers.reverse('show-article', kwargs={'article':article_id})
Now, on the Angular-based revamp of the site, the display URL for an article looks like /mysite/#/article/1234 and is determined by routes.js:
$routeProvider.when('/article/:articleId', { ... } )
Bottom line, I don't have a way to grab an AngularJS route from Python. I could hard-code the all the routes from routes.js into something the backend sees, but it wouldn't be very DRY. I could generate routes.js dynamically with Django, but right now none of our other JS source is touched by Django -- that doesn't seem very clean either. Maybe I should continue to support the old-style URLs (/article/1234) as a redirect to the Angular-style URLs (/#/article/1234)? That still requires logical duplication, I think.
Is there a better pattern I should be using here?
Decoupling clients and servers is often a goal so duplication should not be considered a bad thing in this case. Depending on your needs however there are solutions which provide a reverse method which behaves like in Django. There is django-js-reverse and django-angular for angular specificaly.
I want to use Symfony2 as back end to create a REST API and use AngularJS as front end. The 2 are completely separated ie Symfony 2 will not render anything, it'll just send json data to AngularJS.
I'm not sure on how to configure my web server (nginx).
The Symfony documentation gives the configuration but it's intended for a site that only uses Symfony, and so everything outside of the /web/ folder is not accessible.
I can see several possibilities:
Create 2 different directories (eg /path/frontend and /path/backend) and a corresponding website for both. I would then have 2 different addresses to access the front end and the back end (eg http://myfrontend.com and http://mybackend.com). The problem I see is that I probably won't be able to directly use AJAX calls in AngularJS.
Create 2 different directories (eg /website/frontend and /website/backend) and only one website. I would then probably need to access the front end and back end with something like http://example.com/frontend and http://example.com/backend. I'm not sure how to configure the web server though (issue with root /website/backend/web).
Put the AngularJS directory inside the web folder of Symfony, but then I'd need to also change the configuration so that nginx doesn't only server app.php, app_dev.php and config.php.
Put the AngularJS directory in the src folder of Symfony, and have Symfony handle the routing. I don't know if it will mess with AngularJS' one routing. Also I will probably have a few other php that should be accessible, so I'd need to route them through Symfony also.
What would you suggest and why? Maybe I'm missing something obivous?
I guess you could accomplish your task using any of those methods. It would come down to how you want to structure you application and what it's objectives are. For large scale projects the first method (having the API separate from the AngularJS) would serve you well. Twitter really made that software model big.
So I would suggest going with method one. All you would have to do is specify an Nginx header in your server block that allows cross domain access to another domain. So you would specify the following directive in your frontendangular.com site:
add_header Access-Control-Allow-Origin backendsymfony.com;
This way every time a page request comes in on your front end app Nginx tells the browser that it is safe to access another domain (your symfony setup).
These are 2 frameworks that both have powerful routing capabilities, and it looks like you are going for a best of both worlds. There are many pros and cons to any setup, so I'll list a few that come to mind:
Angular routing / templating is great but it will leave you with SEO and meta issues to solve . It's probably better to manage your major pages with symfony2 and any routing within each page with angular. This would allow you to still make dynamic pages w/out compromising your meta and SEO control. Access Control seems flexible but probably not necessary, I would just put all calls to REST API under http://www.thesite.com/api and if I need another setup something like https://api.thesite.com, nginx can route or proxypass this without leaving the domain.
Locating partials gets a little wonky but that's probably fine for a large application. Just note that you will probably need to search the js location object for [host] / [path] /web/bundles/someBundle/public/blah.... Or you can setup a '/partials' path in nginx.
Twig and Angular tpl may end up a confusing mix as they both use {{foo}}. This alone would make me reconsider mixing the 2, and I might look to go with a frontend server, like node with ejs where I could also benefit from the streaming transfer of the data sent from the API.
You can get around it easy enough with but it's still concerning:
angular.module('myApp', []).config(function($interpolateProvider){
$interpolateProvider.startSymbol('[[').endSymbol(']]');
}
);
You do get the benefit of angular partials as symfony twig, which can be good or bad depending on how you see the flexibility being used. I have seen guys making examples of forms that fill out values with symfony data, but they are just undermining the power of angulars binding.
Don't get me wrong, I actually do really like the idea of the two harmonizing.
Just food for thought - cheers
I have an Angularjs app running on Sinatra.
My Angular routes are working if I click on a link within the app, however if I visit the url directly I get a 404 from Sinatra.
Is there a way to pass the routing from Sinatra to Angular?
Currently all Sinatra is doing is loading the index.html
get '/' do
File.read "#{Dir.pwd}/app/index.html"
end
Thanks to #Ryan I ended up implementing a working solution.
get '/*' do
File.read "#{Dir.pwd}/app/index.html"
end
One way you could do this would be to set up a catch-all route with Sinatra to pass requests on to your angular app. I'm not very familiar with the sinatra framework, but for flask this is how you do it:
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def index(path):
return make_response(open('templates/index.html').read())
Just find the equivalent for Sinatra and you'll be good to go.
EDIT: I realized it is probably not the best idea to set up a catch-all route, especially if you are building a website (and using "$locationProvider.html5Mode(true)" vs. building a single-page webapp), for which returning proper 404's is important for search engine indexing, etc.
I would instead register a flask route for every route in your Angular app. In flask, this is how you do it.
#app.route('/')
#app.route('/about')
def index(path):
return make_response(open('templates/index.html').read())
In sinatra, I'd suppose it would be something like this:
get '/' do
get '/about' do
File.read "#{Dir.pwd}/app/index.html"
end
EDIT: It really depends what you're going for. Some sites want their entire site to be an angular app (and don't prioritize SEO, proper 404's, etc.) and others want a particular section to be reserved for their angular app. You might see "/app/OTHER_STUFF", for example. In that case, a catch all would work well.