由 POST 400 错误拔出来的萝卜
缘起
前段时间遇到扫描问题,好不容易拿到了扫描出来的数据,结果调用接口时弹了个 400(Bad request) 给我,匆匆找了点资料修补上线后,忐忑的心也可以安分点。然后,顺着这个 400 的萝卜,拔出了一大堆的坑。
400 (Bad request)
400 错误的原因很简单,请求头部信息与请求体中的数据格式不匹配,或者 前 -> 后 的数据中字段类型不一致。在有效沟通的前提下,类型不一致的概率很小,那么这个问题就主要集中在头部信息与请求体数据格式不一致上面了。
先看一个正确的请求:
$.ajax({
url : "http://localhost:8080/xxx/xxxx",
type : "POST",
contentType: "application/json;charset=utf-8",
data : JSON.stringify({ name, passwd }), // { name, passwd } es6 的一个语法
success : function(result) {
...
},
error:function(msg){
...
}
})
目前都是前后端分离的开发模式,两端通信全靠 json,所以,在发送 post 请求时必须得约定并设置请求头 contentType: "application/json;charset=utf-8"。如果不设置的话,这个请求的 contentType 默认 application/x-www-form-urlencoded,一个 415 + 大红叉 顶给你。
接着,需要设置 data。在发送请求时,如果写成:data: { name, pwd } 的话,服务器还是会返回 400 错误。其实理由也很简单, http 通信过程中,要么就是字符串,要么就是二进制流 ,而 { name, pwd } 是一个对象,必须先转化成字符串或者流,才能传输。于是在请求中,首先得用 JSON.stringify 将 json 对象转换成字符串,这样,服务器才能正确理解请求并拿到数据。
综上,在 post 请求中,一定要对这两个属性进行设置和处理。
JSON.parse 和 JSON.stringify
这两个 api 在前端的应用频率也是相当高的,不过,因为某些原因,对 JSON.stringify 这个 api 理解上有些误差。直到最近在查资料时才有了不一样的领悟。
JSON.parse 将一个 (json) 字符串转换成 (json) 对象,它有个名字是 反序列化;
JSON.stringify 作用与 JSON.parse 相反,将对象转化成字符串,所以它也有个名字是 序列化。
序列化 (Serialization)是将对象的状态信息转换为可以 存储 或 传输 的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
尤想起,当年写 class 的时候,序列化与反序列化齐飞,直至今日才明白官方定义...溜了溜了...
POST 常见的数据提交类型 - Content-Type
application/x-www-form-urlencoded
最常见的 POST 提交数据的方式,原生 form 表单默认的提交方式,同时,如果在 ajax 中不设置的话,同样以这种方式提交。
这种方式提交的数据会转换成键值对并按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都会进行url 编码。如:
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8 name=test&val1=1&val2=%E6%B5%8B%E8%AF%95&val3%5B%5D=2
multipart/form-data
常用于多文件上传。这种方式将表单数据处理成一条消息,以标签为单元,用分隔符(常见的是 boundary)分开。因为这种方式将数据分割为多个部分,所以它既可以上传键值对,也可以上传文件、多文件。当上传的字段是文件时,会有 Content - Type 来说明文件类型;Content-disposition,用来说明字段的一些信息。每部分以 -boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(字段、文本或二进制等)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 -boundary- 标识结束。
如:(没太看明白)
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text" title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
application/json
这个头应该会很熟悉,这也是日常用的比较多的请求/响应头。这个消息头的作用是告诉服务端消息主体是序列化后的 JSON 字符串。
顺手也贴一个:
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8 {"title":"test","sub":[1,2,3]}
text/plain
这个消息类型是文件已被设置为纯文本形式,浏览器、服务器收到这种类型的数据不会进行进一步的处理,开发者需要自行判断处理。也支持发送 JSON 字符串。
这个类型意味着消息自由性变大。
text/xml 和 application/xml
这两消息类型年代久远...至少在 web 前端领域做实际项目的时候完全没有碰到过。以 xml 文档的形式发送数据。不过因为 xml 严谨结构,对 web 前端来说,这会产生更多的流量,基本被弃用。
然后这两者的区别是前者默认使用 ‘us-ascii’ 字符集编解码,后者默认 'utf-8' 字符集编解码;前者只能在消息头 content-type 中设置编解码格式才有效,后者在消息头或者在文档内部中设置均可以。
由 POST 400 错误拔出来的萝卜的更多相关文章
- 在使用 HttpWebRequest Post数据时候返回 400错误
笔者有一个项目中用到了上传zip并解压的功能.开始觉得很简单,因为之前曾经做过之类的上传文件的功能,所以并不为意,于是使用copy大法.正如你所料,如果一切很正常的能运行的话就不会有这篇笔记了. 整个 ...
- Yii框架 400 错误
YII 400错误 在YII框架中400错误是csrf校验失败的意思 csrf是什么? CSRF(Cross-site request forgery跨站请求伪造,也被称为"One Cli ...
- 解决YII提交POST表单出现400错误,以及ajax post请求时出现400问题
POST表单400错误: 正确做法: Add this in the head section of your layout: <?= Html::csrfMetaTags() ?> -- ...
- request.GetResponse 400错误处理方法
问题描述:在使用request.GetResponse时,如果是400错误,将抛出异常信息,而获取不到返回内容,所以返回的内容只能在catch上面获取,转载于 http://blog.csdn.net ...
- Yii2请求,报400错误
出现400错误是yii2.0的csrf防范策略导致 在components里面添加request配置如下: 'request' => [ // !!! insert a secret key i ...
- 访问本机的WEB API 报400错误
当时用的IP是127.0.0.1 报400错误,换成 localhost 后正常.
- SpringMVC + Spring + MyBatis 学习笔记:提交数据遭遇基础类型和日期类型报400错误解决方法
系统:WIN8.1 数据库:Oracle 11GR2 开发工具:MyEclipse 8.6 框架:Spring3.2.9.SpringMVC3.2.9.MyBatis3.2.8 使用SpringMVC ...
- http 400 错误的请求怎么解决
HTTP400是个错误的统称 你将IE选项-高级中的显示HTTP友好错误信息前面的勾去掉. 然后在开这个页,,把错误代码复制出来 .其实有时是网页本身已经不可用了,你先关掉浏览器稍等一会再登陆网页也是 ...
- http status 400,http 400,400 错误
转载:http://blog.csdn.net/xu_zh_h/article/details/2294233 4 请求失败4xx 4xx应答定义了特定服务器响应的请求失败的情况.客户端不应当在不更改 ...
随机推荐
- 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...
- Python脱产8期 Day05 2019/4/17
数据类型的使用 一 数字类型 1.整型:int 2.浮点型:float 3.重点:数字类型直接相互转化 二字符串类型 一 1.定义:在单引号/双引号/三引号中包含一系列字符. 2.注意:可以通过引号的 ...
- 《Web接口开发与自动化测试 -- 基于Python语言》---现已出版。
终于可以购买了!! 有需要的同学通过下面链接购买. 购买来链接: https://item.jd.com/11806319423.html 为什么要出这样一本书? 首先,今年我有不少工作是跟接口自动化 ...
- Linux进程管理 (篇外)内核线程简要介绍
关键词:kthread.irq.ksoftirqd.kworker.workqueues 在使用ps查看线程的时候,会有不少[...]名称的线程,这些有别于其它线程,都是内核线程. 其中多数内核线程从 ...
- Clustering[Evaluation]
0. 背景 评估(或者说验证)聚类结果就如同聚类本身一样困难.通常的方法有内部评估和外部评估这两种: 内部评估的方法:通过一个单一的量化得分来评估算法好坏:该类型的方法 外部评估的方法:通过将聚类结果 ...
- Maven学习第2期---Maven安装配置
一.Maven介绍 1.1 何为Maven Maven这个词可以翻译为"知识的积累",也可以翻译为"专家"或"内行".Maven是一个跨平台 ...
- 你知道Java的四种引用类型吗
关于java四种引用类型,我也是刚了解,特此记下! 在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用.在这四个引用类型中,只有强引用FinalReference类是包内可见,其他三种引 ...
- C# 实现实时网速
前言 最近参加了一个项目,所以写博客的时间就少了,项目中有一个功能就是在窗体上显示实时网速,用了半天的时间写了出来,想想今天时间蛮充足,就把它分享到博客上吧. 项目展示 项目核心代码: private ...
- 实现多个标签页之间通信的几种方法(sharedworker)
效果图.gif prologue 之前在网上看到一个面试题:如何实现浏览器中多个标签页之间的通信.我目前想到的方法有三种:使用websocket协议.通过localstorage.以及使用html ...
- Git更新代码到本地
一段时间没用git,发现一些东西记不住了,这里记一点常用的命令. 正规流程 git status(查看本地分支文件信息,确保更新时不产生冲突) 若出现冲突,会有提示的 git checkout – [ ...