node 第五天 结合 原生javascript网络请求方法XMLHttpRequest和原生node服务端 实现简单登录流程

  1. 前话

网络请求是前端和服务端配合的重要工具, 不是前端或服务端的特有, 所以要真正了解网络请求
必须手写前端和服务端, 才能真正理解一些东西

  1. 前端代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ajax</title>
  </head>
  <body>
    账号: <input id="user" type="text" /> 密码: <input id="pwd" type="password" />
    <button id="submit">提交</button>
    <p id="msg"></p>
    <script>
      const user = document.querySelector('#user');
      const pwd = document.querySelector('#pwd');
      const btn = document.querySelector('#submit');
      const msg = document.querySelector('#msg');
      btn.addEventListener('click', () => {
        // 表单请求原生node很难解析, 需要正则切割, 错误处理
        // const form = new FormData();
        // form.append('user', user.value);
        // form.append('pwd', pwd.value);
        // request(form);
        const data = {
          user: user.value,
          pwd: pwd.value
        };
        request(JSON.stringify(data));
      });
      function request(data) {
        const ajax = new XMLHttpRequest();
        ajax.open('POST', 'http://127.0.0.1:3001/ajax', true);
        ajax.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
        ajax.send(data);
        ajax.onreadystatechange = function (res) {
          if (ajax.readyState === 4) {
            if (ajax.response === '密码错误') {
              msg.innerHTML = '密码错误';
            } else {
              const userInfo = JSON.parse(ajax.response);
              msg.innerHTML = `登陆成功欢迎您${userInfo.user}, 本次登录返回的token是${userInfo.token}, 请保存在cookie, 用来做身份令牌`;
            }
          }
        };
      }
    </script>
  </body>
</html>

  1. 后端代码 (额…有些引入的模块没用到)
// const { http, fs, querystring, url } = require('./module');
const http = require('http');
const fs = require('fs');
const path = require('path');
const querystring = require('querystring');
const url = require('url');
const multiparty = require('multiparty');

const app = http.createServer((req, res) => {
  if (req.url === '/ajax') {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE');
    if (req.method === 'OPTIONS') {
      res.writeHead(200, 'text/plain;charset=utf-8');
      // 完成预检请求, 客户端才会携带请求体, 服务端才能收到, 所以必须同步调用res.end()
      // 预检请求:
      // 如果服务器同意处理请求,那么它会进行响应,此响应的状态码应该为 200,没有 body,具有 header
      // 所以res.end('receive ajax OPTIONS', 'utf-8') 写法等价于 res.end()  你必须给予预检回应 但是却无法回应请求体
      res.end('receive ajax OPTIONS', 'utf-8');
    } else {
      //预检通过, 正式发起请求
      req.on('data', chunk => {
        const reqData = JSON.parse(chunk.toString('utf-8'));
        if (reqData.pwd !== '456') {
          res.setHeader('Content-Type', 'text/plain;charset=utf-8');
          res.writeHead(403);
          res.end('密码错误');
        } else {
          reqData.token = '10086';
          res.setHeader('Content-Type', 'application/json');
          res.writeHead(200);
          res.end(JSON.stringify(reqData));
        }
      });
    }
  }
});
app.listen(3001);

  1. 你真正理解如何解决js网络请求模块引起的跨域吗 ?

跨域, 为javascript而生, 为了javascript更加强大, 也为了其不能肆意妄为
跨域从来不限制html, 所以有人用 表单+ifram 和 script 标签(JSONP)的方式解决跨域, 但是不得不说
他们已经被淘汰了. 旧时代的洪水猛兽本应该逐渐消退

  1. 从服务端和前端解决跨域, 让js网络请求模块也具备跨域的能力, 而不仅仅是html可以跨域
  • 这里有一个极好的教程, 简洁有力, 教程
  • 阅读教程, 配合手写服务端, 你能理解OPTIONS预检请求, 理解了预检请求也就理解了, 跨域如何保证所谓的安全性
  • 用js网络模块(XMLHttpRequest或fetch)发起一个跨域请求并且该请求是非安全请求, 需要先发送一个预检请求, 预检请求是浏览器实现的规范,预检请求发生在“幕后”,它对 JavaScript 不可见, javascript不可见, 意味着预检请求并不是一个XHR/Fetch, 阅读教程想必你已经知道, 预检请求之后才会发送真正的XHR请求, 服务端不仅要处理预检请求, 还要处理XHR请求, 这里又有诸多细节, 可以参考代码加以理解
  1. 注: 本文词汇–> 服务端亦是指后端, 网络请求以http协议为基础
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值