【发布时间】:2013-12-09 11:33:54
【问题描述】:
背景:
所以,我编写了以下 PHP sn-p 来帮助我调试更大的问题,但现在我更加困惑 jQuery 和 PHP 如何期望 JSON 被发送/接收,因为这段代码没有似乎正在做我期望的事情:
我希望能够以application/x-www-form-urlencoded或作为application/json接收数据,同时仅以application/json 响应(暂时)。
test.php:
<?php
$content_type = $_SERVER['CONTENT_TYPE'];
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
echo <<< _EOF
<html>
<body>
<div id="content"></div>
<script type="text/javascript" src="/jquery-1.10.2.min.js"></script>
</body>
</html>
_EOF;
break;
case 'POST':
header('Content-type: application/json');
if ($content_type == 'application/x-www-form-urlencoded') {
$_POST['message'] = 'debugged';
echo json_encode($_POST);
# Otherwise, get raw body data.
} else {
$data = file_get_contents('php://input');
if ($data == null) {
$data = file_get_contents('php://stdin');
}
$object = json_decode($data, true);
$object['message'] = 'debugged';
echo json_encode($object);
}
break;
default:
echo "These aren't the droids you're looking for. Move along.<br />";
break;
}
测试:
我一直在使用Python Requests Library 和jQuery's Ajax method 测试这段代码。
在 Python 中,数据可以作为application/x-www-form-urlencoded 或附加到请求的原始正文数据发送,具体取决于您提供给post() 方法的data 参数的类型(有关更多信息,请参阅here信息)。
到目前为止一切顺利......
使用请求,我得到了我所期望的。
当post()方法的data参数为Python字典对象时,数据以form-encoded方式发送:
>>> import requests
>>> r = requests.post('http://example.com/test.php', data={"name": "tester", "message": "bug"})
>>> print r.text
{"message": "debugged", "name": "tester"}
当data 参数是文字字符串(注意单引号!)时,数据作为请求的主体发送,并且可能(或可能不会)被解释为 JSON在端点处(我在上面的示例 PHP 代码中将其解释为 JSON,并且保证它只会是 JSON):
>>> r = requests.post('http://example.com/test.php', data='{"name": "tester", "message": "bug"}')
>>> print r.text
{"message": "debugged", "name": "tester"}
这两个结果都是我所期望的。
这是奇怪的部分......
我似乎从这段代码中得到了不同的响应,不是取决于如何我发送数据,而是我使用什么来发送它(即请求,或 jQuery)。两者之间一定有一些我完全想念的不同之处。
如果我将浏览器 (Chrome) 指向 http://example.com/test.php,触发 GET 请求处理程序为我提供上面 PHP 代码中包含的微小 HTML 页面,然后在 JavaScript 控制台中触发以下 jQuery 代码,这就是结果我回来了:
> var output = null;
> $.ajax({
type: 'POST',
url: 'http://example.com/test.php',
data: {
name: 'tester',
message: 'bug'
},
dataType: 'json',
beforeSend: function(x) {
if (x && x.overrideMimeType) {
x.overrideMimeType('application/json; charset=UTF-8');
}
},
success: function(d) {
$output = d;
}
});
> output
Object {message: "debugged"}
现在我在想,“姓名”条目到底去哪儿了?
事实证明,只有我在 PHP 处理程序中显式设置的东西似乎可以作为 jQuery 的输出访问。但有时我想使用来自用户输入的数据,对其进行修改,然后将其作为输出返回。但是使用 jQuery 像这样(或 PHP ......我不确定我的错误在哪一段代码中)我无法做我想做的事。
更奇怪!
接下来我将输出消息更改为“已调试(表单数据)”或“已调试(正文数据)”,具体取决于是否输入了 POST 处理程序中的 if 语句或“elsed” ,并且惊讶地发现 jQuery 将数据作为正文数据发送,但设置了 application/x-www-form-urlencoded 标头。 这完全不是我所期望的。由于这种差异,我觉得 jQuery (1.10.2) 或 Python Requests 中的任何一个行为不端,但我不确定是哪一个。 (或者发送表单编码的数据真的是这种临时性的吗?)
任何关于这里发生的事情、我缺少什么、如果我的期望或错误我应该期待什么、甚至是我在研究此问题时设法忽略的相关文档的链接的任何想法或见解,将不胜感激。
【问题讨论】:
-
您应该确保使用 Chrome 开发人员工具,以便查看浏览器实际发送到服务器(和从服务器接收)的原始 HTTP 标头。
-
这对于测试来说有点意思,但它发送和处理请求的方式都很奇怪,而且看起来过于复杂,我有一种奇怪的感觉,“名称”条目并不是真的消失了,但你所做的某件事让它在经过所有陌生的过程中消失了很长一段路。
-
据我所知,当你将一个对象传递给
data时,它会像表单 urlencoded 一样被编码,因为它贯穿jQuery.param。尝试使用data预编码的字符串JSON.stringify。
标签: javascript php jquery python json