NodeJS路由是非常关键的。我们要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码。
因此,我们需要查看 HTTP 请求,从中提取出请求的 URL 以及 GET/POST 参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,但这里暂定其为我们的HTTP服务器的功能。
我们需要的所有数据都会包含在 request 对象中,该对象作为 onRequest() 回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的 Node.JS 模块,它们分别是 url 和 querystring 模块。
说白了就是根据URL和请求方法来获取参数,使用request方法来获取GET或者POST的参数。根据参数执行相应的代码。

获取路由路径

http.js

  1. const http = require("http");
  2. const url = require("url");
  3. function start() {
  4. function onRequest(req, res) {
  5. const pathname = url.parse(request.url).pathname;
  6. console.log("request for" + pathname + " received.");
  7. res.writeHead(200, { "Content-Type": "text/plain" });
  8. res.write("hello world");
  9. res.end();
  10. }
  11. http.createServer(onRequest).listen(8888);
  12. console.log("服务器启动成功");
  13. }
  14. exports.start = start;

app.js

  1. const server = require("./http");
  2. server.start();

此时启动app 控制台会输出 服务器启动成功
浏览器访问 http://localhost:8888/ 页面会输出hello world 然后控制台打印 Request for / received 这个是根路由。
浏览器访问 http://localhost:8888/a/b 页面输出不变 但是控制台打印就不一样了 Request for /a/b received 这样一个输出。因为 代码中 pathname 就代表了我们在端口号之后的 URL 路径,也就是路由。页面输出没有变化是因为根本没有对路由有响应的处理。
这里 可以理解为 /controller/action。

路由和服务器结合

router.js

  1. function route(pathname) {
  2. console.log("路由是" + pathname);
  3. }
  4. exports.route = route;

这段代码什么也没干,是的下面就看看如何把路由和服务器结合起来。

http.js

  1. const http = require("http");
  2. const url = require("url");
  3. function start(route) {
  4. function onRequest(req, res) {
  5. const pathname = url.parse(request.url).pathname;
  6. route(pathname,res);
  7. res.writeHead(200, { "Content-Type": "text/plain" });
  8. res.write("hello world");
  9. res.end();
  10. }
  11. http.createServer(onRequest).listen(8888);
  12. console.log("服务器启动成功");
  13. }
  14. exports.start = start;

app.js

  1. const server = require("./http");
  2. const route = require("./router");
  3. server.start(route.route);

把router模块通过参数传递给http模块。然后http去执行router模块。router模块就会接受到路由地址然后会打印出路由。
这个时候访问浏览器: http://localhost:8888/a/c 控制台就会打印 路由是 /a/c。
目前 router 模块其实并没有什么用。如何让它有用?

http.js 把 response 传入router中

  1. const http = require("http");
  2. const url = require("url");
  3. function start(route) {
  4. function onRequest(request, response) {
  5. const pathname = url.parse(request.url).pathname;
  6. route(pathname, response);
  7. }
  8. http.createServer(onRequest).listen(8888);
  9. console.log("服务器启动成功");
  10. }
  11. exports.start = start;

router.js 接受到之后做响应的操作

  1. function route(pathname, response) {
  2. if (pathname == "/") {
  3. response.writeHead(200, { "Content-Type": "text/plain" });
  4. response.write("Hello World");
  5. response.end();
  6. } else if (pathname == "/index/home") {
  7. response.writeHead(200, { "Content-Type": "text/plain" });
  8. response.end("index/home");
  9. } else {
  10. response.end("404");
  11. }
  12. }
  13. exports.route = route;

此时启动app.js
浏览器访问http://localhost:8888/ 页面输出 hello world
浏览器访问http://localhost:8888/index/home 页面输出 index/home
浏览器访问http://localhost:8888/bbb 页面输出 404
这样拿到路由就能根据路由返回响应的内容了。
现在还没有通过GET和POST去拿参数。

GET和POST请求

什么是get和post就不多做介绍了。直接上代码

GET

  1. const http = require("http");
  2. const url = require("url");
  3. const util = require("util");
  4. http
  5. .createServer((req, res) => {
  6. res.writeHead(200, { "Content-Type": "text/plain" });
  7. res.end(util.inspect(url.parse(req.url, true)));
  8. })
  9. .listen(3000);

浏览器访问http://localhost:3000/user?name=yideng&age=30 页面输出:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: ‘?name=yideng&age=30’,
query: [Object: null prototype] { name: ‘yideng’, age: ‘30’ },
pathname: ‘/user’,
path: ‘/user?name=yideng&age=30’,
href: ‘/user?name=yideng&age=30’
}

获取 URL 的参数

  1. const http = require("http");
  2. const url = require("url");
  3. const util = require("util");
  4. http
  5. .createServer(function (req, res) {
  6. res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8" });
  7. // 解析 url 参数
  8. const params = url.parse(req.url, true).query;
  9. res.write("网站名:" + params.name);
  10. res.write("\n");
  11. res.write("网站 URL:" + params.url);
  12. res.end();
  13. })
  14. .listen(3000);

浏览器访问http://localhost:3000/user?name=百度&url=www.baidu.com
网站名:百度
网站 URL:www.baidu.com

POST

  1. const http = require("http");
  2. const querystring = require("querystring");
  3. let postHTML =
  4. '<html><head><meta charset="utf-8"><title>Node.js 实例</title></head>' +
  5. "<body>" +
  6. '<form method="post">' +
  7. '网站名: <input name="name"><br>' +
  8. '网站 URL: <input name="url"><br>' +
  9. '<input type="submit">' +
  10. "</form>" +
  11. "</body></html>";
  12. http
  13. .createServer((req, res) => {
  14. let body = "";
  15. req.on("data", (chunk) => {
  16. body += chunk;
  17. });
  18. req.on("end", () => {
  19. // 解析参数
  20. body = querystring.parse(body);
  21. // 设置响应头部信息及编码
  22. res.writeHead(200, { "Content-Type": "text/html; charset=utf8" });
  23. if (body.name && body.url) {
  24. // 输出提交的数据
  25. res.write("网站名:" + body.name);
  26. res.write("<br>");
  27. res.write("网站 URL:" + body.url);
  28. } else {
  29. // 输出表单
  30. res.write(postHTML);
  31. }
  32. res.end();
  33. });
  34. })
  35. .listen(3000);

首先给页面返回一个表单,然后这个表单提交过来的内容回显到页面。