Wildcard or regex node express mount path on middleware - regex

I would like to define different middleware depending on how the path looks.
The thing is that the path may wary; I'd like to for instance support the following paths:
/chat/auth/test
/chat/auth/add
/chrome/auth/test
/chrome/add
Every time auth is in the path I would like the auth middleware to be called, and for chat and chrome I want their respective middlewares to be called.
app.js:
// Middleware authentication
var chatAuthenticate = require('./server/middleware/chat-authenticate');
app.use('/chat', chatAuthenticate(addon));
var authAuthentication = require('./server/middleware/auth-authenticate');
app.use('/auth', authAuthentication());
I understand that I can just add multiple entries to app.js for every possible combination, like /chat/auth and /chrome/auth and it wouldn't increase the complexity at all, but I'm just curious if it's possible to solve this with wildcards or regex :)

app.use(/auth/, authAuthentication);
This will call authAuthentication for every request that contains auth anywhere. A few things to consider:
It is a Regular Expression, so instead of quotes you just need /…/ as delimiters
Note that if you have multiple middlewares that match a route (e.g. another one with /chat/ as RegEx, and you call /auth/chat or /chat/auth, both middlewares will be called. Because of that it is important to consider the order of your app.use() calls.
authAuthentication is required to expect (request, response, next) parameters. If you directly call the function as in your example, the function is expected to return a function that will take the three express middleware parameters.
It is common practice to place all require calls at the top of your script
Make sure you fully read and understood Express Routing. It is awesome.

You can use wildcards (at least in express 4):
app.use('/chat/*', chatMiddleware);
Which would apply that middleware first to any request starting with '/chat/'. Then use the next one for the next level which would only apply to '/chat/auth/*'...
app.use('/chat/auth/*', function(req, res, next) {
//.... middleware logic here
//.... assuming we don't reject the call, call next() when done
next();
));

Related

In ember, how can I correctly treat routes whose pathnames contain hashes (#) as fragment identifiers?

In my router I have the following block:
Router.map(function() {
this.route('stuff');
this.route('registration', { path: '/registration' });
this.route('registration-first', { path: '/registration#first' });
});
The reason I wish to do this is so that from a user perspective, it makes logical sense that each route is a subsection or "fragment" of a single pipeline, but internally, I'm treating each page as a separate route because separation of concerns make more sense for my use case.
The approach above works perfectly fine except when I perform the following:
Transition to the hashed route
Return to the previous route/page (back button, browser)
Forward back to the hashed route/page
At this point in time the browser successfully adds the fragment identifier to the URL, but my route does not transition to the hashed route. Is there any way I can achieve this? Thanks.
You dont. At least not with the # sign. The problem is that # already has a special meaning in a URL: Its the seperator between the path and the hash. Its historically used for anchors on a page. Ember used the hash to store the entire URL before the history API was avaliable.
Honestly I would go with /registration/first and /registration/second, but I think there are other seperators you could use. However you should know that some chars are escaped depending on your browser.

How to filter a Backbone collection on the server

Is there a common pattern for using Backbone with a service that filters a collection on the server? I haven't been able to find anything in Google and Stack Overflow searches, which is surprising, given the number of Backbone apps in production.
Suppose I'm building a new front end for Stack Overflow using Backbone.
On the search screen, I need to pass the following information to the server and get back a page worth of results.
filter criteria
sort criteria
results per page
page number
Backbone doesn't seem to have much interest in offloading filtering to the server. It expects the server to return the entire list of questions and perform filtering on the client side.
I'm guessing that in order to make this work I need to subclass Collection and override the fetch method so that rather than always GETting data from the same RESTful URL, it passes the above parameters.
I don't want to reinvent the wheel. Am I missing a feature in Backbone that would make this process simpler or more compatible with existing components? Is there already a well-established pattern to solve this problem?
If you just want to pass GET parameters on a request, you should just be able to specify them in the fetch call itself.
collection.fetch( {
data: {
sortDir: "ASC",
totalResults: 100
}
} );
The options passed into fetch should directly translate to a jQuery.ajax call, and a data property should automatically get parsed. Of course overriding the fetch method is fine too, especially if you want to standardize portions of the logic.
You're right, creating your own Collection is the way to go, as there are not standards about server pagination except OData.
Instead of overriding 'fetch', what I usually do in these cases is create a collection.url property as a function, an return the proper URL based on the collection state.
In order to do pagination, however, the server must return to you the total number of items so you can calculate how many pages based on X items per page. Nowadays some APIs are using things like HAL or HATEOAS, which are basically HTTP response headers. To get that information, I normally add a listener to the sync event, which is raised after any AJAX operation. If you need to notify external components (normally the view) of the number of available items/pages, use an event.
Simple example: your server returns X-ItemTotalCount in the response headers, and expects parameters page and items in the request querystring.
var PagedCollection = Backbone.Collection.extend({
initialize: function(models,options){
this.listenTo(this, "sync", this._parseHeaders);
this.currentPage = 0;
this.pageSize = 10;
this.itemCount = 0;
},
url: function() {
return this.baseUrl + "?page=" + this.currentPage + "&items=" + this.pageSize;
},
_parseHeaders: function(collection,response){
var totalItems = response.xhr.getResponseHeader("X-ItemTotalCount");
if(totalItems){
this.itemCount = parseInt(totalItems);
//trigger an event with arguments (collection, totalItems)
this.trigger("pages:itemcount", this, this.itemCount);
}
}
});
var PostCollection = PagedCollection.extend({
baseUrl: "/posts"
});
Notice we use another own property, baseUrl to simplify extending the PagedCollection. If you need to add your own initialize, call the parent's prototype one like this, or you won't parse the headers:
PagedCollection.protoype.initialize.apply(this,arguments)
You can even add fetchNext and fetchPrevious methods to the collection, where you simply modify this.currentPage and fetch. Remember to add {reset:true} as fetch options if you want to replace one page with the other instead of appending.
Now if your backend for the project is consistent, any resource that allows pagination on the server may be represented using one PagedCollection-based collection on the client, given the same parameters/responses are used.

How can you store a path and transitionTo it later in Ember's v2 Router?

i'm trying to migrate to the new Router in Ember. the use case is this: user is not logged in but requests a URL that requires login. he is redirected to a login route, after successful login he is redirected to his original destination.
i achieved this with the prior Router by overriding Router.route(path) and intercepting path requests when the app was in unauthorized state.
the new Router doesn't have a route() function, also, i don't know how to override it now that the Router instance is created automatically by Ember. i probably shouldn't do that anyway.
there is a Route.redirect() hook that looks useful. however, Route no longer extends Path in the v2 Router, so there is no Root.path, and no path information is passed into Route.redirect(), so i don't know how to save the path info for calling transitionTo() later.
i've supplied my general approach below. how can i accomplish this? it seems like a very common use case for many application.
// i imagine something like this should happen
App.AuthRequiredRoute = Ember.Route.extend({
redirect: function() {
if(!App.controllerFor('login').get('isLoggedIn')) {
var pathToSave = ????
App.controllerFor('login').set('pathAfterLogin',pathToSave);
this.transitionTo('login');
}
}
}
// and then after login, the LoginController would call App.router.transitionTo(this.pathAfterLogin)
I have done a lot of research into this myself in the last day or two. I can share with you what I have discovered, and a couple of thoughts.
First of all, you can some information regarding the current path and contexts like so:
this.router.router.currentHandlerInfos
This returns an array. Each object has both a name and a context property. The names correspond to the name of the router you would call in transitionTo.
In my opinion, although you could work with something like this, it would be messy. The API docs don't refer to this and it may not be the intention to use this as a public API.
I see issues with the above solution for deeper nested dynamic segments too. Given how new the router v2 is, I think it will continue to evolve and a better solution is likely to present itself. It's a fairly common thing to want to save the current location and return to it at a later date.
In the meantime, rather than a redirect, perhaps use a conditional block in your template that presents a login rather than an outlet if the authenticated flag is not set on the ApplicationController? I know it's not as "right" but it is "right now".

Django reverse routing - solution to case where reverse routing is less specific than forward routing

I have a route defined as follows:
(r'^edit/(\d+)/$', 'app.path.edit')
I want to use the reverse function as follows:
url = reverse('app.path.edit', args=('-id-',))
The generated url gets passed to a js function, and client side code will eventually replace '-id-' with the correct numeric id. This of course won't work, because the 'reverse' function won't match the route, because the url is defined as containing a numeric argument.
I can change the route to accept any type of argument as follows, but then I loose some specificity:
(r'^edit/(.+)/$', 'app.path.edit'
I could create a separate url for each item being displayed, but I'll be displaying many items in a list, so it seems like a waste of bandwidth to include the full url for each item.
Is there a better strategy to accomplish what I want to do?
You can rewrite regexp like this:
(r'^edit/(\d+|-id-)/$', 'app.path.edit')
but I generally prefer this:
(r'^edit/([^/]+)/$', 'app.path.edit') # you can still differ "edit/11/" and "edit/11/param/"
Usually you will anyway need to check entity for existent with get_object_or_404 shortcut or similar, so the only bad is that you have to be more accurate with incoming data as id can contain almost any characters.
In my opinion, and easier solution would be to keep the original url and then pass the value '0' instead of '-id-'. In the client side then you replace '/0/' with the correct id. I think this is better because it doesn't obscure the url routing, and you don't lose specificity.

Is it possible to make URLs conditional with django?

I'm using the middleware to detect the subdomain and place a corresponding object in the request scope. Would it be possible to take it further and declare that the subdomain implements these urls but not those?
Something like?
if request.subdomain.is_blue:
include(these.urls)
the urlconf is executed at startup time, not for each request; so you don't have the opportunity to include or not according to the URL used to acess.
the best would be to write your own middleware, or a restricting decorator (like #login_required), it's quite easy to write your own decorator (i like them more than middlewares for most specific tasks)
You can poke around with request.urlconf, but that can break things