• 浏览器发送请求的方法


    浏览器发送请求的方法

    最初的 form 表单提交

    enctype, 提交数据的格式,用 enctype 将数据发送到服务端时指定的编码类型。

    • application/x-www-form-urlencoded:

      node中的http.createServer方法中,通过监听reqdata数据,可以接受到相关传参数据。

      对于application/x-www-form-urlencoded传参方式,可以直接获取到传参xx=xxx&xx=xxx

      req.on('data', (chunk) => {
        buffer += chunk.toString('utf8');
      });
      
      • 1
      • 2
      • 3
    • multipart/form-data

      而对于multipart/form-data,则获取的数据不同,会读取到content-type后边的boundary数据

      比如 'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryxxxxxxxxxxxx',,

      此时读取的到的为------WebKitFormBoundaryxxxxxxxxxxxx,可以使用类似multiparty进行解析。

      const form = new multiparty.Form();
      form.parse(req, function (err, fields, files) {
        // fields 是通过formData传入的字段跟值
        // files 则是文件
      });
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • text/plain

      纯文本格式

    表单开始提交,浏览器就会刷新页面,然后在新页面里告诉你操作是成功了还是失败了。如果不幸由于网络太慢或者其他原因,就会得到一个 404 页面。

    ajax 的出现

    AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

    在现代浏览器上写 AJAX 主要依靠 XMLHttpRequest 对象

    AJAX 请求是异步执行的,也就是说,要通过回调函数获得响应

    var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象
    
    request.onreadystatechange = function () {
      // 状态发生变化时,函数被回调
      if (request.readyState === 4) {
        // 成功完成
        // 判断响应结果:
        if (request.status === 200) {
          // 成功,通过responseText拿到响应的文本:
          console.log(request.responseText);
        } else {
          // 失败,根据响应码判断失败原因:
          console.log(request.status);
        }
      } else {
        // HTTP请求还在继续...
      }
    };
    
    // 发送请求:
    request.open('GET', '/api/xxxx');
    request.send();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    XMLHttpRequest

    XMLHttpRequestXHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。

    readyState

    XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态。

    • 0 (UNSENT)
      XMLHttpRequest 代理已被创建,但尚未调用 open() 方法。
    • 1 (OPENED)
      open() 方法已经被触发。在这个状态中,可以通过 setRequestHeader() 方法来设置请求的头部,可以调用 send() 方法来发起请求。
    • 2 (HEADERS_RECEIVED)
      send() 方法已经被调用,响应头也已经被接收。
    • 3 (LOADING)
      响应体部分正在被接收。如果 responseType 属性是“text”或空字符串,responseText 将会在载入的过程中拥有部分响应数据。
    • 4 (DONE)
      请求操作已经完成。这意味着数据传输已经彻底完成或失败。
    var xhr = new XMLHttpRequest();
    console.log('UNSENT', xhr.readyState); // readyState 为 0
    
    xhr.open('GET', '/api', true);
    console.log('OPENED', xhr.readyState); // readyState 为 1
    
    xhr.onprogress = function () {
      console.log('LOADING', xhr.readyState); // readyState 为 3
    };
    
    xhr.onload = function () {
      console.log('DONE', xhr.readyState); // readyState 为 4
    };
    
    xhr.send(null);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    progress 事件监听如果是同步请求(open方法的第三个参数为false)则不会触发。

    onreadystatechange

    readyState属性变化时,会触发这个方法。

    // 在onreadystatechange方法中判断readyState的状态码
    request.onreadystatechange = function () {
      if (request.readyState === 4) {
        if (request.status === 200) {
          // ....
        }
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    response

    response 返回响应文本。返回的类型为 ArrayBufferBlobDocumentJavaScript Object 或字符串中的一个。这取决于请求的 responseType 属性。

    responseType

    用于指定响应中包含的数据类型。如果responseType的值为一个空字符串,那么text为默认值,response就是一个字符串。

    responseText

    返回的纯文本的值。

    只有当readyState的值为 4 及status为 200 时,responseText才是完成的返回数据。

    responseURL

    返回当前请求的url,如果是经过多次重定向的那么值为最终的url.

    XMLHttpRequestfetch内部对重定向做了处理,不会重新建立连接

    responseXML

    当响应头中的content-typetext/xml或者直接设置responseTypedocument,响应响应则会按照text/xml进行解析。

    status

    响应状态码,遵循标准响应码规范。

    HTTP 响应状态码用来表明特定 HTTP 请求是否成功完成。 响应被归为以下五大类:

    1. 信息响应 (100–199)
    2. 成功响应 (200–299)
    3. 重定向消息 (300–399)
    4. 客户端错误响应 (400–499)
    5. 服务端错误响应 (500–599)

    规范

    statusText

    响应状态码对应的文本信息。如果服务器未明确指定一个状态文本信息,则statusText的值将会被自动赋值为"OK"

    timeout

    无符号长整型数,代表着一个请求在被自动终止前所消耗的毫秒数。默认值为 0,意味着没有超时。超时并不应该用在同步 XMLHttpRequests 请求中,否则将会抛出一个 InvalidAccessError 类型的错误。当超时发生, timeout 事件将会被触发。

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/server', true);
    
    xhr.timeout = 2000; // 超时时间,单位是毫秒
    
    xhr.onload = function () {
      // 请求完成。在此进行处理。
    };
    
    xhr.ontimeout = function (e) {
      // XMLHttpRequest 超时。在此做某事。
    };
    
    xhr.send(null);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    upload

    用来表示上传的进度

    withCredentials

    是否会携带用户凭证(cookie)。

    默认false,即不携带,在httprequest中不传cookie字段。

    如果在设置为true,那么服务端的响应头也需要设置Access-Control-Allow-Credentialstrue,否则也不能正常访问(CORS错误)。

    通过设置withCredentialstrue可以获取第三方的cookies,如果以cookie作为凭证,容易造成CORS攻击。

    可能攻击的方式:

    1. 如果以cookie为凭证且指定Access-Control-Allow-Origin*,那么使用iframe嵌套直接伪造请求就可以实现cors攻击。
    2. 如果以cookie为凭证但是指定Access-Control-Allow-Origin为对应的域名,可以在控制台中直接发送请求进行攻击。
    abort

    如果请求已被发出,则立刻中止请求。

    当一个请求被终止,它的 readyState 将被置为 XMLHttpRequest.UNSENT (0),并且请求的 status 置为 0

    即使请求中断了,但是服务端仍然接受到请求,只不过浏览器拒收

    一个请求如果还没响应,这时候再发请求那么xmlHttpRequest内部会自动将前一个请求进行中断之后发送最新的请求。

    open

    初始化一个新创建的请求,或重新初始化一个请求。

    xhrReq.open(method, url, async, user, password);
    
    • 1
    • method: 使用的 HTTP 方法,比如 GETPOSTPUTDELETE、等。对于非 HTTP(S) URL 被忽略。
    • url: 请求的 URL
    • async: 是否异步执行操作,默认为 true。如果值为 falsesend() 方法直到收到答复前不会返回。如果 true,已完成事务的通知可供事件监听器使用。如果 multipart 属性为 true 则这个必须为 true,否则将引发异常。
    • user: 可选的用户名用于认证用途;默认为 null
    • password: 可选的密码用于认证用途,默认为 null
    send

    发送请求,如果请求类型为异步请求,send()方法的返回值会立即返回.

    getAllResponseHeaders

    返回响应的header信息(String 类型),以CRLF分割.如果没有接收到响应头,则返回null
    通过以下方式可以进行解析对象:

    const parsedHeaders = {};
    request
      .getAllResponseHeaders()
      .split('\n')
      .forEach((item) => {
        const i = item.indexOf(':');
        const key = item.substr(0, i).replace(/^\s*/, '').replace(/\s*$/, '');
        const val = item.substr(i + 1);
        if (key) {
          if (key === 'set-cookie') {
            parsedHeaders[key] = (parsedHeaders[key] ? parsedHeaders[key] : []).concat([val]);
          } else {
            parsedHeaders[key] = parsedHeaders[key] ? parsedHeaders[key] + ', ' + val : val;
          }
        }
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    getResponseHeader

    获取某个header属性的值,name参数为需要获取属性值的key.如果header对象不存在此属性或者获取header对象失败,则返回null.

    setRequestHeader

    设置HTTP请求头.此方法需要在open()之后和send()之前执行.如果设置了不被支持的属性,请求可能会报错。

    XMLHttpRequest.setRequestHeader(key, value);
    
    • 1

    对于FormDataBlobfile这个数据,不需要手动设置Content-Type,浏览器会自动进行设置。

    监听事件

    可通过addEventListener或者on + 事件名进行监听XMLHttpRequest实例

    • abort
    • error
    • load
    • loadstart
    • loadend
    • progress
    • timeout

    fetch

    XMLHttpRequest外,浏览器还提供了一个更简单的方法fetch

    fetch接受两个参数:

    • input: 可以是请求URL,也可以是一个Request对象(实验中)。

    • init: 一个配置项对象

      • method: 请求方法
      • headers: 请求头.
        如果是post请求,需要传content-type进行标识

        formData格式数据不需要传content-type,浏览器会进行处理。

        Blob数据如果不传content-type,会报错。

        StringObject格式数据默认content-typetext/plain;charset=UTF-8Object数据在传递时会被转换成String格式(调用toString方法变成[object Object], 需要使用JSON.stringify方法转换成string)。

      • body: 请求的 body 信息。注意 GETHEAD 方法的请求不能包含 body 信息, 不然会报错
      • mode: 请求方式(在浏览器头中的sec-fetch-mode字段), 如corsno-cors 或者 same-origin
        默认cors

        no-cors,如果是跨域,不会报错,浏览器中的请求其实已经成功,但是fetch会对response进行拦截,返回的promise是请求失败的。请求方法只限于 GETPOSTHEAD,并且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求。

        same-origin,跨域会报错。

      • credentials: 请求的 credentials,如 omitsame-origin 或者 include
        same-origin:默认值,同源请求时发送 Cookie,跨域请求时不发送。

        include:不管同源请求,还是跨域请求,一律发送 Cookie

        omit:一律不发送。

      • cache: 请求的 cache 模式:defaultno-storereloadno-cacheforce-cache 或者 only-if-cached

        default:默认值,先在缓存里面寻找匹配的请求。

        no-store:直接请求远程服务器,并且不更新缓存。

        reload:直接请求远程服务器,并且更新缓存。

        no-cache:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存。

        force-cache:缓存优先,只有不存在缓存的情况下,才请求远程服务器。

        only-if-cached:只检查缓存,如果缓存里面不存在,将返回 504 错误。

      • redirect: 可用的 redirect 模式:follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误),或者 manual (手动处理重定向)。在 Chrome 中默认使用 followChrome 47 之前的默认值是 manual)。

        follow默认值,fetch()跟随 HTTP 跳转

        error,当请求返回是重定向时,会报错

        manual, fetch()不跟随 HTTP 跳转,response.url属性会指向当前 URL

      • referrer: 一个 USVString 可以是 no-referrerclient 或一个 URL。默认是 client
        设置这个值(xxx),那么请求中的refer字段值为host + xxx
        这个属性可以为任意字符串,也可以设为空字符串(即不发送 referer 标头)。
      • referrerPolicy: 指定了 HTTP 头部 referer 字段的值。可能为以下值之一:no-referrerno-referrer-when-downgradeoriginorigin-when-cross-originunsafe-url

        no-referrer不携带referer字段

        no-referrer-when-downgrade:默认值,总是发送Referer标头,除非从 HTTPS 页面请求 HTTP 资源时不发送

        originreferer标头只包含域名,不包括路径

        origin-when-cross-origin:同源请求Referer标头包含完整的路径,跨域请求只包含域名。

        unsafe-url:不管什么情况,总是发送Referer标头。

        strict-originReferer标头只包含域名,HTTPS 页面请求 HTTP 资源时不发送Referer标头。

        strict-origin-when-cross-origin:同源请求时Referer标头包含完整路径,跨域请求时只包含域名,HTTPS 页面请求 HTTP 资源时不发送该标头。

      • integrity: 包括请求的 subresource integrity 值(例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
        integrity:指定一个哈希值,用于检查 HTTP 回应传回的数据是否等于这个预先设定的哈希值。

        比如,下载文件时,检查文件的 SHA-256 哈希值是否相符,确保没有被篡改

        fetch('http://site.com/file', {
          integrity: 'sha256-abcdef',
        });
        
        • 1
        • 2
        • 3
      • signal:指定一个 AbortSignal 实例,用于取消fetch()请求

    返回一个promiseresolve 时回传 Response 对象。

    取消请求

    let controller = new AbortController();
    
    fetch(url, {
      signal: controller.signal,
    });
    
    controller.signal.addEventListener('abort', () => console.log('abort!'));
    // controller.abort()方法用于发出取消信号。这时会触发abort事件,这个事件可以监听
    controller.abort(); // 取消
    // 可以通过controller.signal.aborted属性判断取消信号是否已经发出
    console.log(controller.signal.aborted); //
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    当调用了abort方法后,controller实例就不能再使用了,controller.signal.aborted已经变成true了,该属性只读,不能修改值来实现再次使用(会报错),只能通过在创建一个AbortController实例来中断。

  • 相关阅读:
    Electron学习笔记(一)
    php-java-net-python-北京名胜古迹展览网站计算机毕业设计程序
    【OAuth2】十八、OIDC的认识应用
    线程状态与线程安全
    使用Python调用API接口获取淘宝商品数据
    Cy5反式环辛烯,TCO-Cy5,Cy5 trans-cyclooctene标记生物分子
    牛客网刷题记录 || 循环
    跨域?如何解决?同源策略?
    Elasticsearch应用场景(三)
    世界杯——手动为梅西标名
  • 原文地址:https://blog.csdn.net/qq_42880714/article/details/127761108