• 【学习笔记03】node.js搭建一个简易的服务器


    一、什么是请求

     1. JS内部的ajax就算一个请求,由ajax发送请求, 返回的数据给到了ajax

    2. 在浏览器地址栏内输入地址敲回车,由浏览器发送, 返回的数据给到浏览器

    3. img、link和script这些标签也可以发送请求,由标签发送, 返回的数据给到了标签

    二、请求地址

    http://localhost:8080/a/b/c/index.html

    • 如果请求的地址是 ./out.js,实际请求的地址:http://localhost:8080/a/b/c/out.js
    • 如果请求的地址是 ./a/out.js,实际请求的地址:http://localhost:8080/a/b/c/a/out.js
    • 如果请求的地址是 ../a/out.js,实际请求的地址:http://localhost:8080/a/b/a/out.js
    • 如果请求的地址是 /a.js,实际请求的地址:http://localhost:8080/a.js
    • 如果请求的地址 /a/b.js,实际请求的地址:http://localhost:8080/a/b.js

    三、搭建一个简易的服务器

     (一)基础页面搭建

    1、分析

    1. const http = require("http");
    2. // 1. 创建一个服务器
    3. const server = http.createServer(function (req, res) {
    4. console.log(req.url);
    5. });
    6. // 2. 给服务监听一个端口号
    7. server.listen(8080, () => {
    8. console.log('恭喜你,服务器启动成功');
    9. console.log('目前正在监听8080端口! ');
    10. console.log('基准地址:http://localhost:8080');
    11. });

    1. const http = require("http");
    2. const url = require("url");
    3. // 1. 创建一个服务器
    4. const server = http.createServer(function (req, res) {
    5. console.log(url.parse(req.url,true));
    6. });
    7. // 2. 给服务监听一个端口号
    8. server.listen(8080, () => {
    9. console.log('恭喜你,服务器启动成功');
    10. console.log('目前正在监听8080端口! ');
    11. console.log('基准地址:http://localhost:8080');
    12. });

     2、代码实现

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. // 1. 创建一个服务器
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. console.log(pathname, query);
    8. if (pathname === "/a") {
    9. // 1. 读取 ./client/views/index.html 文件
    10. fs.readFile("./client/views/index.html", "utf-8", function (err, data) {
    11. if (err) return console.log(err);
    12. // console.log(data)
    13. // 通过 res.end() 返回给浏览器
    14. res.end(data);
    15. });
    16. }
    17. if (pathname === "/b") {
    18. fs.readFile("./client/views/list.html", "utf-8", function (err, data) {
    19. if (err) return console.log(err);
    20. // console.log(data)
    21. res.end(data);
    22. });
    23. }
    24. 1
    25. });
    26. // 2. 给服务监听一个端口号
    27. server.listen(8080, () => {
    28. console.log('恭喜你,服务器启动成功');
    29. console.log('目前正在监听8080端口! ');
    30. console.log('基准地址:http://localhost:8080');
    31. });

     (二)配置css

    1、约定一

    • 如果需要访问html文件, 将路径开头写上 /views  后续拼接上对应的文件名
    • 假如要访问 index.html,路径: /views/index.html
    • 假如要访问 list.html,路径: /views/list.html

    2、预定二

    • 如果要访问css文件需要使用 /style 开头 后续拼接上对应的文件名
    • 假如要访问 index.css,路径: /style/index.css
    • 假如要访问  list.css,路径: /style/list.css

    3、代码实现

    index和list的html代码

     index和list的css代码

    服务器代码实现 

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. const path = require("path");
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. // html的格式
    8. if (/^\/views/.test(pathname)) {
    9. // 拿到文件名
    10. const { base } = path.parse(pathname);
    11. // 读取对应文件返回给请求者
    12. fs.readFile(`./client/views/${base}`, "utf-8", function (err, data) {
    13. if (err) return console.log(err);
    14. res.end(data);
    15. });
    16. }
    17. // css的样式
    18. if (/^\/style/.test(pathname)) {
    19. // 拿到文件名
    20. const { base } = path.parse(pathname);
    21. // 读取对应文件返回给请求者
    22. fs.readFile(`./client/css/${base}`, "utf-8", function (err, data) {
    23. if (err) return console.log(err);
    24. res.end(data);
    25. });
    26. }
    27. });
    28. // 2. 给服务监听一个端口号
    29. server.listen(8080, () => {
    30. console.log('恭喜你,服务器启动成功');
    31. console.log('目前正在监听8080端口! ');
    32. console.log('基准地址:http://localhost:8080');
    33. });

     (三)配置静态资源

    1、约定:如果请求html; css; img; video;

    新约定1

    • /static 开头,后续跟着写上对应的目录与文件名
    • 如果访问的是 index.html;路径: /static/views/index.html
    • 如果访问的是 list.html;路径: /static/views/list.html
    • 如果访问的是 index.css;路径: /static/css/index.css

    新约定2

    • /static 开头,后续写文件名
    • 如果我需要访问 index.html;路径: /static/index.html
    • 如果我需要访问 index.css;路径: /static/index.css
    • 注意:两种约定都可以使用,这里使用的是第二种

     index和list的html代码

     服务器代码实现 

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. const path = require("path");
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. console.log(path.parse(pathname));
    8. if (/^\/static/.test(pathname)) {
    9. /*
    10. path.parse(pathname);
    11. {
    12. root: '/',
    13. dir: '/static',
    14. base: 'list.html',
    15. ext: '.html',
    16. name: 'list'
    17. }
    18. */
    19. // 拿到文件的后缀名与文件名
    20. const { base, ext } = path.parse(pathname);
    21. // 根据后缀名拼接上对应的路径
    22. let baseUrl = "./client";
    23. if (ext === ".html") {
    24. baseUrl += "/views";
    25. } else if (ext === ".css") {
    26. baseUrl += "/css";
    27. }
    28. // 根据处理过的路径读取对应文件返回给请求者
    29. fs.readFile(`${baseUrl}/${base}`, "utf-8", function (err, data) {
    30. if (err) {
    31. fs.readFile("./404.html", "utf-8", (err, data) => {
    32. if (err) return;
    33. res.end(data);
    34. });
    35. return;
    36. }
    37. res.end(data);
    38. });
    39. }
    40. });
    41. server.listen(8080, () => {
    42. console.log('恭喜你,服务器启动成功');
    43. console.log('目前正在监听8080端口! ');
    44. console.log('基准地址:http://localhost:8080');
    45. });

    (四)配置接口(get)

    • 约定, 所有数据或接口相关的, 全都以 /api 开头

      index和list的html代码

    index的js代码 

    1. const xhr = new XMLHttpRequest()
    2. xhr.open('POST', '/api/users/login')
    3. xhr.onload = function () {
    4. console.log(JSON.parse(xhr.responseText))
    5. }
    6. xhr.send('username=QF001&password=123456')

    服务器代码 

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. const path = require("path");
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. if (/^\/static/.test(pathname)) {
    8. // 拿到文件的后缀名与文件名
    9. const { base, ext } = path.parse(pathname);
    10. // 根据后缀名拼接上对应的路径
    11. let baseUrl = "./client";
    12. if (ext === ".html") {
    13. baseUrl += "/views";
    14. } else if (ext === ".css") {
    15. baseUrl += "/css";
    16. } else if (ext === ".js") {
    17. baseUrl += "/js";
    18. }
    19. // 根据处理过的路径读取对应文件返回给请求者
    20. fs.readFile(`${baseUrl}/${base}`, "utf-8", function (err, data) {
    21. if (err) {
    22. if (ext === ".html") {
    23. fs.readFile("./404.html", "utf-8", (err, data) => {
    24. if (err) return;
    25. res.end(data);
    26. });
    27. } else {
    28. res.end("");
    29. }
    30. return;
    31. }
    32. res.end(data);
    33. });
    34. }
    35. if (/^\/api/.test(pathname)) {
    36. if (pathname === "/api/users/info" && req.method === 'GET') {
    37. // 接收到请求, 去数据库 拿到对应的 数据 返回给 请求者
    38. const info = {
    39. code: 1,
    40. message: '请求/users/info接口成功',
    41. info: {
    42. id: 1,
    43. name: 'QF666',
    44. age: 18
    45. }
    46. }
    47. // 返回给前端
    48. res.end(JSON.stringify(info))
    49. }
    50. }
    51. });
    52. server.listen(8080, () => {
    53. console.log('恭喜你,服务器启动成功');
    54. console.log('目前正在监听8080端口! ');
    55. console.log('基准地址:http://localhost:8080');
    56. });

    (五)配置接口(post)

    1、post请求

    接收请求体的数据, 有两个事件

    1. req.on('data', () => {}) ;每当开始解析请求体, 就会执行, 回调函数接受一个参数

             这个参数的值就是ajax send发送时携带的参数 (注意: 该函数会多次执行, 次数不确定)

    2. req.on('end', () => {})     这个函数执行的时候, 表明请求体 全部解析完成

    list的js代码 

    1. const xhr = new XMLHttpRequest()
    2. xhr.open('POST', '/api/users/login')
    3. xhr.onload = function () {
    4. console.log(JSON.parse(xhr.responseText))
    5. }
    6. xhr.send('username=QF001&password=123456')

     post的主要代码

    post的完整代码 

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. const path = require("path");
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. if (/^\/static/.test(pathname)) {
    8. // 拿到文件的后缀名与文件名
    9. const { base, ext } = path.parse(pathname);
    10. // 根据后缀名拼接上对应的路径
    11. let baseUrl = "./client";
    12. if (ext === ".html") {
    13. baseUrl += "/views";
    14. } else if (ext === ".css") {
    15. baseUrl += "/css";
    16. } else if (ext === ".js") {
    17. baseUrl += "/js";
    18. }
    19. // 根据处理过的路径读取对应文件返回给请求者
    20. fs.readFile(`${baseUrl}/${base}`, "utf-8", function (err, data) {
    21. if (err) {
    22. if (ext === ".html") {
    23. fs.readFile("./404.html", "utf-8", (err, data) => {
    24. if (err) return;
    25. res.end(data);
    26. });
    27. } else {
    28. res.end("");
    29. }
    30. return;
    31. }
    32. res.end(data);
    33. });
    34. }
    35. /**
    36. * 约定, 所有接口相关的, 全都以 /api 开头
    37. */
    38. if (/^\/api/.test(pathname)) {
    39. if (pathname === "/api/users/info" && req.method === "GET") {
    40. // 接收到请求, 去数据库拿到对应的数据返回给请求者
    41. const info = {
    42. code: 1,
    43. message: "请求/users/info接口成功",
    44. info: {
    45. id: 1,
    46. name: "QF666",
    47. age: 18,
    48. },
    49. youparams: query,
    50. };
    51. // 返回给前端
    52. res.end(JSON.stringify(info));
    53. }
    54. if (pathname === "/api/users/login" && req.method === "POST") {
    55. let str = ''
    56. req.on("data", (paramsStr) => {
    57. // 因为请求体内容比较多, 在解析的时候, 可能是分段解析,
    58. str += paramsStr
    59. });
    60. req.on('end', () => {
    61. console.log(str) // username=QF001&password=123456
    62. const info = {
    63. code: 1,
    64. message: "请求 /users/login 接口 成功",
    65. youparams: str,
    66. };
    67. res.end(JSON.stringify(info));
    68. })
    69. }
    70. }
    71. });
    72. server.listen(8080, () => {
    73. console.log('恭喜你,服务器启动成功');
    74. console.log('目前正在监听8080端口! ');
    75. console.log('基准地址:http://localhost:8080');
    76. });

     2、参数处理

    • post请求传参是世界约定,要么传递查询字符串, 要么传递 json 字符串
    • post请求传参解析是世界约定,在请求头内部配置 content-type
    • 如果值为application/x-www-form-urlencoded 代表传递是查询字符串
    • 如果值为 application/json 代表传递的 json字符串

    list中的js代码

    1. const xhr = new XMLHttpRequest();
    2. xhr.open("POST", "/api/users/login");
    3. xhr.onload = function () {
    4. console.log(JSON.parse(xhr.responseText));
    5. };
    6. xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    7. xhr.send("username=QF001&password=123456");
    8. // xhr.setRequestHeader("content-type", "application/json");
    9. // xhr.send('{ "username": "QF001", "password": "123456" }');

    分析

    四、服务搭建的完整代码

    (一)JS代码

     (二)HTML和CSS代码

     

     (三)服务器代码

    1. const http = require("http");
    2. const url = require("url");
    3. const fs = require("fs");
    4. const path = require("path");
    5. const server = http.createServer(function (req, res) {
    6. const { pathname, query } = url.parse(req.url, true);
    7. if (/^\/static/.test(pathname)) {
    8. // 拿到文件的后缀名与文件名
    9. const { base, ext } = path.parse(pathname);
    10. // 根据后缀名拼接上对应的路径
    11. let baseUrl = "./client";
    12. if (ext === ".html") {
    13. baseUrl += "/views";
    14. } else if (ext === ".css") {
    15. baseUrl += "/css";
    16. } else if (ext === ".js") {
    17. baseUrl += "/js";
    18. }
    19. // 根据处理过的路径读取对应文件返回给请求者
    20. fs.readFile(`${baseUrl}/${base}`, "utf-8", function (err, data) {
    21. if (err) {
    22. if (ext === ".html") {
    23. fs.readFile("./404.html", "utf-8", (err, data) => {
    24. if (err) return;
    25. res.end(data);
    26. });
    27. } else {
    28. res.end("");
    29. }
    30. return;
    31. }
    32. res.end(data);
    33. });
    34. }
    35. /**
    36. * 约定, 所有 接口相关的, 全都 以 /api 开头
    37. */
    38. if (/^\/api/.test(pathname)) {
    39. if (pathname === "/api/users/info" && req.method === "GET") {
    40. // 接收到请求, 去数据库 拿到对应的 数据 返回给 请求者
    41. const info = {
    42. code: 1,
    43. message: "请求 /users/info 接口 成功",
    44. info: {
    45. id: 1,
    46. name: "QF666",
    47. age: 18,
    48. },
    49. youparams: query,
    50. };
    51. // 返回给前端
    52. res.end(JSON.stringify(info));
    53. }
    54. if (pathname === "/api/users/login" && req.method === "POST") {
    55. /**
    56. * post 请求 传参 世界约定
    57. * 要么传递 查询字符串, 要么传递 json 字符串
    58. *
    59. * post 请求 传参解析 是 世界约定
    60. * 在请求头内部 配置 content-type
    61. * 如果 值 为 application/x-www-form-urlencoded 代表传递是 查询字符串
    62. * 如果 值 为 application/json 代表传递的 json
    63. */
    64. let str = "";
    65. req.on("data", (paramsStr) => {
    66. str += paramsStr;
    67. });
    68. req.on("end", () => {
    69. /*
    70. console.log(req.headers['content-type'])
    71. {
    72. ...
    73. 'content-type': 'application/x-www-form-urlencoded',
    74. ...
    75. }
    76. */
    77. if (req.headers["content-type"] === "application/json") {
    78. str = JSON.parse(str);
    79. }
    80. if (
    81. req.headers["content-type"] ===
    82. "application/x-www-form-urlencoded"
    83. ) {
    84. /**
    85. console.log(str); // username=QF001&password=123456
    86. let { query } = url.parse("?" + str, true);
    87. console.log(query)
    88. query === {
    89. username: QF001,
    90. password: 123456
    91. }
    92. */
    93. str = url.parse("?" + str, true).query;
    94. }
    95. const info = {
    96. code: 1,
    97. message: "请求 /users/login 接口 成功",
    98. youparams: str,
    99. };
    100. res.end(JSON.stringify(info));
    101. });
    102. }
    103. }
    104. });
    105. server.listen(8080, () => {
    106. console.log('恭喜你,服务器启动成功');
    107. console.log('目前正在监听8080端口! ');
    108. console.log('基准地址:http://localhost:8080');
    109. });
  • 相关阅读:
    【OpenAI】新功能发布
    MobaXterm常用使用功能设置
    Python 和 MatLab 模拟粒子动力系统
    SESSION详解
    linux如何抓包数据
    [附源码]java毕业设计智慧教学平台
    【1】请问什么是 AQS?
    SpringFramework 之EnableAsync
    Java并发编程学习笔记4——共享模型之内存
    二本4年软件测试经验,三面阿里(定薪35K),分享我的心得
  • 原文地址:https://blog.csdn.net/m0_58190023/article/details/128109235