尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题
Posted
技术标签:
【中文标题】尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题【英文标题】:CORS issue when trying to do JQuery post with json data, but not with plain text or x-www-form-urlencoded 【发布时间】:2019-08-14 11:35:10 【问题描述】:问题/摘要:
问题,我在使用应用程序 json 数据进行 jQuery 发布时收到 CORS 错误响应。但是对于带有纯/文本或 x-www-urlencoded-form 数据的 jQuery 帖子,我没有收到该错误。
问题/详情:
我有两个应用程序在我的 Ubuntu VM 上运行,一个在 http://localhost:3000
上运行的 React 应用程序和一个 Java Web 服务从我的 Netbeans 10 IDE 的 Payara 服务器上运行,网址为 http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall
。我正在尝试测试从 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 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);
);
这里是纯文本的 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);
);
这是我的带有 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);
);
作为进一步的证据,这是我的 React 应用程序的屏幕截图,您可以忽略输入文本字段,因为它什么都不做。但我有 3 个输入提交按钮。从按钮名称可以推断,一个是上面的 jQuery 帖子,内容类型为 x-www-urlencoded-form,另一个是 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 应用程序),我还可以将 application/json 作为内容类型的 HTTP Post 发送到我的 Java Web 服务应用程序,我可以在其中看到响应正常。
当我从我的 REACT Web 应用程序提交带有 application/json 的 jQuery POST 时,我在 Web 浏览器上的开发人员工具的网页上看到 POST 作为 OPTION 发送(这发生在 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");
【问题讨论】:
收到这些错误消息时响应的 HTTP 状态代码是什么?使用浏览器开发工具中的网络窗格进行检查。此外,问题中的控制台屏幕截图显示了两条 XML Parsing Error: syntax error 消息正在控制台中记录。为什么? 更有趣的是,使用 PostMan 应用程序,我可以将 Content-Type 设置为application/json; charset=utf-8
的 Http Post 发送到我的 Web 服务 url,它会得到很好的响应。
我刚刚注意到您提到的 HTTP 状态代码在您还提到的“网络”窗格中找到。 Request URL: http://cduran-virtualbox:8080/TestMavenWebApplication/firstservicecall Request Method: OPTIONS Status Code: 200 OK Remote Address: 127.0.1.1:8080 Referrer Policy: no-referrer-when-downgrade
【参考方案1】:
简单请求中 Content-Type 标头的唯一值如下:
application/x-www-form-urlencoded 多部分/表单数据 文本/纯文本尝试将“application/json”更改为其他内容类型,否则浏览器将执行预检请求。
请参阅 CORS 文档:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
【讨论】:
我刚刚从developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… 链接指令部分看到了这一点。感谢您的意见。【参考方案2】:我想我可能已经找到了问题,进一步巩固了 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 或 文本/纯文本)。这些称为简单标题,您不需要 明确指定它们。
从上面得到的关键是,只有这 3 种 Content-Types 才允许从网站到后端进行请求。
【讨论】:
【参考方案3】: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);
);
【讨论】:
感谢您抽出宝贵时间发表评论,我已经更新了我的原始帖子以显示后端 java 代码。我不得不承认,即使在 java 后端代码中有一个断点,当我执行 Submit_json jQuery Post 时它也永远不会被击中。 @CDVAProgrammer 根据这些附加信息,jquery 代码为 application/json 内容类型生成的请求似乎不正确。我已经添加了一个更新的 jQuery 代码。使用此更新后的代码后,能否请您在网络选项卡中请求请求,如果它不起作用,请分享请求的原始格式? 不幸的是,我仍然在前端收到 CORS 错误响应。我仍在调查是否缺少另一个标题字段。以上是关于尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章
Axios.get 返回纯 html 而不是 JSON 返回数据
Google Chrome 将 json AJAX 响应显示为树而不是纯文本,新版本
使用 appendchild 或其他方法向 ul 添加 html 代码而不是纯文本?