REST-ful API

Node 可以用来开发 REST-ful API,它提供了一系列的工具类。

utils

http

  • 创建 HTTP 服务器
const http = require('http');
const server = http.createServer((req, res) => {
  res.end("hello world\n");
});
 



  • 启动服务器
server.listen(3000, () => {
  // ...
  console.log("The server is running on port 3000");
});
 



url

  • 解析 path
const url = require("url");
// ...
const parsedUrl = url.parse(req.url, true);
const path = parsedUrl.pathname;
  • 解析 queryString
const queryStringObject = parsedUrl.query;

req

req 是 服务器回调的 第一个参数, 每次请求都会传入一个 req 对象, 它们是全新的。

  • 解析 method
const method = req.method.toLowerCase();
  • 解析 headers
const headers = req.headers;

string_decoder

  • 解析 body

stream 2 string

var StringDecoder = require("string_decoder").StringDecoder;
// ...
const decoder = new StringDecoder("utf-8");
const buffer = "";
req.on("data", function (data) {
  buffer += decoder.write(data);
});
req.on("end", function () {
  buffer += decoder.end();
  console.log("req payload:", buffer);
  // ...
});

router and routes

router handler and callback handler design

  • router handler function params

    • context data

      • 包括 path, query string, method, headers, payload
    • callback

      • callback handler (designed as below)
  • callback handler function params

define handlers

var handlers = {};

// pass context and callback handler
handlers.foo = function (data, callback) {
  // invoke callback by passing status code and payload
  callback(406, { name: "foo handler" });
};

// Not found handler
handlers.notFound = function (data, callback) {
  callback(404);
};

define router and routes

const router = {
  // a route
  foo: handlers.foo,
};

handle the req

// ...
const trimmedPath = path.replace(/^\/+|\/+$/g, "");
// ...
req.on("end", function () {
  buffer += decoder.end();

  // 匹配的路由回调
  const matchedHandler =
    typeof router[trimmedPath] !== "undefined"
      ? router[trimmedPath]
      : handlers.notFound;

  // 构造上下文
  var context = {
    trimmedPath: trimmedPath,
    queryStringObject: queryStringObject,
    method: method,
    headers: headers,
    payload: buffer,
  };

  // 调用 匹配的 路由回调
  matchedHandler(context, function (statusCode, payload) {
    // 通用 回调定义

    statusCode = typeof statusCode == "number" ? statusCode : 200;
    payload = typeof payload == "object" ? payload : {};

    // Convert the payload to a string
    var payloadString = JSON.stringify(payload);

    // https://nodejs.org/dist/latest-v18.x/docs/api/http.html#responsewriteheadstatuscode-statusmessage-headers
    res.setHeader("Content-Type", "application/json");
    res.writeHead(statusCode);
    res.end(payloadString);
  });
});

https

  • 创建 ssl 证书

    open ssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
    
    • country name
    • state and province name
    • locality name
    • organization name
    • organization unit name
    • common name
      • localhost for 开发环境
    • email address
  • 更新代码

    const https = require("https");
    // ...
    const httpsServerOptions = {
      key: fs.readFileSync("./https/key.pem"),
      cert: fs.readFileSync("./https/cert.pem"),
    };
    
    const httpsServer = https.createServer(
      httpsServerOptions,
      function (req, res) {
        requestHandler(req, res);
      }
    );
    
    // Start the HTTPS server
    httpsServer.listen(config.httpsPort, function () {
      console.log("The HTTPS server is running on port " + config.httpsPort);
    });