1
0
Fork 0

Foxx: Starting with the Foxx User Documentation

This commit is contained in:
Lucas Dohmen 2013-03-25 09:50:32 +01:00
parent f483f1f137
commit 74e23f8670
3 changed files with 439 additions and 265 deletions

View File

@ -1,8 +1,64 @@
# Foxx: Build APIs and simple web applications in ArangoDB
Foxx {#UserManualFoxx}
======================
Foxx: Build APIs and simple web applications in ArangoDB
========================================================
**WARNING: The following documentation file is pure fiction,
it is not yet finished**
Foxx is an easy way to create APIs and simple web applications
from within **ArangoDB**.
It is inspired by Sinatra, the classy Ruby web framework. If FoxxApplication is Sinatra,
[ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html)
are the corresponding `Rack`. They provide all the HTTP goodness.
So let's get started, shall we?
## Foxx Application
@copydetails JSF_foxx_application_initializer
@copydetails JSF_foxx_application_start
### Handling Requests
@copydetails JSF_foxx_application_handleRequest
@copydetails JSF_foxx_application_head
@copydetails JSF_foxx_application_get
@copydetails JSF_foxx_application_post
@copydetails JSF_foxx_application_put
@copydetails JSF_foxx_application_patch
@copydetails JSF_foxx_application_delete
### Before and After Hooks
You can use the following two functions to do something
before or respectively after the normal routing process
is happening. You could use that for logging or to manipulate
the request or response (translate it to a certain format for
example).
@copydetails JSF_foxx_application_before
@copydetails JSF_foxx_application_after
### More functionality
@copydetails JSF_foxx_application_helper
@copydetails JSF_foxx_application_accepts
## The functions on a created FoxxApplication
When you have created your FoxxApplication you can now define routes
on it. You provide each with a function that will handle
the request. It gets two arguments (four, to be honest. But the
other two are not relevant for now):
* The request object
* The response object
You can find more about those in their individual sections.
An application build with Foxx is written in JavaScript and deployed
to ArangoDB directly. ArangoDB serves this application, you do not
need a separate application server.

View File

@ -197,18 +197,18 @@ function SetRoutesFoxxApplicationSpec () {
var myFunc = function () {},
routes = app.routingInfo.routes;
app.requires = {
app.requiresLibs = {
a: 1
};
app.models = {
app.requiresModels = {
b: 2
};
app.get('/simple/route', myFunc);
app.start("myContext");
assertEqual(app.routingInfo.routes[0].action.context, "myContext");
assertEqual(app.routingInfo.routes[0].action.requires.a, 1);
assertEqual(app.routingInfo.routes[0].action.models.b, 2);
assertEqual(app.routingInfo.routes[0].action.requiresLibs.a, 1);
assertEqual(app.routingInfo.routes[0].action.requiresModels.b, 2);
}
};
}

View File

@ -1,15 +1,33 @@
/*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true */
/*global module, require, exports */
// Foxx is an easy way to create APIs and simple web applications
// from within **ArangoDB**.
// It is inspired by Sinatra, the classy Ruby web framework. If FoxxApplication is Sinatra,
// [ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html)
// are the corresponding `Rack`. They provide all the HTTP goodness.
//
// So let's get started, shall we?
////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx application
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2013 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Lucas Dohmen
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
// FoxxApplication uses Underscore internally. This library is wonderful.
var FoxxApplication,
BaseMiddleware,
FormatMiddleware,
@ -20,12 +38,19 @@ var FoxxApplication,
INTERNAL = require("internal"),
internal = {};
// ArangoDB uses a certain structure we refer to as `UrlObject`.
// With the following function (which is only internal, and not
// exported) you can create an UrlObject with a given URL,
// a constraint and a method. For example:
//
// internal.createUrlObject('/lecker/gans', null, 'get')
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_createUrlObject
/// @brief create a new url object
///
/// ArangoDB uses a certain structure we refer to as `UrlObject`.
/// With the following function (which is only internal, and not
/// exported) you can create an UrlObject with a given URL,
/// a constraint and a method. For example:
///
/// @EXAMPLES
/// internal.createUrlObject('/lecker/gans', null, 'get')
////////////////////////////////////////////////////////////////////////////////
internal.createUrlObject = function (url, constraint, method) {
'use strict';
var urlObject = {};
@ -44,18 +69,22 @@ internal.createUrlObject = function (url, constraint, method) {
return urlObject;
};
// ## Creating a new Application
// And that's FoxxApplication. It's a constructor, so call it like this:
//
// app = new FoxxApplication({
// urlPrefix: "/wiese",
// templateCollection: "my_templates"
// })
//
// It takes two optional arguments as displayed above:
//
// * **The URL Prefix:** All routes you define within will be prefixed with it
// * **The Template Collection:** More information in the template section
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_initializer
/// @brief Create a new Application
///
/// And that's FoxxApplication. It's a constructor, so call it like this:
/// It takes two optional arguments as displayed above:
/// * **The URL Prefix:** All routes you define within will be prefixed with it
/// * **The Template Collection:** More information in the template section
///
/// @EXAMPLES
/// app = new FoxxApplication({
/// urlPrefix: "/wiese",
/// templateCollection: "my_templates"
/// });
////////////////////////////////////////////////////////////////////////////////
FoxxApplication = function (options) {
'use strict';
var urlPrefix, templateCollection, myMiddleware;
@ -91,23 +120,17 @@ FoxxApplication = function (options) {
];
};
// ## The functions on a created FoxxApplication
//
// When you have created your FoxxApplication you can now define routes
// on it. You provide each with a function that will handle
// the request. It gets two arguments (four, to be honest. But the
// other two are not relevant for now):
//
// * The request object
// * The response object
//
// You can find more about those in their individual sections.
_.extend(FoxxApplication.prototype, {
// Sometimes it is a good idea to actually start the application
// you wrote. If this precious moment has arrived, you should
// use this function.
// You have to provide the start function with the `applicationContext`
// variable.
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_start
/// @brief Start the application
///
/// Sometimes it is a good idea to actually start the application
/// you wrote. If this precious moment has arrived, you should
/// use this function.
/// You have to provide the start function with the `applicationContext`
/// variable.
////////////////////////////////////////////////////////////////////////////////
start: function (context) {
'use strict';
var models = this.requiresModels,
@ -125,18 +148,24 @@ _.extend(FoxxApplication.prototype, {
db._collection("_routing").save(this.routingInfo);
},
// The `handleRequest` method is the raw way to create a new
// route. You probably wont call it directly, but it is used
// in the other request methods:
//
// app.handleRequest("get", "/gaense", function (req, res) {
// //handle the request
// });
//
// When defining a route you can also define a so called 'parameterized'
// route like `/gaense/:stable`. In this case you can later get the value
// the user provided for `stable` via the `params` function (see the Request
// object).
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_handleRequest
/// @brief Handle a request
///
/// The `handleRequest` method is the raw way to create a new
/// route. You probably wont call it directly, but it is used
/// in the other request methods:
///
/// When defining a route you can also define a so called 'parameterized'
/// route like `/gaense/:stable`. In this case you can later get the value
/// the user provided for `stable` via the `params` function (see the Request
/// object).
///
/// @EXAMPLES
/// app.handleRequest("get", "/gaense", function (req, res) {
/// //handle the request
/// });
////////////////////////////////////////////////////////////////////////////////
handleRequest: function (method, route, argument1, argument2) {
'use strict';
var newRoute = {}, options, callback;
@ -157,97 +186,124 @@ _.extend(FoxxApplication.prototype, {
this.routingInfo.routes.push(newRoute);
},
// ### Handle a `head` request
// This handles requests from the HTTP verb `head`.
// As with all other requests you can give an option as the third
// argument, or leave it blank. You have to give a function as
// the last argument however. It will get a request and response
// object as its arguments
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_head
/// @brief Handle a `head` request
///
/// This handles requests from the HTTP verb `head`.
/// As with all other requests you can give an option as the third
/// argument, or leave it blank. You have to give a function as
/// the last argument however. It will get a request and response
/// object as its arguments
////////////////////////////////////////////////////////////////////////////////
head: function (route, argument1, argument2) {
'use strict';
this.handleRequest("head", route, argument1, argument2);
},
// ### Manage a `get` request
// This handles requests from the HTTP verb `get`.
// See above for the arguments you can give. An example:
//
// app.get('/gaense/stall', function (req, res) {
// // Take this request and deal with it!
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_get
/// @brief Manage a `get` request
///
/// This handles requests from the HTTP verb `get`.
/// See above for the arguments you can give. An example:
///
/// @EXAMPLES
/// app.get('/gaense/stall', function (req, res) {
/// // Take this request and deal with it!
/// });
////////////////////////////////////////////////////////////////////////////////
get: function (route, argument1, argument2) {
'use strict';
this.handleRequest("get", route, argument1, argument2);
},
// ### Tackle a `post` request
// This handles requests from the HTTP verb `post`.
// See above for the arguments you can give. An example:
//
// app.post('/gaense/stall', function (req, res) {
// // Take this request and deal with it!
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_post
/// @brief Tackle a `post` request
///
/// This handles requests from the HTTP verb `post`.
/// See above for the arguments you can give. An example:
///
/// @EXAMPLES
/// app.post('/gaense/stall', function (req, res) {
/// // Take this request and deal with it!
/// });
////////////////////////////////////////////////////////////////////////////////
post: function (route, argument1, argument2) {
'use strict';
this.handleRequest("post", route, argument1, argument2);
},
// ### Sort out a `put` request
// This handles requests from the HTTP verb `put`.
// See above for the arguments you can give. An example:
//
// app.put('/gaense/stall', function (req, res) {
// // Take this request and deal with it!
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_put
/// @brief Sort out a `put` request
///
/// This handles requests from the HTTP verb `put`.
/// See above for the arguments you can give. An example:
///
/// @EXAMPLES
/// app.put('/gaense/stall', function (req, res) {
/// // Take this request and deal with it!
/// });
////////////////////////////////////////////////////////////////////////////////
put: function (route, argument1, argument2) {
'use strict';
this.handleRequest("put", route, argument1, argument2);
},
// ### Take charge of a `patch` request
// This handles requests from the HTTP verb `patch`.
// See above for the arguments you can give. An example:
//
// app.patch('/gaense/stall', function (req, res) {
// // Take this request and deal with it!
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_patch
/// @brief Take charge of a `patch` request
///
/// This handles requests from the HTTP verb `patch`.
/// See above for the arguments you can give. An example:
///
/// @EXAMPLES
/// app.patch('/gaense/stall', function (req, res) {
/// // Take this request and deal with it!
/// });
////////////////////////////////////////////////////////////////////////////////
patch: function (route, argument1, argument2) {
'use strict';
this.handleRequest("patch", route, argument1, argument2);
},
// ### Respond to a `delete` request
// This handles requests from the HTTP verb `delete`.
// See above for the arguments you can give.
// **A word of warning:** Do not forget that `delete` is
// a reserved word in JavaScript so call it as follows:
//
// app['delete']('/gaense/stall', function (req, res) {
// // Take this request and deal with it!
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_delete
/// @brief Respond to a `delete` request
///
/// This handles requests from the HTTP verb `delete`.
/// See above for the arguments you can give.
/// **A word of warning:** Do not forget that `delete` is
/// a reserved word in JavaScript so call it as follows:
///
/// @EXAMPLES
/// app['delete']('/gaense/stall', function (req, res) {
/// // Take this request and deal with it!
/// });
////////////////////////////////////////////////////////////////////////////////
'delete': function (route, argument1, argument2) {
'use strict';
this.handleRequest("delete", route, argument1, argument2);
},
// ## Before and After Hooks
// You can use the following two functions to do something
// before or respectively after the normal routing process
// is happening. You could use that for logging or to manipulate
// the request or response (translate it to a certain format for
// example).
// ### Before
// The before function takes a path on which it should watch
// and a function that it should execute before the routing
// takes place. If you do omit the path, the function will
// be executed before each request, no matter the path.
// Your function gets a Request and a Response object.
// An example:
//
// app.before('/high/way', function(req, res) {
// //Do some crazy request logging
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_before
/// @brief Before
///
/// The before function takes a path on which it should watch
/// and a function that it should execute before the routing
/// takes place. If you do omit the path, the function will
/// be executed before each request, no matter the path.
/// Your function gets a Request and a Response object.
/// An example:
///
/// @EXAMPLES
/// app.before('/high/way', function(req, res) {
/// //Do some crazy request logging
/// });
////////////////////////////////////////////////////////////////////////////////
before: function (path, func) {
'use strict';
if (_.isUndefined(func)) {
@ -263,16 +319,21 @@ _.extend(FoxxApplication.prototype, {
});
},
// ### After
// This works pretty similar to the before function.
// But it acts after the execution of the handlers
// (Big surprise, I suppose).
//
// An example:
//
// app.after('/high/way', function(req, res) {
// //Do some crazy response logging
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_after
/// @brief After
///
/// This works pretty similar to the before function.
/// But it acts after the execution of the handlers
/// (Big surprise, I suppose).
///
/// An example:
///
/// @EXAMPLES
/// app.after('/high/way', function(req, res) {
/// //Do some crazy response logging
/// });
////////////////////////////////////////////////////////////////////////////////
after: function (path, func) {
'use strict';
if (_.isUndefined(func)) {
@ -288,27 +349,36 @@ _.extend(FoxxApplication.prototype, {
});
},
// ## The ViewHelper concept
// If you want to use a function inside your templates, the ViewHelpers
// will come to rescue you. Define them on your app like this:
//
// app.helper("link_to", function (identifier) {
// return urlRepository[identifier];
// });
//
// Then you can just call this function in your template's JavaScript
// blocks.
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_helper
/// @brief The ViewHelper concept
///
/// If you want to use a function inside your templates, the ViewHelpers
/// will come to rescue you. Define them on your app like this:
///
/// @EXAMPLES
/// app.helper("link_to", function (identifier) {
/// return urlRepository[identifier];
/// });
///
/// Then you can just call this function in your template's JavaScript
/// blocks.
////////////////////////////////////////////////////////////////////////////////
helper: function (name, func) {
'use strict';
this.helperCollection[name] = func;
},
// ## Shortform for using the FormatMiddleware
//
// More information about the FormatMiddleware in the corresponding section.
// This is a shortcut to add the middleware to your application:
//
// app.accepts(["json"], "json");
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_application_accepts
/// @brief Shortform for using the FormatMiddleware
///
/// More information about the FormatMiddleware in the corresponding section.
/// This is a shortcut to add the middleware to your application:
///
/// @EXAMPLES
/// app.accepts(["json"], "json");
////////////////////////////////////////////////////////////////////////////////
accepts: function (allowedFormats, defaultFormat) {
'use strict';
@ -322,9 +392,13 @@ _.extend(FoxxApplication.prototype, {
});
// ## The Base Middleware
// The `BaseMiddleware` manipulates the request and response
// objects to give you a nicer API.
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_initializer
/// @brief The Base Middleware
///
/// The `BaseMiddleware` manipulates the request and response
/// objects to give you a nicer API.
////////////////////////////////////////////////////////////////////////////////
BaseMiddleware = function (templateCollection, helperCollection) {
'use strict';
var middleware = function (request, response, options, next) {
@ -332,29 +406,39 @@ BaseMiddleware = function (templateCollection, helperCollection) {
requestFunctions,
_ = require("underscore");
// ### The Request Object
// Every request object has the following attributes from the underlying Actions,
// amongst others:
//
// * path: The complete path as supplied by the user
//
// FoxxApplication adds the following methods to this request object:
////////////////////////////////////////////////////////////////////////////////
/// The Request Object
/// Every request object has the following attributes from the underlying Actions,
/// amongst others:
///
/// * path: The complete path as supplied by the user
///
/// FoxxApplication adds the following methods to this request object:
////////////////////////////////////////////////////////////////////////////////
requestFunctions = {
// ### The superfluous `body` function
// Get the body of the request
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_request_body
/// @brief The superfluous `body` function
///
/// Get the body of the request
////////////////////////////////////////////////////////////////////////////////
body: function () {
return this.requestBody;
},
// ### The jinxed `params` function
// Get the parameters of the request. This process is two-fold:
//
// 1. If you have defined an URL like `/test/:id` and the user
// requested `/test/1`, the call `params("id")` will return `1`.
// 2. If you have defined an URL like `/test` and the user gives a
// query component, the query parameters will also be returned.
// So for example if the user requested `/test?a=2`, the call
// `params("a")` will return `2`.
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_request_params
/// @brief The jinxed `params` function
///
/// Get the parameters of the request. This process is two-fold:
///
/// 1. If you have defined an URL like `/test/:id` and the user
/// requested `/test/1`, the call `params("id")` will return `1`.
/// 2. If you have defined an URL like `/test` and the user gives a
/// query component, the query parameters will also be returned.
/// So for example if the user requested `/test?a=2`, the call
/// `params("a")` will return `2`.
////////////////////////////////////////////////////////////////////////////////
params: function (key) {
var ps = {};
_.extend(ps, this.urlParameters);
@ -363,36 +447,50 @@ BaseMiddleware = function (templateCollection, helperCollection) {
}
};
// ### The Response Object
// Every response object has the following attributes from the underlying Actions:
//
// * contentType
// * responseCode
// * body
// * headers (an object)
//
// FoxxApplication adds the following methods to this response object.
////////////////////////////////////////////////////////////////////////////////
/// The Response Object
/// Every response object has the following attributes from the underlying Actions:
///
/// * contentType
/// * responseCode
/// * body
/// * headers (an object)
///
/// FoxxApplication adds the following methods to this response object.
////////////////////////////////////////////////////////////////////////////////
responseFunctions = {
// ### The straightforward `status` function
// Set the status code of your response, for example:
//
// response.status(404);
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_response_status
/// @brief The straightforward `status` function
///
/// Set the status code of your response, for example:
///
/// @EXAMPLES
/// response.status(404);
////////////////////////////////////////////////////////////////////////////////
status: function (code) {
this.responseCode = code;
},
// ### The radical `set` function
// Set a header attribute, for example:
//
// response.set("Content-Length", 123);
// response.set("Content-Type", "text/plain");
//
// or alternatively:
//
// response.set({
// "Content-Length": "123",
// "Content-Type": "text/plain"
// });
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_response_set
/// @brief The radical `set` function
///
/// Set a header attribute, for example:
///
/// @EXAMPLES
/// response.set("Content-Length", 123);
/// response.set("Content-Type", "text/plain");
///
/// or alternatively:
///
/// @EXAMPLES
/// response.set({
/// "Content-Length": "123",
/// "Content-Type": "text/plain"
/// });
////////////////////////////////////////////////////////////////////////////////
set: function (key, value) {
var attributes = {};
if (_.isUndefined(value)) {
@ -412,46 +510,57 @@ BaseMiddleware = function (templateCollection, helperCollection) {
}, this);
},
// ### The magical `json` function
// Set the content type to JSON and the body to the
// JSON encoded object you provided.
//
// response.json({'born': 'December 12, 1915'});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_response_json
/// @brief The magical `json` function
///
/// Set the content type to JSON and the body to the
/// JSON encoded object you provided.
///
/// @EXAMPLES
/// response.json({'born': 'December 12, 1915'});
////////////////////////////////////////////////////////////////////////////////
json: function (obj) {
this.contentType = "application/json";
this.body = JSON.stringify(obj);
},
// ### The mysterious `render` function
// If you initialize your FoxxApplication with a `templateCollection`,
// you're in luck now.
// It expects documents in the following form in this collection:
//
// {
// path: "high/way",
// content: "hallo <%= username %>",
// contentType: "text/plain",
// templateLanguage: "underscore"
// }
//
// The `content` is the string that will be rendered by the template
// processor. The `contentType` is the type of content that results
// from this call. And with the `templateLanguage` you can choose
// your template processor. There is only one choice now: `underscore`.
//
// If you call render, FoxxApplication will look
// into the this collection and search by the path attribute.
// It will then render the template with the given data:
//
// response.render("high/way", {username: 'FoxxApplication'})
//
// Which would set the body of the response to `hello FoxxApplication` with the
// template defined above. It will also set the `contentType` to
// `text/plain` in this case.
//
// In addition to the attributes you provided, you also have access to
// all your view helpers. How to define them? Read above in the
// ViewHelper section.
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_BaseMiddleware_response_render
/// @brief The mysterious `render` function
///
/// If you initialize your FoxxApplication with a `templateCollection`,
/// you're in luck now.
/// It expects documents in the following form in this collection:
///
/// @EXAMPLES
/// {
/// path: "high/way",
/// content: "hallo <%= username %>",
/// contentType: "text/plain",
/// templateLanguage: "underscore"
/// }
///
/// The `content` is the string that will be rendered by the template
/// processor. The `contentType` is the type of content that results
/// from this call. And with the `templateLanguage` you can choose
/// your template processor. There is only one choice now: `underscore`.
///
/// If you call render, FoxxApplication will look
/// into the this collection and search by the path attribute.
/// It will then render the template with the given data:
///
/// @EXAMPLES
/// response.render("high/way", {username: 'FoxxApplication'})
///
/// Which would set the body of the response to `hello FoxxApplication` with the
/// template defined above. It will also set the `contentType` to
/// `text/plain` in this case.
///
/// In addition to the attributes you provided, you also have access to
/// all your view helpers. How to define them? Read above in the
/// ViewHelper section.
////////////////////////////////////////////////////////////////////////////////
render: function (templatePath, data) {
var template;
@ -474,9 +583,9 @@ BaseMiddleware = function (templateCollection, helperCollection) {
}
};
// Now enhance the request and response as described above and call next at the
// end of this middleware (otherwise your application would never
// be executed. Would be a shame, really).
/// Now enhance the request and response as described above and call next at the
/// end of this middleware (otherwise your application would never
/// be executed. Would be a shame, really).
request = _.extend(request, requestFunctions);
response = _.extend(response, responseFunctions);
next();
@ -488,32 +597,37 @@ BaseMiddleware = function (templateCollection, helperCollection) {
};
};
// ## The Format Middleware
// Unlike the `BaseMiddleware` this Middleware is only loaded if you
// want it. This Middleware gives you Rails-like format handling via
// the `extension` of the URL or the accept header.
// Say you request an URL like `/people.json`:
// The `FormatMiddleware` will set the format of the request to JSON
// and then delete the `.json` from the request. You can therefore write
// handlers that do not take an `extension` into consideration and instead
// handle the format via a simple String.
// To determine the format of the request it checks the URL and then
// the `accept` header. If one of them gives a format or both give
// the same, the format is set. If the formats are not the same,
// an error is raised.
//
// Use it by calling:
//
// FormatMiddleware = require('foxx').FormatMiddleware;
// app.before("/*", FormatMiddleware.new(['json']));
//
// or the shortcut:
//
// app.accepts(['json']);
//
// In both forms you can give a default format as a second parameter,
// if no format could be determined. If you give no `defaultFormat` this
// case will be handled as an error.
////////////////////////////////////////////////////////////////////////////////
/// @brief The Format Middleware
///
/// Unlike the `BaseMiddleware` this Middleware is only loaded if you
/// want it. This Middleware gives you Rails-like format handling via
/// the `extension` of the URL or the accept header.
/// Say you request an URL like `/people.json`:
/// The `FormatMiddleware` will set the format of the request to JSON
/// and then delete the `.json` from the request. You can therefore write
/// handlers that do not take an `extension` into consideration and instead
/// handle the format via a simple String.
/// To determine the format of the request it checks the URL and then
/// the `accept` header. If one of them gives a format or both give
/// the same, the format is set. If the formats are not the same,
/// an error is raised.
///
/// Use it by calling:
///
/// @EXAMPLES
/// FormatMiddleware = require('foxx').FormatMiddleware;
/// app.before("/*", FormatMiddleware.new(['json']));
///
/// or the shortcut:
///
/// @EXAMPLES
/// app.accepts(['json']);
///
/// In both forms you can give a default format as a second parameter,
/// if no format could be determined. If you give no `defaultFormat` this
/// case will be handled as an error.
////////////////////////////////////////////////////////////////////////////////
FormatMiddleware = function (allowedFormats, defaultFormat) {
'use strict';
var stringRepresentation, middleware = function (request, response, options, next) {
@ -588,8 +702,8 @@ FormatMiddleware = function (allowedFormats, defaultFormat) {
};
};
// We finish off with exporting FoxxApplication and the middlewares.
// Everything else will remain our secret.
/// We finish off with exporting FoxxApplication and the middlewares.
/// Everything else will remain our secret.
////////////////////////////////////////////////////////////////////////////////
/// @brief loads a manifest file
@ -654,11 +768,15 @@ exports.FoxxApplication = FoxxApplication;
exports.BaseMiddleware = BaseMiddleware;
exports.FormatMiddleware = FormatMiddleware;
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
// End:
/// -----------------------------------------------------------------------------
/// --SECTION-- END-OF-FILE
/// -----------------------------------------------------------------------------
/// Local Variables:
/// mode: outline-minor
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
/// End: