Coder Social home page Coder Social logo

express-enrouten's Introduction

express-enrouten

Build Status
NPM version

Route configuration middleware for expressjs.

Note: express-enrouten >=1.0 is only compatible with express >=4.0. For express 3.x support, please use express-enrouten 0.3.x.

API

app.use(enrouten(options))

var express = require('express'),
    enrouten = require('express-enrouten');

var app = express();
app.use(enrouten({ ... }));
// or app.use('/foo', enrouten({ ... }));

Configuration

express-enrouten supports routes via configuration and convention.

app.use(enrouten({ directory: 'routes' }));

directory

The directory configuration option (optional) is the path to a directory. Specify a directory to have enrouten scan all files recursively to find files that match the controller-spec API. With this API, the directory structure dictates the paths at which handlers will be mounted.

controllers
 |-user
     |-create.js
     |-list.js
// create.js
module.exports = function (router) {
    router.post('/', function (req, res) {
        res.send('ok');
    });
};
app.use(enrouten({
    directory: 'controllers'
}));

Routes are now:

/user/create
/user/list

index

The index configuration option (optional) is the path to the single file to load (which acts as the route 'index' of the application).

app.use(enrouten({
    index: 'routes/'
}));
// index.js
module.exports = function (router) {

    router.get('/', index);
    router.all(passport.protect).get('/account', account);

    // etc...
};

routes

The routes configuration option (optional) is an array of route definition objects. Each definition must have a path and handler property and can have an optional method property (method defaults to 'GET').

Optionally, a middleware property can be provided to specify an array of middleware functions (with typical req, res and next arguments) for that specific route.

Note that a handler has a different function signature than a controller. While a controller takes a single argument (a router), a handler takes the typical req and res pair.

app.use(enrouten({
    routes: [
        { path: '/',    method: 'GET', handler: require('./routes/index') },
        { path: '/foo', method: 'GET', handler: require('./routes/foo') },
        { path: '/admin', method: 'GET', handler: require('./routes/foo'), middleware: [isAuthenticated] }
    ]
}));

routerOptions

The routerOptions configuration option (optional) allows additional options to be specified on each Router instance created by express-enrouten. Please see the Express API documentation for complete documentation on each possible option.

app.set('case sensitive routing', true);
app.use(enrouten({
    directory: 'controllers',
    routerOptions: {
        caseSensitive: true
    }
}));

Named Routes

For index and directory configurations there is also support for named routes. The normal express router that is passed in will always behave as such, but in addition it can be used to name a route, adding the name and path to app.locals.enrouten.routes. For example:

'use strict';

module.exports = function (router) {

    router({ path: '/user/:id', name: 'user-info' })
        .get(function (req, res) {
            res.send('ok');
        });

};

Controller Files

A 'controller' is defined as any require-able file which exports a function that accepts a single argument. Any files with an extension of .js (or .coffee if CoffeeScript is registered) will be loaded and if it exports a function that accepts a single argument then this function will be called. NOTE: Any file in the directory tree that matches the API will be invoked/initialized with the express router object.

// Good :)
// controllers/controller.js
module.exports = function (router) {
    router.get('/', function (req, res) {
        // ...
    });
};

// Bad :(
// Function does not get returned when `require`-ed, use `module.exports`
exports = function (router) {
    // ...
};

// Bad :(
// controllers/other-file-in-same-controller-directory.js
modules.exports = function (config) {
    // `config` will be an express Router
    // ...
};

// Acceptable :)
// controllers/config.json - A non-js file (ignored)
// controllers/README.txt - A non-js file (ignored)
// controllers/util.js - A js file that has a different API than the spec (ignored)
module.exports = {
    importantHelper: function () {

    }
};

Linting

$ npm run-script lint

Tests

$ npm test

Coverage

$ npm run-script cover && open coverage/lcov-report/index.html

express-enrouten's People

Contributors

alexsantos avatar gabrielcsapo avatar grawk avatar jasisk avatar jeffharrell avatar lensam69 avatar pvenkatakrishnan avatar shaunwarman avatar simonexmachina avatar tlivings avatar totherik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

express-enrouten's Issues

API usage is little confused

in README

var express = require('express'),
    enrouten = require('express-enrouten');

var app = express();
express.use(enrouten({ ... });

but in index.js, another express instance is created. so there are two express instances.

Therfore when I use express-enrouten without kraken, I configure some settings in express app, but the settings doesn't apply in controllers.
I guess the reason it's different instance.

Route middleware passed onto other routes

Hi,

I have the following directory structure

  routes
      - v1
           - me
                - index.js
           - groups
                - index.js
                - payments.js

i have made is so that routes/v1/groups/index.js cannot be accessed unless the user is logged on (passport-local)

 const controller = require(global.settings.paths.controllers +
      '/v1/groups/index.js');

 module.exports = function(router) {
      //Must be logged on
      router.use(

           function(req, res, next) {
           if (req.isAuthenticated()) {
                return next();
           } else {
                return error('errors.logged_in.name', 'errors.logged_in.desc', res);
         }
        }
      );

      //Base
      router.get('/', controller.profile);
 };

What i have noticed is that the middleware passed into router.use() is being passed onto routes/v1/groups/payments.js

which is a basic dummy route for now.

  1. Do all of the router.use() middlewares get passed onto subsequent routes?
  2. If so how can i avoid this( ex. do i need to include the middlewares on the individual route?).
  3. Is there an option to eliminate this behaviour?

Ideally, when registering the middleware it would be amazing if you can allow it to persist to different routes on an middleware by middleware basis. Another problem i foresee n my example, is when payments.js is loaded before index.js. if i dont add the middle ware to this script it will be accessible. So there should be some controls as to how routes are being attached.

Any advice and or comments are greatly appreciated!

Thanks

Named routes

Does anyone have a working example with named routes for me? I have tried a few times to get express-enrouten to work with a fresh express.js install, but I cant get it to work.

My installed packages:

  "express": "~4.13.1",
  "express-enrouten": "^1.3.0",
  "express-nunjucks": "^1.0.0",

Thanks

Feature Request: Dynamic parameter handling for directories

I'm often in situations where I'd like to be able to separate out some deeply nested routes based on a root/:param type of situation.

Here are some example routes to illustrate the points:

  • /api/projects
  • /api/projects/:taskId
  • /api/projects/:taskId/team
  • /api/projects/:taskId/team/:teamId

Right now, I'd have one big index.js file in the /api/projects directory for all those routes. What do you think about a structure like this:

/api
  /projects
    index.js
    /_taskId
      index.js
      /team
        index.js
        /_teamId
          index.js

Basically, directories with a leading _ would be converted to parameter routes. I mean, I'll admit it gets a little deep directory wise. But, you could always still just put everything right in the index.js. I think coupled with some CLI tooling/generators this wouldn't be that bad to whip out deep API handlers pretty quickly.

Router level middleware

I might be missing something, but is there currently a way to pass middleware to be used for every request that enrouten makes a route for?

Non-JS files being accidently required

If we have a file called index.js and index.md in the same folder. It will try to require index.md as well as index.js.

It's basically because of these two lines:
https://github.com/krakenjs/express-enrouten/blob/v1.2.x-release/lib/directory.js#L101

impl = require(abs);

This is actually breaking my es6 code coverage attempts with .es6 and .js files in the same folder, where I hoped kraken would ignore the .es6 files.

More or less a dup of #73

Problems using TypeScript for controllers

If I place .ts files under the controllers directory, they are processed by Kraken and when I try to run the app with node index.js it does not run.
Of course I'm compiling .ts into .js files during development.
Is there a way to ignore anything that is different from .js?
Or at least a way to compile .ts files with Grunt.
Thanks!

Files with no extension are being processed by the directory traversal

Referenced from krakenjs/kraken-js#440

The problem is on the express-enrouten module, specifically here: https://github.com/krakenjs/express-enrouten/blob/v1.2.x-release/lib/directory.js#L101-L102

In order to support requireable non-traditional file extensions, (eg: thing.coffee), the file extension is thrown away, and the file is checked using require.resolve().

There are three scenarios here:

  1. controllerFile.js: Extension thrown out, /path/to/controllerFile resolves as a module, since it can be matched to controllerFile.js. It will be processed.
  2. textFile.txt: Extension thrown out, path/to/textFile This does not resolve as a module, since require() can't match it to textFile, textFile.js, textFile.json nor a directory with an index.js file. It will be ignored.
  3. fileWithNoExtension: /path/to/fileWithNoExtension resolves as a module, because it can be matched to a valid existing file (just like the first case). It will be processed.

Case 3 causes issues with SVN-like version control systems, since CVS stores extensionless files in its hidden directories (eg: Entries, Repository, Root).

Creating routes for subdomains

I've searched through the current codebase but do not see any support for registering routes based off of a subdomain as I have a requirement for this and cannot run multiple servers.

For example:

api.service.com/ => api/index.js

Is this on the roadmap or should [I / a contributor] go ahead and work on this functionality?

Doesn't work, doesn't load a page. A browser just freezes in the middle of a request.

The module doesn't allow to load a page. When I enable it as writtent in your manual it doesn't load a page. The browser just freezes in the middle of the request. No errors, no any additional info, just freezes. Here's my index.js of a krakenjs application. No any other alternations of the default kraken.js app is made:

'use strict';

var kraken = require('kraken-js'),
    app = require('express')(),
    db = require('./lib/database'),
    options = {
        onconfig: function (config, next) {
            //any config setup/overrides here
            db.config(config.get('databaseConfig'));

            next(null, config);
        }
    },
    port = process.env.PORT || 8000;


// Here I require enrouten:
var enrouten = require('express-enrouten');

// Here I configure it:
app.use(enrouten({
    routes: [
        { path: '/',    method: 'GET', handler: require('./controllers/index') },
        { path: '/foo', method: 'GET', handler: require('./controllers/foo') }
    ]
}));
app.use(kraken(options));

app.listen(port, function (err) {
    console.log('[%s] Listening on http://localhost:%d', app.settings.env, port);
});

Please write how to configure this module right way. You didin't provide enough info. It doesn't work if you include it in your code as written in your manual.

Fix API

I sooooo hate this API (and have since day one), so this is an issue to finally fix it. Should be:

var app = express();
app.use(enrouten(config));

This fix is trivial and backward compatible, merely creating a placeholder issue so I don't forget. :rage4:

How to get all original paths of registered routes

i have executed

route.get('/', function (...) { ... });
route.get('/foo/:id', function (...) { ... });
route.post('/foo/:id', function (...) { ... });'

in series dictionary
how to show all path, in my project

Route name query

I have added a named route and would like to know how will I get the same via request object.

I want to know the name of the route which got matched.

Example:

router({ path: '/user/:id', name: 'user-info' })
.get(function (req, res) {
//Here I am looking for route name which got matched.
res.send(req.route.name);
});

Router options not inherited by default

This issue is related to krakenjs/kraken-js#281.

If a user enables any of the router-specific options in express, they are not inherited by enrouten-based routes. On the one hand, this is expected behavior given these options don't automatically apply to new Router instances as they're not coupled to any particular app instance. On the other hand, enrouten initializing new Router instances is an implementation detail and the behavior should act more like if routes were registered against the express base router.

The express options that apply to the base router are "case sensitive routing" and "strict routing".

Route dont Match

// Zertifikat Hersteller List
    router({  
        path:   '/' + language + '/' + gettext('url_path1') + '/' + gettext('url_Brands'),
        name:   language + 'Brands'
    }, function(req, res) {

        res.json({hello:'Brands'});
        res.end();

    });

    // Zertifikat Hersteller Detail
    router({  
        path:   '/' + language + '/' + gettext('url_path1') + '/' + gettext('url_Brands') + '/:company',
        name:   language + 'BrandsCompany'
    }, function(req, res) {

        res.json({hello:'BrandsCompany', brand: req.params.company});
        res.end();

    });

i can create the url in the template, but i cant get the URL to process i get only 404 errors, but other urls in the same file looks like the same and work... i dont now what is wrong?

If needed i can give private access to website and source file of the route file

reverse routes within templates and controllers/middleware?

A bit of backstory (because from my experience, most NodeJS people aren't even aware this is a thing)

In Django, the concept of Dont Repeat Yourself is taken quite seriously.

In regards to routes, we only define our routes once in the project or apps urls.py. There we give each route a regex pattern (defining some matches for kwargs and args), a name, a namespace and a controller to handle this matched route.

if for example I have a route like (using python code as an example):

url("^products/(?P<productID>\d+)/$", views.ProductDetailView.as_view(), name="product-detail"),
url("^auth/google/$", views.SocialAuthRedirectView.as_view(), name="social-auth-google")

In a template if I want to generate an url in my controllers (django calls them views):

import reverse

class SocialAuthRedirectView(RedirectView):
    def get_success_url(self, *args, **kwargs):
        return reverse("social-auth-google")

and in my templates (what you guys call views):

{% extends "base.html" %}

{% block content %}
  <a href='{% url "social-auth-google" %}'> login with google </a>
{% endblock %}

So ignoring that i'm using python here to illustrate a deficiency in most nodejs routing modules... (that of Don't Repeat Yourself), using express-enrouten, how would I achieve the above in nodejs?

I'm really not keen on hardcoding urls in my templates or my js modules. it's really bad practice and makes my modules non-portable.

Controller Files and Routes

Folks,
Issue I am having is probably due to not fully understanding how enrouten works. For some reason, the route declarations are being superceded by controller filenames.

Code:

app.js:

var controllerPath = __dirname + '/controllers';
app.use(enrouten({directory: controllerPath }));

controllers/indexController.js

module.exports = function registerRoutes(app){
    app.get('/', pong);
};

function pong(req, rsp) {
    rsp.set('Content-Type', 'application/json');
    var response = {
        ping: 'pong'
    };
    rsp.send(response);
};

For whatever reason, the index URL does not work, ie http://localhost:3000/.

In order for the page to show up, i have to call the controller filename in the uri, ie http://localhost:3000/indexController.js

Problems with .DS_Store Files in the Controllers Directory

Originally reported by @hoffi here.

I use KrakenJS version 1.0.1 on Mac OS X 10.9 and it seems that it has problems when there are .DS_Store files in the Controllers Directory:

.../controllers/.DS_Store:1
    at exports.runInThisContext (vm.js:69:16)
    at Module._compile (module.js:432:25)
    at Object.Module._extensions..js (module.js:467:10)
    at Object..js (/usr/local/Cellar/nvm/0.7.0/v0.11.13/lib/node_modules/node-dev/lib/hook.js:52:17)
    at Module.load (module.js:349:32)
    at Function.Module._load (module.js:305:12)
    at Module.require (module.js:357:17)
    at require (module.js:373:17)
    at handler (.../node_modules/kraken-js/node_modules/express-enrouten/lib/directory.js:61:20)
    at traverse (.../node_modules/kraken-js/node_modules/express-enrouten/lib/directory.js:39:9) 

Add a way to pass configuration into handler setup controllers

As a vague example, maybe something like accepting functions in the form of

module.exports = function (router, config) {
}

This would solve one of the most common questions I get in the context of Kraken: "How do I handle configuration? I can't get to it from here"

Allow to ignore glob path

Hi,
Is it possible to make express-enrouten ignore all .test.js files in my routes/controllers directory ?

Adding development-only routes

I'm having trouble attaching a development-only route in the newest version of express-enrouten. I'd like to continue using the directory option and place my development-only route in that directory. There was a recent change to the argument passed to my routes; an express.Router instance is passed rather than the app itself. I'd argue that passing the app is much more useful. It has info about the current environment, but more than it has all sorts of metadata that I attached to the app that I'd like available in my routes.

Support path-to-regexp somehow?

Is it possible to match a URL like :something/somewhere/somehow with a folder structure that express-enrouten will handle?

multer don't work on middlware

I using krakenJS

router.post('/new', multer({ dest: './public/files'}).single('upl'), function (req, res) {
    console.log(req.body); {}
    console.log(req.file); undefined
    res.send('xD');
  });

If i remove multer({ dest: './public/files'}).single('upl') req.body = {"name": "Foo"}

Not able to upgrade engine-munger(version 1.1.1)

Hi,

I am using the node version of 5.3.0.
I am trying to upgrade the below module.

     I. engine-munger from the version 0.2.8 to 1.1.1
II. adarois from the version 0.1.10 to 1.0.1
III. dustjs-linkedin from the version 2.6.2 to 2.7.2

when I give the command "npm install", it is giving the below error message

Unhandled rejection Error: Cannot find module 'engine-munger/lib/expressView'
at Function.Module._resolveFilename (module.js:326:15)
at Function.Module._load (module.js:277:25)
at Module.require (module.js:354:17)
at require (internal/module.js:12:17)

Can you please provide some suggestions?

@lmarkus

can config muilt directores

can config muilt directores

app.use(enrouten({
    directory:  ['controllers1', ' controllers2']
}));

by the way, now can i use like this as fall back?

app.use(enrouten({
    directory:  'controllers1'
}));
app.use(enrouten({
    directory: ' controllers2'
}));

case sensitive routing

i have enabled case sensitive routing, but i can use mixed strings with upper and lowercase chars.

Special case 'index.js' to default to '/'

With the new routing rules, the file name is used as part of the path. Unfortunately, the convention of using an index.js file in a directory somewhat breaks that behavior, or at least makes it unexpected. This issue proposed to special-case index.js to default to '/' instead of '/index', such that it can be used as the root for that particular path, matching the behavior in Node.js.

Nested routes

Hi,

I am having a problem with nested routes

Currently i have the following dir

routes (main directory for all routes)

  • v1
    • me
      • index.js
    • groups
      • index.js
      • payments.js
  • v2
    -- same as above (ish)

i set up enrouten like so

const app = express();

app.use([
  enrouten({
      directory: 'routes',
      routerOptions: {
           caseSensitive: true
      }
  })
])

I get results for
localhost:4000/v1/me/
localhost:4000/v1/groups/

but i do not get anything from
localhost:4000/v1/groups/payments //-> Or anything within payments.js

//routes/v1/groups/payments.js

'use strict';

 module.exports = function(router) {
      router.get('*', function(req, res) {
           res.send('dog'); // Request continually loads
      });
 };
  1. Is there a limit to how many nested routes enrouten can handle?
  2. If there is what is the limit and where can i find the documentation?
  3. If there is not a limit, what would cause my payments.js route to hang?

Thanks in advance!!

v1.0.0 and express4

Hi,
In the docs there is a mention to version 1.0 for use with express 4.0. Is there an expected release date?

Thanks for the great library.

Project Status

It seems this project is no longer maintained.

Is anyone aware of a successor?
One feature I feel this is missing is nested id routing
/users/:userId/orders/:orderId

dot directories are not ignored

my app wont run and responds with this error

controllers/.svn/all-wcprops:1

looks like the app included the file under the .svn directory..

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.