1 问题描述
欲使用Python的requests库(requests.session().request(...)
)实现对此Ajax的POST请求进行模拟实现。
但在chrome发现其请求的形式不一样,是以前从未注意到的————Request Payoad
形式,请求的参数也有一些诡异————并非 json 或者 key=value 这类标准的键-值型请求数据,而是 纯文本(`[11626301]`)。
发现其Ajax在POST数据时,使用的数据格式是request payload
,有别于之前常见的 POST数据格式(Form data
)。而使用Form data数据的提交方式时,无法提交成功。
![](https://img2020.cnblogs.com/blog/1173617/202105/1173617-20210510005836477-525156141.png)
![](https://img2020.cnblogs.com/blog/1173617/202105/1173617-20210510010302073-1331421694.png)
2 问题分析
2.1 request payloa VS form data
HTTP请求中的form data和request payload的区别
AJAX Post请求中常用的2种传参数的形式:form data 和 request payload
2.1.1 for-data
【get
请求】时,则:表单参数(请求数据集)直接可反映在url中,形式为key1=value1&key2=value2形式,比如:
http://news.baidu.com/ns?word=NBA&tn=news&from=news&cl=2&rn=20&ct=1
【post
请求】时,则:表单参数(请求数据集)是在请求体body中,也是以key1=value1&key2=value2的形式在请求体中。
通过chrome的开发者工具可以看到如下:
RequestURL:http://127.0.0.1:8080/test/test.do
Request Method:POST
Status Code:200 OK
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:25
Content-Type:application/x-www-form-urlencoded
Cookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8D
Host:127.0.0.1:8080
Origin:http://127.0.0.1:8080
Referer:http://127.0.0.1:8080/test/index.jsp
User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36
Form Data
name:mikan
address:street
Response Headers
Content-Length:2
Date:Sun, 11 May 2014 11:05:33 GMT
Server:Apache-Coyote/1.1
这里要注意post请求的Content-Type为application/x-www-form-urlencoded(默认的),参数是在请求体中,即上面请求中的Form Data。
[前端]:
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("name=foo&value=bar");
在servlet中,可以通过request.getParameter(name)的形式来获取表单参数。
/**
* 获取httpRequest的参数
*
* @param request
* @param name
* @return
*/
protected String getParameterValue(HttpServletRequest request, String name) {
return StringUtils.trimToEmpty(request.getParameter(name));
}
2.1.2 Request payload
如果使用原生AJAX POST请求的话,那么请求在chrome的开发者工具的表现如下,主要是参数在
Remote Address:192.168.234.240:80
Request URL:http://tuanbeta3.XXX.com/qimage/upload.htm
Request Method:POST
Status Code:200 OK
Request Headers
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
Connection:keep-alive
Content-Length:151
Content-Type:application/json;charset=UTF-8
Cookie:JSESSIONID=E08388788943A651924CA0A10C7ACAD0
Host:tuanbeta3.XXX.com
Origin:http://tuanbeta3.XXX.com
Referer:http://tuanbeta3.XXX.com/qimage/customerlist.htm?menu=19
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
[{widthEncode:NNNcaXN, heightEncode:NNNN5NN, displayUrl:201409/03/66I5P266rtT86oKq6,…}]
Response Headers
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/json;charset=UTF-8
Date:Thu, 04 Sep 2014 06:49:44 GMT
Server:nginx/1.4.7
Transfer-Encoding:chunked
Vary:Accept-Encoding
【注意】:请求的Content-Type
为application/json;charset=UTF-8
,而请求表单参数在Request Payload
中。
后端获取(这里使用org.apache.commons.io.):
/**
* 从 request 获取 payload 数据
*
* @param request
* @return
* @throws IOException
*/
private String getRequestPayload(HttpServletRequest request) throws IOException {
return IOUtils.toString(request.getReader());
}
2.1.3 二者区别
结论:
Form data
的Content-Type是application/x-www-form-urlencoded
(默认)Request payload
的Content-Type是application/json;charset=UTF-8
,或不指定Content-Type
if a request (typically POST) has Content-type header set to application/x-www-form-urlencoded the body is expected to be in the form of a standard querystring with url-encoded key=value pairs joined by &.
Form data section then shows the key-value parameters (when viewed parsed).
This way was much more common in past because it is a default for HTML forms.
other cases are shown in Request payload section (and nowadays parsed for readability as well for common formats like JSON).
如果一个请求(通常是POST)的Content-type
头被设置为application/x-www-form-urlencoded
,那么请求体应该是一个标准的查询字符串,带有url编码的key=value对,由&连接。
然后,表单数据部分显示键-值参数(当被查看时)。
这种方式在过去很常见,因为它是HTML表单的默认格式。
其他情况:
- 如使用原生AJAX的POST请求,如果不指定请求头
Request Header
,默认使用的Content-Type是text/plain;charset=UTF-8
,参数出现在Request payload块。 - (现在为了可读性,也为常见格式如,
JSON解析
,其对应的Content-Type
是application/json; charset=UTF-8
)
3 解决方法
import requests;
session = requests.session();
response = session.request(method="POST", url="https://www.cnblogs.com/johnnyzen/ajax/GetPostStat", json = [ "11626301" ], headers={"content-type":"application/json; charset=UTF-8"});
print(response.status_code)
print("result:" + str(response.content))
![](https://img2020.cnblogs.com/blog/1173617/202105/1173617-20210510010545029-852284923.png)