Features:
Here's a simple Midnight application:
const midnight = require("midnight");
const app = midnight();
app.route("/", (req, res) => {
res.send("Hello world!");
});
app.start();
That's it.
Let's take a closer look on how to get application up and running.
Install Midnight using Yarn:
yarn add midnight
Or using Node Packaged Modules:
npm install midnight
Prerequisites for running a Midnight application are now installed. Next step is to create a new application.
Create new file called app.js
with following contents:
const midnight = require("midnight");
const app = midnight();
app.route("/", (req, res) => {
res.send("Hello world!");
});
app.start();
Next step is to run the application:
node app.js
Well done, application is now running at http://localhost:8080.
Scroll down to learn more about the Midnight framework.
Setting a new route is super easy:
app
.route("/", (req, res) => {
res
.status(200)
.content("text/plain")
.send("Hello world!");
})
.method(["GET", "POST"]); // Allow GET and POST requests
Route parameters can be captured as shown below:
app
.route("/post/:id", (req, res) => {
app.log.info("Get post id %s", req.params.id);
res
.status(200)
.set("Content-Type", "text/plain")
.send("Hello world!");
})
.get(); // Allow GET requests only
Define route groups:
const group = app.route("/group/:group");
// Apply middleware to route group
group.use((req, res, next) => {
res.set("Has-Parent-Middleware", true);
next();
});
// /group/:group
group.route("/", (req, res) => {
res.send("Route group /");
});
// /group/:group/foo/:id
group.route("/foo/:id", (req, res) => {
res.send(req.params);
});
See Route and app.route for more detailed documentation.
Midnight is fully compatible with Connect framework.
Following example will populate request.query object containing HTTP GET parameters:
const compression = require("compression");
// Gzip/deflate all outgoing responses
app.use(compression());
app.route("/", (req, res) => {
res.status(200).send(JSON.stringify(req.query));
});
In case a route specific middleware is required:
const bodyParser = require("body-parser");
app
.route("/", (req, res) => {
res.status(200).send(JSON.stringify(req.body));
})
// Parse urlencoded request bodies into req.body
.use(bodyParser.urlencoded({ extended: false }));
It's also possible to create a custom middleware:
app.use((req, res, next) => {
// Use X-Custom-Header response header with every request
res.set("X-Custom-Header", true);
next();
});
app.route("/", (req, res) => {
res.send("Response status is 200");
});
Serving static files with Midnight and Connect is easy:
const serveStatic = require("serve-static");
app.use(serveStatic(path.join(app.config.root, 'static')))
Example above serves static files with a following directory layout:
Requesting http://localhost:8080/stylesheets/style.css serves the stylesheets with ease.
Midnight has a flexible plugin system built-in to easily extend the application.
Here's how to create a new plugin:
const skyColorPlugin = {
name: "sky-plugin",
attach: (app, options = {}) => {
// Called when plugin is attached
// Options can be passed as a parameter
this.options = options;
},
init: (app, next) => {
// Called when the application is initialized
app.sky = this.options.color;
// Call next() when done extending the app
next();
}
};
// Attach the plugin with parameters
// Plugin extends the app with `sky` property
app.plugin(skyColorPlugin, {
color: "blue"
});
Application server won't start until all the plugins are initialized.
Plenty of more examples included with the source code.
Go to Github and browse the repository.
app.configure({
port: 9000,
views: '/templates'
});
app.log.info('Server will run at port %s', app.config.port);
To reveal the default configuration:
app.log.info(JSON.stringify(app.config));
{
'host': '127.0.0.1',
'port': 8080,
'views': '/views',
'root': '/application/root/path',
'env': 'development',
'version': '0.0.1'
}
Start the application.
app.start();
Alternatively, start the server with configuration parameter.
app.start({
port: 9000
});
Set log level:
// Default logging level
app.config.log = app.log.level.info;
Logging.
// Trace
app.log.trace('Finely detailed information');
// Debug
app.log.debug('Detailed information');
// Info
app.log.info('Interesting runtime events');
// Warning
app.log.warn('Runtime situations that are undesirable');
// Error
app.log.error('Runtime errors or unexpected conditions');
// Fatal
app.log.fatal('This is very bad');
Declare a new route:
app.route('/post/:id', (req, res) => {
res.send(req.params);
});
Use regular expression as a route pattern:
// Accept requests with url /route/{parameter}
app.route(new RegExp('^\\/route\/(?:([^\\/]+?))\\/?$', 'i'), (req, res) => {
res.send(req.params);
});
Routes can be used like below to set additional parameters:
app.route('/', (req, res) => {
res.send('Hello world!');
}).get(); // Allow GET requests only
Leave handler argument out to simply use route specific middleware:
// Use custom middleware for specific route only
app.route('/specific/route').use(yourMiddlewareHere);
See Router for more examples.
Provides few useful tools, see Github for complete list.
Use middleware for all the requests.
app.use(globalMiddlewareHere);
Attach a plugin to the application.
app.plugin(plugin);
See Plugins for more examples.
See Router for examples on how to define routes.
Specify allowed methods for the route
// Accept GET requests
route.method('GET');
// Accept GET, POST and DELETE requests
route.method(['GET', 'POST', 'DELETE']);
Above is equivalent to:
// Accept GET requests
route.get();
// Accept GET, POST and DELETE requests
route.get().post().delete();
All HTTP methods are allowed in case no method is specified.
Allow GET requests.
route.get();
Allow POST requests.
route.post();
Allow PUT requests.
route.put();
Allow DELETE requests.
route.delete();
Use middleware for specific route.
const bodyParser = require("body-parser");
app
.route("/", (req, res) => {
res.status(200).send(JSON.stringify(req.body));
})
// Parse urlencoded request bodies into req.body
.use(bodyParser.urlencoded({ extended: false }));
Define subroute (route group)
const group = app.route("/group/:group");
// /group/:group/foo/:id
group.route("/foo/:id", (req, res) => {
res.send(req.params);
});
Get request method.
Get request header.
request.get('Content-Type');
Get request Content-Type
.
request.content();
Set status code.
response.status(200);
Set response header.
// Set response header
response.set('Access-Control-Allow-Origin', '*');
// Remove response header
response.set('Access-Control-Allow-Origin');
Get response header.
response.get('Content-Type');
Set Content-Type
response header.
// Set response header
response.content('image/png');
// Get response header
response.content();
Redirect to a location.
response.redirect('/');
Set response encoding.
response.encoding('utf-8');
Send a response.
// Content-Type: text/html
response.send('Hello world!');
Depending on the object type different Content-Type
header is used:
// Content-Type: application/json
response.send({ name: 'Harry' });
// Content-Type: application/json
response.send(['Apples', 'Oranges']);
// Content-Type: application/octet-stream
response.send(new Buffer('Hello world!'));
This method automatically adds Content-Length
header for the response.