尝试使用json数据执行JQuery post时出现CORS问题,但不能使用纯文本或x-www-form-urlencoded

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试使用json数据执行JQuery post时出现CORS问题,但不能使用纯文本或x-www-form-urlencoded相关的知识,希望对你有一定的参考价值。

发行/概述:

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

发行/详细信息:

我在我的Ubuntu VM上运行了两个应用程序,一个在http://localhost:3000上运行的React应用程序,以及一个从我的Netbeans 10 IDE在这个url http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall上从Payara Server运行的Java Web服务。我正在尝试测试从React应用程序到Web服务使用不同内容类型的不同jQuery帖子。

为了避免收到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).

但我有两个其他测试方法做jQuery帖子(一个content-typetext/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);
    }
 }); 

这是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);
       }
   });   

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

  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);
       }
   });

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

enter image description here

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

application / x-www-form-urlencoded response:来自Servlet的Hello - 收到的内容类型x-www-form-urlencoded

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

纯文本响应:从Servlet返回Hello - 内容类型接收纯文本

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

编辑/更新2:

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

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

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

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

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

编辑/更新1:

这是我的后端服务器代码。没有什么特别的,它只是检查内容类型头字段,然后解析对象并将不同的响应发送回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");
        }
    }    
}
答案

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

  • 应用程序/ x-WWW窗体-urlencoded
  • 多部分/格式数据
  • 纯文本/

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

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

另一答案

CORS完全依赖于响应中的Access-Control-Allow-Origin标头值,并且似乎对具有json内容类型的请求的响应未接收到此标头。

我认为具有JSON内容类型的请求可能在服务器端失败,并且标头“Access-Control-Allow-Origin”仅为成功请求设置。

您是否通过在response.addHeader("Access-Control-Allow-Origin", "http://localhost:3000");上调试点来检查它是否因为JSON内容类型请求而被点击?

你可以分享一下这个标题设置的服务器代码吗?

对不起,我在答案部分询问我的问题而不是评论,因为我现在无法发表评论。

编辑:更新了应用程序/ json内容类型POST查询的Jquery代码。请分享请求的原始格式,如果不起作用,可以在“网络”选项卡下看到。由于请求的格式不正确,因此它没有达到服务器端的实现,这也就是为什么没有在响应中设置标头。

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

  $.ajax({
     url: urlToPost,
     type: "POST",
     contentType: 'application/json',
     data: JSON.stringify({ “Object”: “CD”, “Quantity”: “4” }),
     success: function(response) {
        console.log("json response: " + response);
    },
    failure: function(errMsg) {
        alert(errMsg);
    }
 }); 
另一答案

我想我可能已经找到了这个问题,进一步巩固了Indrajit Bhaskaran在上面的回答。

根据这个链接https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers#Directives

请注意,始终允许某些标头:Accept,Accept-Language,Content-Language,Content-Type(但只能使用其解析值的MIME类型(忽略参数)application / x-www-form-urlencoded,multipart / form-data,或text / plain)。这些称为简单标头,您无需明确指定它们。

上面提到的关键是,只允许从网站到请求后端的3种内容类型。

以上是关于尝试使用json数据执行JQuery post时出现CORS问题,但不能使用纯文本或x-www-form-urlencoded的主要内容,如果未能解决你的问题,请参考以下文章

nginx,jquery - 执行 POST 时出现 Access-Control-Allow-Origin 错误

尝试 POST 时出现“无效的 JSON”

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

将 JSON 数据从 JQuery 发送到 WCF REST 方法时出现问题

为啥我在执行 POST 请求时收到 405 Method Not Allowed

使用 jquery 将数据表转换为 Json