Webpack运行后,XMLHttpRequest发送带参请求,后台$_POST没有数据

Posted yichi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpack运行后,XMLHttpRequest发送带参请求,后台$_POST没有数据相关的知识,希望对你有一定的参考价值。

环境:

  打包工具: Webpack;

  整合软件包: WAMP;

  编辑器:VsCode;

 Webpack虚拟出的端口号是8080,本地Apache的端口号是80

问题重现:

JS代码,使用FormData对象作为传输数据的格式:

function postData() 
    var formData = new FormData();
    formData.append("data", JSON.stringify(name:‘xxx‘, age:20));
    
    function xhrRequest(resolve, reject) 
      var xhr = new XMLHttpRequest();
      xhr.open(‘POST‘, _this.gRequestphpUrl);
      xhr.setRequestHeader("cache-control","no-cache"); //②
      xhr.onreadystatechange = function() 
         if (this.readyState === 4 && this.status === 200)
           var dataResp = JSON.parse(this.responseText);
           resolve(dataResp, this);
         
         else 
            reject(‘网络错误:‘ + this.status, this);
         
      
      xhr.send(formData);
    
    
    var sendReq = new Promise(xhrRequest);
    return sendReq;

PHP代码,使用跨域接收他域传来的访问请求:

<?php
    header(‘Access-Control-Allow-Origin:*‘);
    header(‘Access-Control-Allow-Headers: cache-control‘);  //①

    if ( !isset($_POST[‘data‘]))
        return;
    
    file_put_contents(‘./rec.txt‘, json_encdoe($_POST[‘data‘]));
   $objResp = new class;
   $objResp->data = ‘this is from server‘;
   echo json_encode($objResp);
?>

问题:

  XMLHttpRequest请求代码在Webpack虚拟的环境中发出,请求PHP文本资源。调试PHP时发现JS发起请求后,$_POST数组处于—— 一次请求数组为空、下一次请求数组有元素、再下一次请求数组又为空,这样有序的循环中。且每次请求file_get_contents("php://input", "r")中也没有值。

  奇怪的是当$_POST数组为空时前端竟然收到了正确的JSON格式消息。

问题排查:

  觉得奇怪的是前台用FormData包裹的数据,后台$_POST数组却为空,且从‘php://input’中读不到值。

 1. 怀疑JS发起请求的请求头‘Content-Type‘值不对。Server通过这个字段得到请求头的类型,然后进行解析。[1]  如果解析不对,$_POST数据将出错或没有数据。 ——》  尝试各种’Content-Type‘,没有解决这个问题;

 2. 注意到浏览器控制台有OPTIONS类型的请求,即某次请求发出,控制台出现一次OPTIONS请求,

技术图片

发现该请求里没有请求数据,此时调试PHP,发现$_POST为空的情况。随即在没有手动发送请求情况下控制台自动发出一次POST请求,这时请求里包含请求数据。

 技术图片

解决方案:

  不让浏览器发送OPTIONS请求,而是只发送一次POST请求。

  查阅资料后了解OPTIONS请求是一个预检请求,xhr判断请求头里的URL路径是否能被访问到,若不能的话就返回一个CORS策略问题(

技术图片

上图是注释掉①处代码会出现的问题,因为跨域时PHP需要设置能够接收包含’cache-control‘的请求头),若可以的话就会再次发送原来的POST请求。

 如果在跨域时不想要发送OPTIONS请求,需满足下列条件:[2]

1. 不要发送下列方法的请求:

  PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH

2. 除请求头自带的设置,不要手动设置除下列的其它字段:

  Accept、Accept-Language、Content-Language、Content-Type (but note the additional requirements below)、DPR、Downlink、Save-Data、Viewport-Width、Width

3.  上述2中的’Content-Type‘字段不可以设置除以下的值:

  application/x-www-form-urlencoded、multipart/form-data、text/plain

 

综上所述,只要把代码中的①和②处注释掉就可以了。

 

参考:

[1]    https://blog.csdn.net/qq_27845259/article/details/83106391   ——   ’Content-Type‘字段类型及简介

[2]    https://juejin.im/entry/58eaf351a22b9d0058a8e35c    ——    浅谈 AJAX 跨域请求时的 OPTIONS 方法

https://segmentfault.com/a/1190000016040998   ——   发送两次请求,其中有个是OPTIONS请求

以上是关于Webpack运行后,XMLHttpRequest发送带参请求,后台$_POST没有数据的主要内容,如果未能解决你的问题,请参考以下文章

webpack 构建后运行命令

安装weback后,运行webpack -v报错:‘webpack’不是内部或者外部命令

安装后 webpack 无法在 Heroku 上运行

SCRIPT7002:XMLHttpRequest:网络错误 0x80070005,成功预检请求后拒绝访问

原生Ajax XMLHttpRequest对象

vue项目用webpack打包后运行后找不到.ttf及.woff文件