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请求

原文地址:https://www.cnblogs.com/yichi/p/11014267.html

时间: 2024-10-16 00:55:21

Webpack运行后,XMLHttpRequest发送带参请求,后台$_POST没有数据的相关文章

VS2015启动运行后一直发送VsHub请求解决方案

原文:VS2015启动运行后一直发送VsHub请求解决方案 VS2015启动运行后,打开Fiddler监听接口调用实际请求,结果发现全部都是VsHub的请求(图1),想看到自己想要的请求非常难. 解决办法: 1.杀死VsHub.exe和Microsoft.VsHub.Server.HttpHostx64.exe进程. 2.把C:\Program Files (x86)\Common Files\microsoft shared\VsHub\1.0.0.0文件夹重命名. 注意:杀死进程后会自动启动

利用postman进行接口测试并发送带cookie请求的方法

做web测试的基本上都用用到postman去做一些接口测试,比如测试接口的访问权限,对于某些接口用户A可以访问,用户B不能访问:比如有时需要读取文件的数据.在postman上要实现这样测试,我们就必要要用到cookie请求.用postman发送带cookie的请求,由于chrome安全的限制,postman是发不出带cookie的请求.如果想要发送带cookie的请求,需要开启postman Interceptor. 什么是POSTMAN? POSTMAN是一个Chrome插件工具,我们可以通过

thymeleaf的初次使用(带参请求以及调用带参js方法)

之前对于前端框架接触较少,第一次接触thymeleaf,虽说看起来并不复杂但我还是花费了好一会儿才弄懂. 话不多少下面就简单说一下我在项目中的应用. 首先是java代码 controller层 将需要在前端展示的信息放入model中: @RequestMapping("getAll") public String getAll(Model model){ List<ScheduleJob> list = scheduleJobService.getAllJob(); mod

C#--带参SQL语句数通用数据访问类

Update() GetSingleResult() GetReader() 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data; 6 using System.Data.SqlClient; 7 using System.Configuration; 8 9 10 namespace DAL.Helper 11 { 12

XMLHttpRequest发送XML请求

1.前言 对于请求参数为大师key-value对的情形,笔者更加倾向于使用简单的POST请求.但对于某些极端的表形,如请求参数特别多,而且请求参数的结构关系复杂,则可以考虑发送XML请求.XML请求的实质还是POST请求,只是在发送请求的客户产端页面将请求参数封装成XML字符串的形式,服务器则负责解析XML字符串.当然,服务器获取到XML字符串后,可借助dom4j或JDOM等工具来解析. 2.例子 这个例子还是跟前面所讲的一样,通过左边的点击国家,然后点击"发送",右边 就可以看到国家

XMLHttpRequest发送POST请求

1.前言 POST请求的适用性更广,可使用更大的请求参数,而且POST请求的请求参数通常不能直接看到.因此在使用Ajax发送请求时,尽量采用POST方式而不是GET方式发送请求.发送POST请求通常需要如下的三个步骤: 1)        使用open方法打开连接时,指定使用POST方式发送请求. 2)        设置正确的请求头,POST请求通常应设置Content-Type请求头 3)        发送请求,把请求参数转换为查询字符串,将字符串作为send()方法请求参数. 2.例子

如何使用HttpClient来发送带客户端证书的请求,以及如何忽略掉对服务器端证书的校验

最近要做客户端和服务器端的双向认证,在客户端向服务器端发送带证书的请求这里有一点问题,网上的例子大多都不太好使,于是找了github上httpclient源代码中的例子改造了一下,终于弄明白了 github上我参考的例子在:https://github.com/apache/httpclient/blob/4.5.x/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.java 下面先贴上我自己的代码(需

使用xmlHttprequest 发送异步请求(Ajax核心对象)

1.创建XMlHtttpRequest对象 因为浏览器不同载入xmlHttpRequst的方式也不一样 IE中:var  xmlhttp=new ActiveXObject("MSXML2.XMLHTTP"); 其他浏览器:var  xmlhttp=new  XMLHttpRequest(); 2.对onreadystatechange事件追加方法 当xmlhttp.readystate 状态改变时会自动触发这个事件 readystate可能出现的五种状态: 0:未初始化:XMLHtt

Postman发送带cookie的http请求

Postman是chrome上一个非常好用的http客户端插件,可惜由于chrome安全的限制,发不出带cookie的请求.如果想要发送带cookie的请求,需要开启Interceptor: 这个Interceptor还需要到chrome应用商店下载 Postman Interceptor 扩展程序.现在能发送带cookie的http请求.发送cookie时,在header中添加key-value,key固定为Cookie,value是cookie具体的k=v,例如: 需要注意的是,发送带coo