尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题

CAM*_*344 3 java jquery web-services cors reactjs

问题/摘要:

问题,我在使用应用程序 json 数据执行 jQuery 帖子时收到 CORS 错误响应。但是我没有收到带有纯文本/文本或 x-www-urlencoded-form 数据的 jQuery 帖子的错误。

问题/详情:

我有两个应用程序在我的 Ubuntu VM 上运行,一个是 React 应用程序http://localhost:3000,一个是从我的 Netbeans 10 IDE 的 Payara 服务器运行的 Java Web 服务,位于此 url http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall。我正在尝试使用从 React 应用程序到 Web 服务的不同内容类型来测试不同的 jQuery Posts。

为了避免收到 CORS 错误消息,我将其添加到了 java web 服务器 HttpServletRequest 对象 response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");

但是,在使用 Json 数据执行 jQuery 帖子时出现此错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Run Code Online (Sandbox Code Playgroud)

但是我还有另外两种执行 jQuery Posts 的测试方法(一种content-type是存在的text/plain,另一种application/x-www-form-urlencoded是没有这个问题的。即我​​可以成功地将 jQuery Post 消息发送到 Web 服务并得到响应。

这是带有 json 数据的 jQuery Post 代码,其中我遇到了 CORS 响应问题

  var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

  $.ajax({
     type: "POST",
     dataType: "json",
     contentType: 'application/json; charset=utf-8',
     //crossDomain: true,
     url: urlToPost,
     async:true,
     data: JSON.stringify({ Object: 'CD', Quantity: '4' }),
     success: function(response) {
        console.log("json response: " + response);
    },
    failure: function(errMsg) {
        alert(errMsg);
    }
 }); 
Run Code Online (Sandbox Code Playgroud)

这是带有纯文本的 jQuery 帖子,该帖子有效(即没有 CORS 响应,我可以看到正在访问的 Web 服务代码,并且我可以看到对启动 jQuery 帖子的这个 React 应用程序的响应):

var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

   $.ajax({
       type: "POST",
       //dataType: "text",
       contentType: 'text/plain',
       url: urlToPost,
       data: "Hello from CommunicationForm (plain text)",
       success: function(response) {
         console.log("plain text response: " + response);
       }
   });   
Run Code Online (Sandbox Code Playgroud)

这是我的带有 x-www-urlencoded-form 的 jQuery 帖子,它也有效:

  var myObject = {
      var1: 'Hello from CommunicationForm'  
   };
   var urlToPost = 'http://cduran-VirtualBox:8080/TestMavenWebApplication/firstservicecall';

   $.ajax({
       type: "POST",
       //dataType: "text",
       contentType: 'application/x-www-form-urlencoded; charset=utf-8',
       url: urlToPost,
       data: myObject,
       success: function(response) {
           console.log("application/x-www-form-urlencoded response: " + response);
       }
   });
Run Code Online (Sandbox Code Playgroud)

作为进一步的证据,这是我的 React 应用程序的屏幕截图,您可以忽略输入文本字段,因为它什么都不做。但我有 3 个输入提交按钮。从按钮名称可以推断出,一个使用 x-www-urlencoded-form 内容类型执行上面的 jQuery 帖子,另一个执行 text/plain,另一个执行 json。

在此处输入图片说明

单击 x-www.. 按钮后,此日志语句(如屏幕截图所示)将从 Web 服务接收回(表明它工作正常)。

application/x-www-form-urlencoded 响应:您好,从 Servlet 返回 - 收到的内容类型 x-www-form-urlencoded

单击纯文本按钮后,此日志语句显示在屏幕截图上,这再次证明 jQuery Post 工作正常:

纯文本响应:您好从 Servlet 返回 - 内容类型收到纯文本

最后两条控制台日志消息是单击 Submit_json 按钮后的 CORS 错误响应。

编辑/更新 2:

附加说明 - 使用 Post Man 应用程序,我可以将内容类型为 application/json 的 HTTP Post 发送到我的 Java Web 服务应用程序并看到响应。

我创建了一个常规的 Maven Java 应用程序(不是 Web 应用程序),我还可以向我的 Java Web 服务应用程序发送一个带有 application/json 作为内容类型的 HTTP Post,我可以在其中看到很好的响应。

当我从我的 REACT Web 应用程序提交带有 application/json 的 jQuery POST 时,我在 Web 浏览器上的开发人员工具的网络页面上看到 POST 作为选项发送(这发生在 Firefox 和 Chrome 浏览器中)。

此链接https://github.com/angular/angular/issues/22492中的评论提到发送简单请求,并列出不包含application/json.

这确实让事情变得更加混乱。

编辑/更新 1:

这是我的后端服务器代码。没什么特别的,它只是检查 content-type 头字段,然后解析对象并将不同的响应发送回 React 应用程序。

public class FirstServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

        String contentType = request.getHeader("content-type");
        response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");

        if (contentType.equals("text/plain")) {
            InputStream is = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line = "";
            while((line = br.readLine()) != null) {
                System.out.println("Plain/Text data received: " + line);
            }
            response.getWriter().print("Hello back from Servlet - content type received plain text");
        } else if (contentType.equals("application/x-www-form-urlencoded; charset=utf-8")) {
            String msgReceived = request.getParameter("var1");
            System.out.println("Message Received: " + msgReceived);            
            response.getWriter().print("Hello back from Servlet - content type received x-www-form-urlencoded");
        } else if (contentType.toLowerCase().contains("json")) {
           JSONObject json = new JSONObject(request.getParameterMap());
           System.out.println("json data received: " + json.toString());
                       response.getWriter().print("Hello back from Servlet - content type received application/json");
        } else {
            response.getWriter().print("Hello back from Servlet - content type undefined");
        }
    }    
}
Run Code Online (Sandbox Code Playgroud)

小智 5

简单请求中 Content-Type 标头的唯一值如下:

  • 应用程序/x-www-form-urlencoded
  • 多部分/表单数据
  • 文本/普通

尝试将“application/json”更改为其他内容类型,否则浏览器将执行预检请求。

请参阅 CORS 文档:https : //developer.mozilla.org/en-US/docs/Web/HTTP/CORS