缘起

  前段时间遇到扫描问题,好不容易拿到了扫描出来的数据,结果调用接口时弹了个 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. C# — 创建Windows服务

    以前从来没有接触过C#,对Windows服务也完全不了解,今天通过使用VS2017创建了一个Windows服务,并进行了安装和卸载,目前也是一知半解的地步,简单的做个笔记记录一下,也算是复习了吧. 第 ...

  2. net spider(python 网络爬虫)

    # -*- coding: utf-8 -*- import urllib2,cookielib from bs4 import BeautifulSoup url="http://www. ...

  3. [翻译] 使用 .NET Core 3.0 创建一个 Windows 服务

    原文: .NET Core Workers as Windows Services 在 .NET Core 3.0 中,我们引入了一种名为 Worker Service 的新型应用程序模板.此模板旨在 ...

  4. 今天我得鼓吹一波 Kotlin

    Kotlin 被作为 Google 官方语言也有一年多了,但除了刚宣布那个月极度火爆以外,后面生活又回归了平静.不少小伙伴紧跟 Google 爸爸的步伐,也对 Kotlin 有了或多或少的了解,Git ...

  5. MySQL 5.7中如何定位DDL被阻塞的问题

    在上篇文章<MySQL表结构变更,不可不知的Metadata Lock>中,我们介绍了MDL引入的背景,及基本概念,从“道”的层面知道了什么是MDL.下面就从“术”的层面看看如何定位MDL ...

  6. RPM包制作过程(一)

    本机环境:centos7,64位 1. 首先安装工具,rpmbuild可能在rpmdevtools里已经包含 #yum install rpm-devel.x86_64 #yum install rp ...

  7. SQL Server 跨服务器查询

    select * from OPENDATASOURCE( 'SQLOLEDB', 'Data Source=10.10.10.10;User ID=sa;Password=123456'). [CF ...

  8. 一些leetcode算法题

    DFS算法 思想:一直往深处走,直到找到解或者走不下去为止 DFS(dep,...) // dep代表目前DFS的深度 { if (找到解或者走不下去了){ return; } 枚举下种情况,DFS( ...

  9. Python-序列化模块-json-62

    序列化模块 Eva_J 什么叫序列化——将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现在我们能想到 ...

  10. 软件扒网站? 爬虫? F12查看源码? 查看网页源代码?浏览器sources? 区别和联系!

    1.软件扒网站: 利用各类扒站网站,如仿站小工具8.0,可以按照规则将网站的未经浏览器简析的前端代码扒下来,并整理成css,js,html等文件夹,很方便.(当然看不到ajax等相关代码) 备注:如果 ...