SkillAgentSearch skills...

Bogart

Fast, Sinatra-Inspired JavaScript Framework running on JSGI with Node.JS!

Install / Use

/learn @nrstott/Bogart
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Build Status

Bogart

A blazing fast rapid application development web framework using JSGI for node.

Getting Started

Bogart can be installed via npm.

npm install bogart

Alternatively, clone the git repository.

git clone git://github.com/nrstott/bogart.git

Hello World in Bogart

Make a directory: mkdir hello-world

Create the following file:

app.js

var bogart = require('bogart');

var router = bogart.router();
router.get('/', function(req) { 
  return "hello world"; 
});

router.get('/:name', function(req) {
  return 'hello '+req.params.name;
});

var app = bogart.app();
app.use(bogart.batteries({secret: "my-super-secret"})); // A batteries included JSGI stack including streaming request body parsing, session, flash, and much more.
app.use(router); // Our router

app.start();

Start your app: node app.js

Visit it in a web browser at http://localhost:8080. Visit the route that says hello to you by name at http://localhost:8080/bob

Changing the port

If you can't run on 8080, change the app.start call e.g. app.start(9090, '127.0.0.1')

Routing

Routing in Bogart is simple and intuitive. A route is an HTTP method paired with an URL matching pattern and a handler function.

var router = bogart.router();
router.get('/', function(req) {
  return bogart.html('Hello World');
});

Routes are tested for matches in the order in which they are defined.

Route Patterns

Route patterns are matched against URLs. They may include named parameters that will be accessible via the params object of the req object passed to the route handler.

var router = bogart.router();
router.get('/hello/:name', function(req) {
  var greeting = 'Hello '+req.params.name;
  return bogart.html(greeting);
});

Route patterns support wildcards. Wildcards will match anything whereas regular named parameters will not match beyond a path separator ("/").

var router = bogart.router();
router.get('/hello/*', function(req, name) {
    return bogart.html('Hello '+req.params.splat[0]);
});

No Route Found

When no route pattern matches the request, a next jsgi application to be called may be specified either with the Router#notFound method or via a parameter to the function returned by bogart:router. If both techniques are used, then the parameter overrides the app specified by the Router#notFound method.

Specified by calling the Router#notFound method

var myRouter = bogart.myRouter();
router.get('/', index);
myRouter.notFound(function (req) {
  return bogart.html('Not Found', { status: 404 });
});

Specified as a parameter to the router

var myRouter = bogart.router();
myRouter.get('/', index);

var app = bogart.app();
app.use(myRouter(function (req) {
  return {
    status: 404,
    body: [ 'Not Found' ]
  };
}))

Regex Routes

When a route pattern is not powerful enough, regular expressions may be used to specify which URLs are to be matched.

var router = bogart.router();
router.get(/\/posts?/, function(req) {
  // Matches 'post' or 'posts'
  return bogart.html('Regex Route');
});

Parameters are via regular expression groups in regular expression routes. The parameter values are put in an Array in req.params.splat of the req object passed to the route handler.

var router = bogart.router();
router.get(/hello-(.*)/, function(req) {
  var name = req.params.splat[0];
  return bogart.html('Hello '+name);
});

Custom HTTP Verbs

To handle HTTP Verbs other than get, post, put, and delete, the route method of Router can be invoked.

var router = bogart.router();
router.route('options', '/', function (req) {
  // Logic for handling the request goes here.
});

Bogart Application

bogart.app makes it easy to setup a middleware chain and start coding. Combined with bogart.batteries (See Below), you can setup a full-stack JSGI application in two lines of code.

var app = bogart.app();
app.use(bogart.batteries({ secret: "my-super-secret" });

After adding bogart.batteries, you will normally want to add a Router. This is also done with app.use. To start the application, use the start method.

var app = bogart.app();
app.use(bogart.batteries({ secret: "my-super-secret" }));

var router = bogart.router();
// NOTE: Here you would normally add some routes.

app.use(router);
app.start();

Response Helpers

Bogart includes helpers for creating JSGI Responses. The helpers, by convention, take a final parameter of an options object that allows the caller to override defaults. The options object is merged with the default JSGI Response values of the helper before the JSGI Response is returned.

Respond with JSON

Helper to create an HTTP 200 Success response with a Content-Type of application/json.

Sample Route:

var router = bogart.router();
router.get('/', function(req) {
  return bogart.json({ framework: 'Bogart' });
});

This route yields the following JSGI Response:

{
  status: 200,
  headers: { 'Content-Type': 'application/json' },
  body: [ '{ "framework": "Bogart" }' ]
}

Respond with CORS headers

Helper to send a JSON response with 'Access-Control-Allow-Origin', 'Access-Control-Allow-Methods', and 'Access-Control-Allow-Headers' headers to faciliate Cross-Origin Resource Sharing (CORS).

Sample Route:

var router = bogart.router();
router.get('/', function(req) {
  return bogart.cors({ framework: 'Bogart' });
});

This route yields the following JSGI Response:

{
  status: 200,
  headers: { 
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
    'Access-Control-Allow-Headers': 'x-requested-with,*'
  },
  body: [ '{ "framework": "Bogart" }' ]
}

Redirect

Helper to create an HTTP 302 Temporary Redirect response.

Sample Route:

var router = bogart.router();
router.get('/', function(req) {
  return bogart.redirect('/some/other/url');
});

This route yields the following JSGI Response:

{
  status: 302,
  headers: { 'Location': '/some/other/url' },
  body: []
}

Error

Helper to create an HTTP 500 Internal Server Error response.

Sample Route:

var router = bogart.router();
router.get('/', function(req) {
  return bogart.error('<html>...</html>');
});

This route yields the following JSGI Response:

{
  status: 500,
  headers: { 'Content-Type': 'text/html' },
  body: [ '<html>...</html>' ]
}

Not Modified

Helper to create an HTTP 304 Not Modified response.

Sample Route:

var router = bogart.router();
router.get('/', function(req) {
  return bogart.notModified();
});

This route yields the following JSGI Response:

{
  status: 304,
  headers: {},
  body: []
}

File (Streaming!)

Helper to create an HTTP 200 Success response with a body streamed from the contents of a file. The Content-Type of the response is determined by the mime type of the file.

Sample Route:

var path = require('path');

var router = bogart.router();
router.get('/download/*', function(req) {
  var filePath = path.join(__dirname, 'public', req.params.splat[0]);

  return bogart.file(filePath);
});

This route yields the following JSGI Response:

{
  status: 200,
  headers: { 'Content-Type': '<mimetype of the file>' },
  body: fileStream // <-- A file stream
}

Proxy (Streaming!)

Helper to create a response that proxies the response from a URL.

Sample Route:

var router = bogart.router();
router.get('/google', function(req) {
  return bogart.proxy('http://www.google.com');
});

This route yields a JSGI Response that matches the response from the proxied URL.

Imperative Response Builder

Bogart includes the ResponseBuilder helper to provide an imperative interface. While not recommended as a goto style of programming in Bogart, there are times when buiding a response imperatively makes for cleaner, better code. This is true especially when working with callback based functions that cannot be wrapped by bogart.promisify.

var router = bogart.router();
router.get('/', function(req) {

  // Get a ResponseBuilder
  var res = bogart.res();

  doSomethingAsync(function(err, messageStr) {
    res.setHeader('Content-Type', 'text/plain');

    if (err) {
      res.status(500);
      res.send('Error');
      return res.end(); // We use return to break out of the function, do not want to continue executing after res.end()
    }

    res.status(200);
    res.send(messageStr);
    res.end(); // End the Response.  This is analagous to resolving a promise for a JSGI Response.
  });

  return res;
});

Using Session

The session middleware can be included individually with app.use(bogart.middleware.session) or by using batteries app.use(bogart.batteries) which includes a default stack of JSGI middleware.

A session function will be available on the request object passed to your route handlers. This function follows the jQuery style of arity determining if it is getting or setting a key/value pair. A call to session with one argument is a get to the value of the key referenced by the argument.

req.session('name'); // => value associated with 'name'

A call to session with two arguments is a set.

req.session('name', 'Nathan'); // sets the value of 'name' to 'Nathan'

Contrived Example

A set of two routes that use session:

router.get('/:name', function(req) {
  req.session('name', req.params.name);
  return bogart.redirect(

Related Skills

View on GitHub
GitHub Stars165
CategoryDevelopment
Updated3y ago
Forks29

Languages

JavaScript

Security Score

65/100

Audited on Jul 10, 2022

No findings