Overview

更新时间:
2024-05-15
下载文档

Overview

The webapp object conventionally denotes the application. The webapp object has methods for:

  • Routing HTTP requests; see for example, app.METHOD().
  • Configuring middleware; see app.route().
  • Rendering HTML views; see app.render().
  • Registering a template engine; see app.engine().

It also has settings (properties) that affect how the application behaves; for more information, see app.set().

The application object can be referred from the Request object and the Response object as req.app, and res.app, respectively.

User can use the following code to import the WebApp module.

var WebApp = require("webapp");

Support

The following shows WebApp module APIs available for each permissions.

 User ModePrivilege Mode
WebApp.create
WebApp.createApp
WebApp.createSub
WebApp.Router
WebApp.static
app.locals
app.isMaster
app.addcert
app.all
app.METHOD
app.groupName
app.disable
app.disabled
app.enable
app.enabled
app.engine
app.render
app.route
app.start
app.stop
app.port
app.set
app.use

WebApp Class

WebApp.create(group, subs[, taskFile], saddr[, tlsOpt])

  • group {String} Server group name(master server module). Usually the module name is used as the group name. If the server work on mult-task mode(subs > 0) and taskFile is missing, the group must be supported as app module name.
  • subs {Integer} Sub task counts, if subs > 0, app run in multi-task mode.
  • taskFile {String} Sub task module name. default: use group as module name.
  • saddr {Object} Server socket address. If the port of saddr is set to 0, the server port will be assigned automatically, and that can be get by app.port().
  • tlsOpt {Object} TLS securely connections options. default: undefined, means use TCP connection.

This method creates a master-server. When the master-server starts, it can create a specified number(subs) of sub-servers (subs), refer to WebApp mult-task.

Example

  • Create single server:
var WebApp = require("webapp");
var socket = require("socket");

var saddr = socket.sockaddr(socket.INADDR_ANY, 8000);
var app = WebApp.create("webapp", 0, saddr);
app.use("/", function(req, res) {
  res.send("Hello world.");
});

app.start();
  • Create mult-task server:
var WebApp = require("webapp");
var socket = require("socket");

var saddr = socket.sockaddr(socket.INADDR_ANY, 8000);
var app = WebApp.create("./webapp", 2, saddr);
app.use("/", function(req, res) {
  res.send(`my ser is: ${app.groupName.name}`);
});

app.start();

WebApp.createApp([subs])

  • subs {Integer} the new task counts, if subs > 0, app run in multi-task mode.

This method creates a master-server (name: './__webapp__'). If developing an EdgerOS application, use this function to create a WebApp object. When the master-server starts, it can create a specified number(subs) of sub-servers (subs), refer to WebApp mult-task.

Example

  • Create single server:
var WebApp = require("webapp");

var app = WebApp.createApp();

app.use("/", function(req, res) {
  res.send("Hello world.");
});

app.start();
  • Create mult-task server:
var WebApp = require("webapp");

var app = WebApp.createApp(2);

app.use("/", function(req, res) {
  res.send(`my ser is: ${app.groupName.name}`);
});

app.start();
  • Sub-server (./__webapp__.js):
var WebApp = require("webapp");

var app = WebApp.createSub("./__webapp__");

app.use("/", function(req, res) {
  res.send(`my ser is: ${app.groupName.name}`);
});

app.start();

WebApp.createSub(group)

  • group {String} Server group name, the same as master-server group name.

Use this method to create a sub-server when the sub-server is not on the same module as the master-server.

Example

  • Master-server:
var WebApp = require("webapp");
var socket = require("socket");

var saddr = socket.sockaddr(socket.INADDR_ANY, 8000);
var app = WebApp.create("web_mult", 2, "./web_mult_sub", saddr);
app.use("/", function(req, res) {
  res.send(`my ser is: ${app.groupName.name}`);
});

app.start();
  • Sub-server (./web_mult_sub.js):
var WebApp = require("webapp");

var app = WebApp.createSub("web_mult");
app.use("/", function(req, res) {
  res.send(`my ser is: ${app.groupName.name}`);
});

app.start();

WebApp.Router([web[, options]])

  • web {Object} webapp instance.
  • options {Object} Options.

This is web router, See webrouter for details.

Example

var Router = WebApp.Router;
var router = Router.create();
app.use(router);

WebApp.static(root[, options])

  • root {String} root directory of serve files.
  • options {Object} Options.

This is serveStatic middleware, See serveStatic for details.

Example

var static = WebApp.static;
app.use(static("public"));

WebApp mult-task

The WebApp have two work mode:

  • MASTER The master-server listens and receives the client request. If the sub server is registered on the master server, the master server will dispatch the request to itself or the sub server for processing.

  • SUB The sub-server works on a separate task. It does not listen on the port, does not directly accept requests from the client, but accepts requests dispatched by the master-server.

A WebApp can be a single task or multiple tasks(mult-task). When it works in mult-task mode, there is one master-server and several sub-servers, which are created by master-server when the master-server is started. When the master-server is working, the client requests are evenly distributed to all the sub-servers and the master-server itself.

The sub-server can be the same module as the master-server, or it can be a different module. If they are on the same module, you don't need to create a sub-server explicitly. If the sub-server is not on the same module as master-server, user should create it by createSub.

WebApp Object

app.locals

  • {Object} The app.locals object has properties that are local variables within the application. Once set, the value of app.locals properties persist throughout the life of the application,

You can access local variables in templates rendered within the application. This is useful for providing helper functions to templates, as well as application-level data. Local variables are available in middleware via req.app.locals.

Example

app.locals.title = "My App";
app.locals.strftime = require("strftime");
app.locals.email = "me@myapp.com";

console.log(app.locals.title);
console.log(app.locals.email);

app.isMaster()

  • Returns: {Boolean} Whether it is the master server.

Get whether the server object is the master server.

app.addcert(opt)

  • opt {Object} Tls server option.
  • Returns: {Boolean} Whether it was added successfully.

opt includes following items:

  • name {String} Server domain name.
  • ca {String} Optional trusted CA certificates. default: no CA certificates.
  • cert {String} Server certificate.
  • key {String} Private key of server certificate.
  • passwd {String} Private key password. default: no password.

This method adds a SNI (Server Name Indication) certificate to the tls server. SNI is an extension used to improve SSL or TLS for servers. It mainly solves the disadvantage that one server can only use one certificate (one domain name). With the support of the server for virtual hosts, one server can provide services for multiple domain names, so SNI must be supported to meet the demand.

app.start()

  • Returns: {Boolean} App start success or not.

Start app server. The app's setting must be done before this operator.

app.stop([stopAll][, cb])

  • stopAll {Boolean} always true for MASTER mode, close all task servers. For SUB mode: true - stop all task servers; false - stop this sub server. default: false.
  • cb {Function} Callback when stop event emit.

Stop app server.

app.port()

  • Returns: {Integer | Undefined} Server socket port.

When the server starts with the MASTER module, app.port() gets the port of the server, otherwise it returns undefined.

Example

var port = app.port();
console.log(port);

app.METHOD([path, ]handle[, handle..])

  • path {String | RegExp | Array} The path for which the request handle function is invoked; can be any of:
    • A string representing a path. default: '/' (root path)
    • A path pattern.
    • A regular expression pattern to match paths.
    • An array of combinations of any of the above.
  • handle {Function} The request handle function. WebApp support async handle, see Async Handle for details.

Routes an HTTP request, where METHOD is the HTTP method of the request, such as GET, PUT, POST, DELETE and so on, in lowercase. Thus, the actual methods are app.get(), app.post(), app.put(), app.delete() and so on.

WebApp supports the following routing methods corresponding to the HTTP methods of the same names in lowercase:

DELETE, GET, HEAD, POST, PUT

CONNECT, OPTIONS, TRACE

COPY, LOCK, MKCOL, MOVE, PROPFIND, PROPPATCH, SEARCH, UNLOCK, BIND, REBIND, UNBIND, ACL

REPORT, MKACTIVITY, CHECKOUT, MERGE

MSEARCH, NOTIFY

EdgerOS 1.8.5 and later supports methods:

SUBSCRIBE, UNSUBSCRIBE

PATCH, PURGE

MKCALENDAR

LINK, UNLINK

SOURCE

Example

  • Path:
// This will match paths starting with /abcd:
app.get("/abcd", function(req, res) {
  // User handle.
});
  • Path Pattern:
// This will match paths starting with `/abcd` and `/abd`:
app.get("/abc?d", function(req, res) {
  // User handle.
});
// This will match paths starting with `/abcd`, `/abbcd`, `/abbbbbcd`, and so on:
app.get("/ab+cd", function(req, res) {
  // User handle.
});
// This will match paths starting with `/abcd`, `/abxcd`, `/abFOOcd`, `/abbArcd`, and so on:
app.get("/ab*cd", function(req, res) {
  // User handle.
});
// This will match paths starting with `/ad` and `/abcd`:
app.get("/a(bc)?d", function(req, res) {
  // User handle.
});
  • Regular expression pattern:
// This will match paths starting with `/abc` and `/xyz`:
app.get(/\/abc|\/xyz/, function(req, res) {
  // User handle.
});

app.all([path, ]handle[, handle..])

  • path {String | RegExp | Array} The path for which the request handle function is invoked; can be any of:
    • A string representing a path. default: '/' (root path)
    • A path pattern.
    • A regular expression pattern to match paths.
    • An array of combinations of any of the above.
  • handle {Function} The request handle function. WebApp support async handle, see Async Handle for details.

This method is like the standard app.METHOD() methods, except it matches all HTTP verbs.

Examples

The following callback is executed for requests to /secret whether using GET, POST, PUT, DELETE, or any other HTTP request method:

app.all("/secret", function(req, res, next) {
  console.log("Accessing the secret section ...");
  next(); // pass control to the next handler
});

The app.all() method is useful for mapping 'global' logic for specific path prefixes or arbitrary matches. For example, if you put the following at the top of all other route definitions, it requires that all routes from that point on require authentication, and automatically load a user. Keep in mind that these callbacks do not have to act as end-points: loadUser can perform a task, then call next() to continue matching subsequent routes.

app.all("*", requireAuthentication, loadUser);

Or the equivalent:

app.all("*", requireAuthentication);
app.all("*", loadUser);

Another example is white-listed “global” functionality. The example is similar to the ones above, but it only restricts paths that start with “/api”:

app.all("/api/*", requireAuthentication);

app.groupName

  • groupName {Object}
    • group {String} The app grpup name, see WebApp mult-task.
    • name {String} The app server name, see WebApp mult-task.

app.disable(name)

  • name {String} setting name.

Sets the Boolean setting name to false, where name is one of the properties from the app settings, see set(name[, value]). Calling app.set('foo', false) for a Boolean property is the same as calling app.disable('foo').

Example

app.disable("case sensitive routing");
app.get("case sensitive routing");
// => false

app.disabled(name)

  • name {String} setting name.
  • Returns: {Boolean} true if the Boolean setting name is disabled (false).

Example

app.disabled("case sensitive routing");
// => true

app.enable("case sensitive routing");
app.disabled("case sensitive routing");
// => false

app.enable(name)

  • name {String} setting name.

Sets the Boolean setting name to true, Calling app.set('foo', true) for a Boolean property is the same as calling app.enable('foo').

Example

app.enable("case sensitive routing");
app.get("case sensitive routing");
// => true

app.enabled(name)

  • name {String} setting name.
  • Returns: {Boolean} true if the setting name is enabled (true).

Example

app.enabled("case sensitive routing");
// => false

app.enable("case sensitive routing");
app.enabled("case sensitive routing");
// => true

app.engine(ext, callback)

  • ext {String} extension name.
  • callback {Function} the handle function of template engine.

Registers the given template engine callback as ext. app has registered the ejs engine by default.

app.set(name[, value])

  • name {String} setting name.
  • value {any} setting value.
  • Returns: {any} return value of setting name while value omited.

Assigns setting name to value. You may store any value that you want, but certain names can be used to configure the behavior of the server.

Calling app.set('foo', true) for a Boolean property is the same as calling app.enable('foo'). Similarly, calling app.set('foo', false) for a Boolean property is the same as calling app.disable('foo').

Retrieve the value of a setting with app.get().

Application Settings

The following table lists application settings.

PropertyTypeDescriptionDefault
case sensitive routingBooleanEnable case sensitivity. When enabled, "/Foo" and "/foo" are different routes. When disabled, "/Foo" and "/foo" are treated the same.N/A (undefined)
strict routingBooleanEnable strict routing. When enabled, the router treats "/foo" and "/foo/" as different. Otherwise, the router treats "/foo" and "/foo/" as the same.N/A (undefined)
viewsString or ArrayA directory or an array of directories for the application's views. If an array, the views are looked up in the order they occur in the array.'/views'
view cacheBooleanEnables view template compilation caching.true
view engineStringThe default engine extension to use when omitted.ejs engine.

Example

app.set("title", "My Site");
app.get("title"); // "My Site"

app.get(name)

  • name {String} setting name.
  • Returns: {any} return value of setting name.

Example

app.get("title");
// => undefined

app.set("title", "My Site");
app.get("title");
// => "My Site"

app.get([path, ]handle[, handle..])

Routes HTTP GET requests to the specified path with the specified callback functions. See app.METHOD().

app.render(name[, options], callback)

  • name {String} the given view name.
  • options {Object} local variables for the view.
  • callback{Function} accepting an error and the rendered template string.

Returns the rendered HTML of a view via the callback function.It accepts an optional parameter that is an object containing local variables for the view. It is like res.render(), except it cannot send the rendered view to the client on its own.

Example

app.render("email", function(err, html) {
  // ...
});

app.render("email", { name: "Tobi" }, function(err, html) {
  // ...
});

app.route([path])

  • path {String|RegExp} route path.
    • A string representing a path. default: '/' (root path)
    • A path pattern.
    • A regular expression pattern to match paths.
  • Returns: {Object} an instance of a Router.

Returns an instance of a single route, which you can then use to handle HTTP verbs with optional middleware. Use app.route() to avoid duplicate route names (and thus typo errors).

Example

app
  .route("/events")
  .all(function(req, res, next) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get(function(req, res, next) {
    res.json({});
  })
  .post(function(req, res, next) {
    // maybe add a new event...
  });

app.use([path, ]handle[, handle..])

  • path {String|RegExp | Array} The path for which the middleware function is invoked; can be any of:
    • A string representing a path. default: '/' (root path)
    • A path pattern.
    • A regular expression pattern to match paths.
    • An array of combinations of any of the above.
  • handle {Function | Object} A middleware function or router object. WebApp support async handle, see Async Handle for details.

Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches path.

A route will match any path that follows its path immediately with a "/". For example: app.use('/apple', ...) will match "/apple", "/apple/images", "/apple/images/news", and so on.

Since path defaults to "/", middleware mounted without a path will be executed for every request to the app.

Example

This middleware function will be executed for every request to the app:

app.use(function(req, res, next) {
  console.log("Time: %d", Date.now());
  next();
});

Middleware functions are executed sequentially, therefore the order of middleware inclusion is important.

// this middleware will not allow the request to go beyond it
app.use(function(req, res, next) {
  res.send("Hello World");
});

// requests will never reach this route
app.get("/", function(req, res) {
  res.send("Welcome");
});

Error-handling Middleware

Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors. For details about error-handling middleware, see: Error Handling.

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature (err, req, res, next):

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send("Something broke!");
});

Events

start

Emitted when the webapp start done.

stop

Emitted when the webapp stop.

ready

Emitted when the multi-task web server's sub task already.

  • totalSubs {Integer} Total number of subtasks.
  • openedSubs {Integer} Number of open subtasks.

final

Emitted before the webapp final handle call. so 'Angular' or 'Vue' web app can use this event send index.html file to browser.

Example

app.on("final", function(req, res, status, reason, estack) {
  if (status === 404) {
    res.sendFile("/public/index.html");
  }
  if (Array.isArray(estack)) {
    console.stack(estack);
  }
});

task

  • arg {Object} Task arguments.
  • i {Integer} Subtask index, from 1 to sub task count.

Emitted when the webapp create sub task. multi-task web servers need to use ARGUMENT variables to pass parameters, so users cannot directly use ARGUMENT variables, but user can process user-defined task parameters through ARGUMENT.arg.

Example

app.on("task", function(arg, i) {
  // arg is object, can pass some arguments to sub task.
  // i is task index, from 1 to sub task count.
  arg.bar = "foo";
});
// Sub task can use following method get arg
console.log(ARGUMENT.arg.bar);

Error Handling

Error Handling refers to how WebApp catches and processes errors that occur both synchronously and asynchronously. WebApp comes with a default error handler so you don’t need to write your own to get started.

Catching Errors

It’s important to ensure that WebApp catches all errors that occur while running route handlers and middleware.

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then WebApp will catch and process it. For example:

app.get("/", function(req, res) {
  throw new Error("BROKEN"); // WebApp will catch this on its own.
});

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where WebApp will catch and process them.

If you pass anything to the next() function, WebApp regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

You must catch errors that occur in asynchronous code invoked by route handlers or middleware and pass them to WebApp for processing. For example:

app.get("/", function(req, res, next) {
  setTimeout(function() {
    try {
      throw new Error("BROKEN");
    } catch (err) {
      next(err);
    }
  }, 100);
});

The above example uses a try...catch block to catch errors in the asynchronous code and pass them to WebApp. If the try...catch block were omitted, WebApp would not catch the error since it is not part of the synchronous handler code.

Use promises to avoid the overhead of the try..catch block or when using functions that return promises. For example:

app.get("/", function(req, res, next) {
  Promise.resolve()
  .then(function() {
    throw new Error("BROKEN");
  })
  .catch(next); // Errors will be passed to WebApp.
});

Since promises automatically catch both synchronous errors and rejected promises, you can simply provide next as the final catch handler and WebApp will catch errors, because the catch handler is given the error as the first argument.

Whichever method you use, if you want WebApp error handlers to be called in and the application to survive, you must ensure that WebApp receives the error.

The Default Error Handler

WebApp comes with a built-in error handler that takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.

If you pass an error to next() and you do not handle it in a custom error handler, it will be handled by the built-in error handler; the error message will be written to the client.

If you call next() with an error after you have started writing the response (for example, if you encounter an error while streaming the response to the client) the WebApp default error handler closes the connection and fails the request.

So when you add a custom error handler, you must delegate to the default WebApp error handler, when the headers have already been sent to the client:

function errorHandler(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render("error", { error: err });
}

Note that the default error handler can get triggered if you call next() with an error in your code more than once, even if custom error handling middleware is in place.

Writing Error Handlers

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: (err, req, res, next). For example:

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send("Something broke!");
});

You define error-handling middleware last, after other app.use() and routes calls; for example:

var bodyParser = require("middleware").bodyParser;

app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(function(err, req, res, next) {
  // logic
});

Responses from within a middleware function can be in any format, such as an HTML error page, a simple message, or a JSON string.

For organizational (and higher-level framework) purposes, you can define several error-handling middleware functions, much as you would with regular middleware functions. For example, to define an error-handler for requests made by using XHR and those without:

var bodyParser = require("middleware").bodyParser;

app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

In this example, the generic logErrors might write request and error information to stderr, for example:

function logErrors(err, req, res, next) {
  console.error(err.stack);
  next(err);
}

Also in this example, clientErrorHandler is defined as follows; in this case, the error is explicitly passed along to the next one.

Notice that when not calling “next” in an error-handling function, you are responsible for writing (and ending) the response.

function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: "Something failed!" });
  } else {
    next(err);
  }
}

Implement the “catch-all” errorHandler function as follows (for example):

function errorHandler(err, req, res, next) {
  res.status(500);
  res.render("error", { error: err });
}

Async Handle

WebApp and WebApp.Router support Async Handle.

If your handle function is an async function, or returns a promise object:

  • If promise is reject as an error object, WebApp will call next(error) to handle it.
  • If promise is resolve as a normal value, WebApp will call res.send(value) to send this value.
  • If promise is resolve as undefined, WebApp will not do any processing.

In this way, we can support callback function style and async/await at the same time with minimal cost. Although it is very free to do so, we strongly recommend using only one of them, because the application's error handling method should be consistent.

Example

  • Use async handle and res.send method:
function handle() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Hello world.");
    }, 1000);
  });
}

app.get("/", async function(req, res) {
  var ret = await handle();
  res.send(ret);
});
  • Use async handle and return value:
function handle() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Hello world.");
    }, 1000);
  });
}

app.get("/", async function(req, res) {
  var ret = await handle();
  return ret;
});
  • Use async handle and next() mehtod:
function handle() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Hello world.");
    }, 1000);
  });
}

app.use("/", async function(req, res, next) {
  var ret = await handle();
  console.log(ret);
  next();
});

Stream Mode

The http protocol supports block transfer. The http header does not set Content-Length, and Transfer-Encoding', 'chunked' is set, and the data can be sent to the client in an http response.

With this feature, the server can work in stream mode. An http request does not have to be returned immediately, and the server pushes it to the client when the data is ready. Stream mode need to do the following:

  • res.write() is used repeatedly in the http request reply, and finally ends with res.end().

Example

var socket = require("socket");
var WebApp = require("webapp");
var iosched = require("iosched");
var mw = require("middleware");

// Create app.
var saddr = socket.sockaddr("192.168.7.32", 8000);
var app = WebApp.create("app", 0, saddr);

app.route("/stream").get(function(req, res) {
  res.type("html");
  res.write("<html><body>");
  var count = 0;
  var timer = setInterval(() => {
    res.write(`<h3>count: ${count++}</h3>`);
    if (count === 20) {
      res.end("</html></body>");
      clearInterval(timer);
      timer = null;
    }
  }, 1000);

  req.on("close", () => {
    if (timer) {
      clearInterval(timer);
      timer = null;
    }
  });

  res.on("end", () => {
    if (timer) {
      clearInterval(timer);
      timer = null;
    }
  });
});

// Catch 404 and forward to error handler.
app.use(function error(req, res, next) {
  res.status(404);
  next(new Error("Not Found"));
});

// Error handler.
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  var status = err.status ? err.status : res.status();
  status = status < 400 ? 500 : status;
  res.json({ status: status, msg: err.message });
});

// Start app.
app.start();

// Event loop.
while (true) {
  iosched.poll();
}

Example

A base app example

var socket = require("socket");
var WebApp = require("webapp");
var iosched = require("iosched");

// Create app.
var app = WebApp.create("app", 0, socket.sockaddr(socket.INADDR_ANY, 8000));

// Route and handle.
app.get("/", function index(req, res) {
  res.send("Hello world!");
});

// Catch 404 and forward to error handler.
app.use(function(req, res, next) {
  res.status(404);
  next(new Error("Not Found"));
});

// Error handler.
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  var status = err.status ? err.status : res.status();
  status = status < 400 ? 500 : status;
  res.json({ status: status, msg: err.message });
});

// Start app.
app.start();

// Event loop.
while (true) {
  iosched.poll();
}

A comprehensiveapp app example

var socket = require("socket");
var WebApp = require("webapp");
var iosched = require("iosched");
var bodyParser = require("middleware").bodyParser;

// Create app.
var app = WebApp.create("app", 0, socket.sockaddr(socket.INADDR_ANY, 8000));

// Index page.
app.get("/", function index(req, res) {
  // Handle request. If you encounter an error, you could return a Error.
  // return new Error('error');

  // Response as follow methods:
  // res.render('index');
  // res.send(text);
  // res.json(object);
  // res.sendStatus(statusCode);
  var html = `
		<html><body>
			<H1>Hello world!</H1>
		</body></html>`;
  res.send(html);
});

app
  .route("/use")
  .use(function(req, res, next) {
    // Verify the user.
    next();
  })
  .get("/show", function(req, res) {
    var id = req.params.id;

    // Get user info by user id...

    res.json({ id: id, name: "lisa", addr: "Beijing" });
  })
  .post("/add", bodyParser.urlencoded(), function(req, res) {
    var post = body;

    // Access and process data. post em. post.name, post.addr...

    res.json({ result: "ok" });
  });

// Catch 404 and forward to error handler.
app.use(function(req, res, next) {
  res.status(404);
  next(new Error("Not Found"));
});

// Error handler.
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  var status = err.status ? err.status : res.status();
  status = status < 400 ? 500 : status;
  res.json({ status: status, msg: err.message });
});

// Start app.
app.start();

// Event loop.
while (true) {
  iosched.poll();
}

A app porject example

The project organize as follow:

[/root/app1]
	|-[public]..............static file.
	|	|-[css]
	|	|-[image]
	|	|-[html]
	|	|-[js]
	|-[routers].............modules routers.
	|	|-index.js
	|	|-user.js
	|-[views]...............render views.
	|	|-index.ejs
	|	|-error.ejs
	|-[js]..................user modules.
	|-app.js................app start file.
	|-config.json...........config file.
  • app.js:
var socket = require("socket");
var WebApp = require("webapp");
var iosched = require("iosched");
var mw = require("middleware");
var index = require("./routers");
var user = require("./routers/user");

// Create app.
var app = WebApp.create("app1", 0, socket.sockaddr(socket.INADDR_ANY, 8000));

// Static file handler, use internal middleware.
app.use("/public", mw.serveStatic("/root/app1/public"));

// Index.
app.use("/", index);

// User module router.
app.use("/user", user);

// Catch 404 and forward to error handler.
app.use(function(req, res, next) {
  res.status(404);
  next(new Error("Not Found"));
});

// Error handler.
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  var status = err.status ? err.status : res.status();
  status = status < 400 ? 500 : status;
  res.json({ status: status, msg: err.message });
});

// Start app.
app.start();

// Event loop.
while (true) {
  iosched.poll();
}
  • routers/index.js:
var Router = require("webapp").Router;

var router = Router.create();
router.get("/", function(req, res) {
  res.render("index", { title: "JSRE" });
});

module.exports = router;
  • routers/user.js:
var Router = require("webapp").Router;
var bodyParser = require("middleware").bodyParser;

var router = Router.create();
router
  .use(function(req, res) {
    // Verify the user.
  })
  .get("/show", function(req, res) {
    var id = req.params.id;

    // Get user info by user id...

    res.json({ id: id, name: "lisa", addr: "Beijing" });
  })
  .post("/add", bodyParser.json(), function(req, res) {
    var post = req.body;

    // Access and process data. post em. post.name, post.addr...

    res.json({ result: "ok" });
  });

module.exports = router;
  • views/index.ejs:
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
  </body>
</html>
  • views/error.ejs:
<!DOCTYPE html>
<html>
  <body>
    <h1>Status: <%= status %></h1>
    <p>Error info: <%= msg %></p>
  </body>
</html>
文档内容是否对您有所帮助?
有帮助
没帮助