写一个服务,既可以处理静态资源文件请求,又可以响应 AJAX 请求

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="/static/css/index.css">
  7. </head>
  8. <body>
  9. <h1>
  10. index.html
  11. </h1>
  12. <ul>
  13. <li>
  14. <a href="/1-axios.html">AXIOS</a>
  15. </li>
  16. <li>
  17. <a href="/login.html">登录</a>
  18. </li>
  19. </ul>
  20. <script src="/static/js/index.js"></script>
  21. </body>
  22. </html>

login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. .box {
  12. margin: 30px auto;
  13. width: 400px;
  14. height: 300px;
  15. overflow: hidden;
  16. }
  17. .box .item {
  18. margin-left: 40px;
  19. margin-top: 15px;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <h1>
  25. login.html
  26. </h1>
  27. <div class="box">
  28. <div class="item">
  29. <span>用户名</span>
  30. <input type="text" placeholder="请输入用户名" id="username">
  31. </div>
  32. <div class="item">
  33. <span>密码</span>
  34. <input type="password" id="pwd" />
  35. </div>
  36. <div class="item">
  37. <button id="loginBtn">登录</button>
  38. </div>
  39. </div>
  40. <script src="/static/js/axios.js"></script>
  41. <script src="/static/js/3-login.js"></script>
  42. </body>
  43. </html>

login.json

  1. {
  2. "code": 0,
  3. "data": {
  4. "token": "dsaf1si3hfaskjlf3"
  5. },
  6. "msg": "ok"
  7. }

js

  1. // 根据 pathname不同,响应不同的内容;
  2. // 静态资源文件请求的 pathname: /(index.html) /a/b/xxx.css xx.js xx.png .. myDream.m4a;
  3. // 静态资源文件请求的 pathname 除了 / ,都带有扩展名;
  4. // ajax 请求 pathname: /home/help/search ;而 ajax 接口是不带扩展名的;
  5. let http = require('http');
  6. let url = require('url');
  7. let fs = require('fs');
  8. let mime = require('mime');
  9. // 1. 创建服务
  10. let server = http.createServer((req, res) => {
  11. let urlObj = url.parse(req.url, true); // 处理 url
  12. let {pathname, query} = urlObj; // 从 urlObj 中获取 pathname 和 query(query 是客户端 get 请求时传递的问号传参,经过 url 模块解析后形成的一个对象)
  13. // 判断请求是静态资源请求 还是动态的 ajax 请求;
  14. // 如果是静态资源文件请求 pathname 会带有 .xxx 扩展名或者 pathname 是 /
  15. if (pathname === '/' || /(\.\w+)$/.test(pathname)) {
  16. // 如果满足这个条件,说明请求的是静态资源文件
  17. let filePath = '';
  18. let contentType = '';
  19. if (pathname === '/') {
  20. filePath = __dirname + '/index.html'; // 计算机读取文件时需要一个路径,可以使用绝对路径也可以使用相对路径;
  21. contentType = 'text/html';
  22. } else {
  23. filePath = __dirname + pathname;
  24. contentType = mime.getType(pathname);
  25. }
  26. // 设置响应头
  27. res.setHeader('Content-Type', contentType);
  28. fs.readFile(filePath, (err, data) => {
  29. if (err) {
  30. res.statusCode = 404;
  31. res.end('not found');
  32. } else {
  33. res.end(data);
  34. }
  35. })
  36. } else {
  37. // else 的情况就是 ajax 请求
  38. // 根据不同接口返回不同的内容,即根据 pathname 不同,做不同操作;这种机制叫做路由;
  39. // 因为现在 ajax 没有特殊情况返回的都是 json,所以在这里设置
  40. // ajax 请求的接口也是 pathname,因为请求这个 pathname 不再返回静态资源文件,而是根据客户端的请求返回不同的内容;
  41. res.setHeader('Content-Type', 'application/json;charset=UTF-8;');
  42. if (pathname === '/api/getBanner') {
  43. // 这个接口的作用就是返回指定 id 的 banner 图信息;
  44. // 从 query 中获取客户端传过来的 id,如果获取不到 id 是 undefined;
  45. let {id} = query;
  46. // console.log(typeof id);
  47. // id 存在返回指定 id 的数据,不存在返回全部
  48. if (id) {
  49. // 如果 id 存在
  50. let con = fs.readFileSync(__dirname + '/banner.json', 'utf8'); // 读取回来的结果是 JSON 格式的字符串;(现在没有数据库,真实项目中这里要查数据库)
  51. let dataArr = JSON.parse(con);
  52. let itemById = dataArr.find(item => +item.id === +id); // 传过来的 id 是 string 类型的,而数组项中的 id 是 number 类型的;需要转一下 number
  53. // find 的结果有可能不存在,不存在的时候是 undefined
  54. let d = {
  55. code: 0,
  56. data: {
  57. data: null
  58. },
  59. msg: 'ok'
  60. };
  61. if (itemById) {
  62. d.data.data = itemById;
  63. } else {
  64. d.data.data = {};
  65. d.code = -1;
  66. d.msg = `id${id}的banner不存在`
  67. }
  68. res.end(JSON.stringify(d)); // res.end() 只能接收 Buffer 或者字符串;所以需要把对象 d 转成 JSON 格式的字符串
  69. // console.log(con);
  70. // console.log(typeof con);
  71. } else {
  72. // 如果 id 不存在
  73. let conAll = fs.readFileSync(__dirname + '/banner.json', 'utf8');
  74. let conAllAry = JSON.parse(conAll);
  75. // 构造接口文档约定的数据结构
  76. let d2 = {
  77. code: 0,
  78. data: {
  79. data: conAllAry
  80. },
  81. msg: 'ok'
  82. };
  83. res.end(JSON.stringify(d2));
  84. }
  85. }
  86. // 登录接口:根据用户 post 过来的数据去和咱们数据库中的数据比对;首先获取客户端传递的数据中的用户名和密码,然后从数据库中查找和传递用户名一样的数据,如果找到用户名一样的,接着比对密码,用户名和密码都相同才算是登录成功,其他情况都是登录失败
  87. if (pathname === '/api/login') {
  88. // post 请求方式:
  89. // 1. 构造约定的数据结构,默认成功
  90. let d3 = {
  91. code: 0,
  92. data: null,
  93. msg: 'ok'
  94. };
  95. // 2. 获取客户端 post 过来的数据;因为 post 请求传递的数据比较大,客户端会切片,一片一片的传递,而服务器也是一片一片的接收;所以 Node.js 是靠两个事件来接收 post 数据的
  96. let dataStr = '';
  97. req.on('data', (chunk) => {
  98. // 服务端在接收客户端 post 过来的数据的时候,每接收一次会触发一次 data 事件,触发一次 data 事件就会执行一次这个回调函数;
  99. // console.log(chunk);
  100. dataStr += chunk;
  101. });
  102. req.on('end', () => {
  103. // 服务端接收 post 数据结束后触发 end 事件,就会执行这个回调
  104. // console.log('完了');
  105. // console.log(typeof dataStr); string dataStr 此时已经有了全部的客户端传递过来的数据了,但是是一个字符串类型的;需要转成对象;
  106. let dataObj = JSON.parse(dataStr);
  107. // 根据 dataObj 中的用户名去数据库中查找
  108. let conUser = fs.readFileSync('./user.json', 'utf8');
  109. let conUserAry = JSON.parse(conUser);
  110. // console.log(Array.isArray(conUserAry));
  111. let user = conUserAry.find(item => item.name === dataObj.username);
  112. // 根据用户名查询的结果有可能不存在,所以需要判断
  113. if (user) {
  114. // 说明库里面有这个用户名,但是仍然需要比对密码
  115. if (user.pwd === dataObj.pwd) {
  116. res.end(JSON.stringify(d3));
  117. } else {
  118. d3.code = 1;
  119. d3.msg = '用户名或者密码错误';
  120. res.end(JSON.stringify(d3));
  121. }
  122. } else {
  123. // else 说明库里面没有这个用户
  124. d3.code = -1;
  125. d3.msg = `${dataObj.username}不存在,请前往注册`;
  126. res.end(JSON.stringify(d3));
  127. }
  128. })
  129. }
  130. }
  131. });
  132. // 2. 监听端口号
  133. server.listen(8000, () => console.log('port 8000 is on'));

接口文档

  1. # 接口文档
  2. ## 1. 获取指定 id 的 banner 图信息
  3. + 接口:/api/getBanner
  4. + 请求方式:GET
  5. + 参数:id int,默认空
  6. + 参数意义:要获取的 banner 图的 id,不传获取全部
  7. + 返回值示例:
  8. 1. id 不传时返回全部
  9. ```json
  10. {
  11. code: 0,
  12. data: {
  13. data: [
  14. {
  15. "id": 1, // banner 图 id
  16. "img": "/static/img/banner1.jpg", // 图片的地址
  17. "desc": "广阔的就业推荐机会", // 图片描述
  18. "link": "http://www.zhufengpeixun.cn/" // 跳转链接
  19. },
  20. ....
  21. ]
  22. },
  23. msg: 'ok'
  24. }
  1. 传id
  1. {
  2. code: 0,
  3. data: {
  4. data: {
  5. "id": 1, // banner id
  6. "img": "/static/img/banner1.jpg", // 图片的地址
  7. "desc": "广阔的就业推荐机会", // 图片描述
  8. "link": "http://www.zhufengpeixun.cn/" // 跳转链接
  9. }
  10. },
  11. msg: 'ok'

2. 登录

  • 接口:/api/login
  • 请求方式:POST
  • 参数:
    • username 用户名
    • pwd 用户密码

{username: ‘mabin’, pwd: ‘123455’}

  • 返回值:
  1. {
  2. code: 0, // 0 成功,其他失败
  3. data: null,
  4. msg: 'ok'
  5. }

```