缘起

  前段时间遇到扫描问题,好不容易拿到了扫描出来的数据,结果调用接口时弹了个 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 错误拔出来的萝卜的更多相关文章

  1. 在使用 HttpWebRequest Post数据时候返回 400错误

    笔者有一个项目中用到了上传zip并解压的功能.开始觉得很简单,因为之前曾经做过之类的上传文件的功能,所以并不为意,于是使用copy大法.正如你所料,如果一切很正常的能运行的话就不会有这篇笔记了. 整个 ...

  2. Yii框架 400 错误

    YII  400错误 在YII框架中400错误是csrf校验失败的意思 csrf是什么? CSRF(Cross-site request forgery跨站请求伪造,也被称为"One Cli ...

  3. 解决YII提交POST表单出现400错误,以及ajax post请求时出现400问题

    POST表单400错误: 正确做法: Add this in the head section of your layout: <?= Html::csrfMetaTags() ?> -- ...

  4. request.GetResponse 400错误处理方法

    问题描述:在使用request.GetResponse时,如果是400错误,将抛出异常信息,而获取不到返回内容,所以返回的内容只能在catch上面获取,转载于 http://blog.csdn.net ...

  5. Yii2请求,报400错误

    出现400错误是yii2.0的csrf防范策略导致 在components里面添加request配置如下: 'request' => [ // !!! insert a secret key i ...

  6. 访问本机的WEB API 报400错误

    当时用的IP是127.0.0.1 报400错误,换成 localhost 后正常.

  7. SpringMVC + Spring + MyBatis 学习笔记:提交数据遭遇基础类型和日期类型报400错误解决方法

    系统:WIN8.1 数据库:Oracle 11GR2 开发工具:MyEclipse 8.6 框架:Spring3.2.9.SpringMVC3.2.9.MyBatis3.2.8 使用SpringMVC ...

  8. http 400 错误的请求怎么解决

    HTTP400是个错误的统称 你将IE选项-高级中的显示HTTP友好错误信息前面的勾去掉. 然后在开这个页,,把错误代码复制出来 .其实有时是网页本身已经不可用了,你先关掉浏览器稍等一会再登陆网页也是 ...

  9. http status 400,http 400,400 错误

    转载:http://blog.csdn.net/xu_zh_h/article/details/2294233 4 请求失败4xx 4xx应答定义了特定服务器响应的请求失败的情况.客户端不应当在不更改 ...

随机推荐

  1. 使用BBED跳过归档进行恢复

    https: 使用BBED跳过归档进行恢复 数据库启动异常,提示6号文件丢失 SQL> startup ORACLE instance started. Total System Global ...

  2. mybatis 中 foreach collection的三种用法(转)

    文章转自 https://blog.csdn.net/qq_24084925/article/details/53790287 oreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集 ...

  3. anaconda新建虚拟环境安装各个依赖包

    深度学习的代码,好多都需要安装一些安装包,在服务器上安装需要权限就很麻烦.看到网上有说把这些安装包一个个下载下来上传到服务器再安装,心累,想想工程量就很大~~~ 这时候就可以在anaconda中新建虚 ...

  4. 编写Linux C++程序如何影响VIRT(虚存)和RES(实存/常驻内存)

    转载目的,主要是为了理解lVIRT虚拟内存.RES常驻内存.共享内存SHR.SWAP和实际程序应用如何对应的. 在Linux命令行中执行top命令,可以查询到所有进程使用的VIRT虚拟内存.RES常驻 ...

  5. Sql Server利用游标批量清空数据表

    先吐槽一下,由于公司要为新客户部署一个全新的系统,然而公司并没有空库,所以只能把正在线上运行的数据库给备份,然后清空相关数据 下面分享一下我在做清空数据库时写的一个批量清空数据表的方法 思路:查询出该 ...

  6. Tomcat完美配置多个HOST主机,域名,SSL

    这里是Tomcat9版本,其它版本基本一致! 1.配置多个主机域名 1.打开conf文件夹下的server.xml 复制官方提供的HOST配置,修改为你的域名,appBase路径(相对路径) 2.新建 ...

  7. 从CompletableFuture到异步编程设计

    从CompletableFuture到异步编程设计,笔者就分为2部分来分享CompletableFuture异步编程设计,前半部分总结下CompletableFuture使用实践,后半部分分享下Com ...

  8. 作为一个.NET开发者,怎么看待和选择层出不穷的新技术,新架构?

    经常在一些技术社区看到这些的问题,一个.NET开发者去求职,看到应聘的公司的技术栈还是比较老的ASP.NET WEBFORM的时候,希望了解未来会否使用ASP.NET MVC的时候,没有获得肯定答复, ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(92)-打印EasyUI 的datagrid表格

    前言 应用系统有时候需要打印Datagrid的表格内容,我们本节就来学习打印datagrid内容 打印主要使用:web打印(我们之前有讲过web打印插件jqprint) + 将datagrid重新编制 ...

  10. Python—生成器

    列表生成式 现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现? >>> a = [i+1 for i in r ...