JAVA技术交流QQ群:170933152

-------------------------

RESTful架构有一些典型的设计误区。

最常见的一种设计错误,就是URI包含动词。因为"资源"表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中。

举例来说,某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示show。

如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:

  POST /accounts/1/transfer/500/to/2

正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:

  POST /transaction HTTP/1.1
  Host: 127.0.0.1
  
  from=1&to=2&amount=500.00

另一个设计误区,就是在URI中加入版本号

  http://www.example.com/app/1.0/foo

  http://www.example.com/app/1.1/foo

  http://www.example.com/app/2.0/foo

因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分(参见Versioning REST Services):

  Accept: vnd.example-com.foo+json; version=1.0

  Accept: vnd.example-com.foo+json; version=1.1

  Accept: vnd.example-com.foo+json; version=2.0

-------------------------

懒人直接看 200、400、401、403、404、500 就可以了。

其中 2XX/3XX 其实都是请求成功,但是结果不同。4XX 是请求出错,5XX 是服务器处理出现错误。

200 这个最容易理解,就是正确的请求返回正确的结果,如果不想细分正确的请求结果都可以直接返回200。

201 表示资源被正确的创建。比如说,我们 POST 用户名、密码正确创建了一个用户就可以返回 201。

202 请求是正确的,但是结果正在处理中,没法返回对应的结果。比如说,我们请求一个需要大量计算的结果,但是并没有计算结束时,可以返回这个,这时候客户端可以通过轮询等机制继续请求。

203 请求的代理服务器修改了源服务器返回的 200 中的内容,一般用不到。比如说,我们通过代理服务器向服务器 A 请求用户信息,服务器 A 正常响应,但代理服务器命中了缓存并返回了自己的缓存内容,这时候它返回 203 告诉我们这部分信息不一定是最新的,我们可以自行判断并处理。

204 请求正确,但是没有需要返回的内容。比如说,我们请求删除某个用户,删除成功可以返回 204。

205 类似 204,但是要求请求者重置视图,一般也用不到。比如说,我们请求删除某个用户,服务器返回 205 的话,我们就刷新现在的用户列表。

206 请求成功,但根据请求头只返回了部分内容。比如说,我们下载一部片,共有 10 部分,我们把请求也分成了 10 次(防止一次请求过大),这时候服务器就可以返回 206 并在其头部告诉我们这是哪一部分,然后再根据这个信息进行拼装。

300 请求成功,但结果有多种选择。比如说,我们下载一部片,服务器有 avi、mp4 等格式,这时候可以返回 300,并在 body 里告知有哪些格式,然后用户可以根据这些格式再次请求。

301 请求成功,但是资源被永久转移。比如说,我们要下载葫芦娃,但是由于旧的存储服务商涨价了,现在要使用新的存储服务了,要去新地址下载,这时候可以返回 301,并在 header 的 Location 中告知新的地址,以后也应当到这个地址下载。

302 请求成功,但是资源被临时转移了。和 301 不同的是,除非是 HEAD 请求,否则新地址的信息应当在 body 中返回,并且资源只是临时转移,以后不应当通过新地址来下载。

303 类似 302,但要求使用 GET 来访问新的地址来获取资源。

304 请求的资源并没有被修改过。比如说,我们发送请求想看看 5.20 后的情侣信息,服务器查询没有新的情侣信息产生,这时候可以返回 304,然后客户端可以继续用旧的数据。

305 请求的资源必须通过代理访问。比如说,我们想请求服务器 A 上新的 iPhone 的信息,但是需要通过代理服务器才能访问,如果直接请求了服务器 A,没有经过代理服务器,这时候服务器 A 就可以返回 305 从而告诉我们应当访问代理服务器。 306 不用了。

307 类似 302,但要求使用原有的请求方式来通过新地址获取资源。

308 类似 301,但要求使用原有的请求方式来通过新地址获取资源。

400 请求出现错误,比如请求头不对等,所有不想明确区分的客户端请求出错都可以返回 400。

401 没有提供认证信息。比如说,请求的时候没有带上 Token 等。

402 为将来的需要所保留的状态码。

403 请求的资源不允许访问。比如说,你使用普通用户的 Token 去请求管理员才能访问的资源。

404 请求的内容不存在。

405 请求的方法不允许使用。比如说,服务器只实现了 PATCH 了局部更新资源,并没有实现 PUT 来替换资源,而我们使用了 PUT,这时候服务器可以返回 405 来告知并没有实现对 PUT 的相关处理。

406 请求的资源并不符合要求。比如说,我们 header 里请求 JSON 格式的数据,但是服务器只有 XML 格式的数据,这时候可以返回 406 告知。

407 类似 401,但是要求必须去同代理服务器进行认证。

408 客户端请求超时。我们想 POST 创建一个用户,虽然建立了连接,但是网络不好,服务器在规定时间内没有得到我们的请求信息,这时候服务器可以返回 408 告诉我们超时了。然后我们可以重新发送请求。

409 请求冲突。比如说,服务器要求不同用户不能重名,服务器已经有了一个名叫小伟的用户,这时候我们又想创建一个名叫小伟的用户,服务器可以返回 409,告诉我们冲突了,也可以在 body 中明确告知是什么冲突了。

410 请求资源曾经存在,但现在不存在了。比如说,我们下载葫芦娃,但是因为版权被删了,下载不了了,这时候服务器返回 410,告诉我们洗洗早点睡。

411 没有提供请求资源的长度。比如说,我们下载葫芦娃,服务器只允许我们分部分下载,我们如果不告诉服务器我们要下载哪部分,服务器就返回 411 警告我们。

412 请求的资源不符合请求头中的 IF-* 的某些条件。比如说,我们下载葫芦娃,然后在请求头告知服务器要 5.20 后更新过的,服务器没有,于是返回了 412。

413 请求体过大。比如说,服务器要求上传文件不能超过 5M,但是我们 POST 了 10M,这时候就返回 413。

414 请求的 URI 太长了。比如说,我们提供了太多的 Query 参数,以至于超过了服务器的限制,这时候可以返回 414。

415 不支持的媒体类型。比如说,我们上传了一张七娃的 GIF 动图,而服务器只允许你上传 PNG 图片,这时候就返回 415。 416 请求的区间无效。比如说,我们分部分下载时请求葫芦娃的 10 分钟到 12 分钟的内容,但是这部葫芦娃只有 1 分钟的内容,这时候就返回 416。

417 预期错误。指服务器没法满足我们在请求头里的 Expect 相关的信息。

418 我是个茶壶。这是一个愚人节的玩笑,这个状态码就是用来搞笑的。

500 服务器错误。没法明确定义的服务器错误都可以返回这个。

501 请求还没有被实现。比如说,我们请求一个接口来自动拒绝项目经理的要求,但是这个接口只是美好的想象,并没有被实现,这时候可以返回 501。

502 网关错误。比如说,我们向服务器 A 请求下载葫芦娃,但是 A 其实只是一个代理服务器,他得向 B 请求葫芦娃,但是不知道为啥 B 不理他或者给他错误,这时候哦可以 A 返回 502 用来表示 B 这家伙傲娇了。

503 服务暂时不可用。比如说,服务器正好在更新代码重启。

504 类似 502,但是这时候是 B 不理 A,超时了 。

505 请求的 HTTP 版本不支持。比如说,现在强行根据 HTTP 1000 来请求。

-------------------------------------------------

HTTP无状态协议(超文本传输协议,属于文本协议)HTTP无状态协议是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。HTTP请求头和相应头参考:http://tools.jb51.net/table/http_header相应头和请求头对照(部分)Request
Response
Accept:浏览器能够处理的内容类型
Accept-Ranges:表明服务器是否支持指定范围请求及哪种类型的分段请求
Accept-Charset:浏览器能够显示的字符集
Accept-Encoding:浏览器能够处理的压缩编码
Accept-Language:浏览器当前设置的语言
Connection:浏览器与服务器连接类型,表示是否要持续连接Cookie:把保存在该请求域名的所有cookies发送给服务器
Set-Cookie:设置HTTP cookie
Host:指定请求服务器的域名或端口号
Server:服务器软件名称
Referer:先前请求的网页User-Agent:用户代理
Vary:告诉下游代理是使用缓存响应还是从原始服务器请求Location:重定向到新的资源Refresh:应用于重定向或一个新的资源被创造
Date:请求发送的时间
Date:原始服务器发出消息的时间Expires:相应过期的时间Age:从原始服务器到代理缓存形成的估算时间(以秒计,非负)
Cache-Control:指定请求和相应遵循哪种缓存机制。
Cache-Control:告诉所有的缓存机制是否可以缓存以及用哪种方式缓存RESTful(英文:Representational State Transfer,简称REST表现层状态转换)一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。HTTP状态码HTTP状态码分类
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错
HTTP状态码列表
100 Continue    继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK  请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted    已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information   非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content  无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content   重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices    多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently   永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found   临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other   查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified    未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy   使用代理。所请求的资源必须通过代理访问
306 Unused  已经被废弃的HTTP状态码
307 Temporary Redirect  临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized    请求要求用户的身份认证
402 Payment Required    保留,将来使用
403 Forbidden   服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found   服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed  客户端请求中的方法被禁止
406 Not Acceptable  服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required   请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out    服务器等待客户端发送的请求时间过长,超时
409 Conflict    服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
410 Gone    客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large    由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large   请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type  服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed  服务器无法满足Expect的请求头信息
500 Internal Server Error   服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out    充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported  服务器不支持请求的HTTP协议的版本,无法完成处理---------------------本文来自 晞晞 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/leledexixi/article/details/59109160?utm_source=copy 

-

-----------------------------------------------

http://www.ruanyifeng.com/blog/2011/09/restful 阮一峰认为,版本号应该放在 HTTP 请求头中

https://juejin.im/post/59826a4e518825359c5e72d1 这个认为,API 版本号应该区分

而且 github API,也是 URI 中带有版本号的,难道说 github 的 API 设计的不好?

所以我怀疑 阮一峰这个问题上搞错了。

能分享一些实际的设计 API 的经验吗?谢谢

---------------------------

REST URI设计:版本号放在http header中,rewrite配置

REST API新版本上线后,旧版本要继续在线,所以要做多版本并行。

服务器代码目录

api.example.com/

0.1/

controller

model

htdocs/index.php

0.2/

controller

model

htdocs/index.php

之前做的URI是这样的:

curl http://api.example.com/0.2/users/1

web server需要做rewrite,把各个版本的请求路由到 {v}/www/index.php。

版本号的格式为:11.11.11,即([0-9]+\.)+[0-9]+

这时候apache这么配:

    DocumentRoot "/api.example.com/"ServerName api.example.comRewriteEngine OnRewriteRule ^/(([0-9]+\.)+[0-9]+)/ /$1/www/index.php

更多的了解REST以后,觉得把版本号、access_token放在header中更符合资源的概念。

参考:http://www.ruanyifeng.com/blog/2011/09/restful.html

URI改成这样:

curl -H 'Accept:application/json; version=0.2' http://api.example.com/users/1

这个时候需要web server从header中解析到版本号,然后路由。

这个时候apache这么配:

    DocumentRoot "/api.example.com/"ServerName api.example.comRewriteEngine OnRewriteCond  %{HTTP_ACCEPT}  version=(([0-9]+\.)+[0-9]+) RewriteRule ^(.+)$ - [env=v:%1]RewriteCond  %{HTTP_ACCEPT}  version=(([0-9]+\.)+[0-9]+)RewriteRule  .*   /%{ENV:v}/htdocs/index.php#RewriteLogLevel 9#RewriteLog logs/api.example.com-rewrite_log

在网上查了半天,才试出来apache rewrite从header中取变量。

nginx 这么配:

server {listen       8080;server_name  api.example.com;root html/api;#access_log   logs/api.example.com/access.log combined buffer=32k;access_log   logs/api.example.com/trunk/access.log combined;error_log    logs/api.example.com/trunk/error.log;location = /robots.txt {expires 1d;}location = /favicon.ico {expires 1d;}location / {rewrite ^/$ /docs.php last;set $api_version "enabled";if ($uri ~ "((([0-9]+\.)+[0-9]+)|trunk)/docs/.*") {set $api_version $1;rewrite ^/((([0-9]+\.)+[0-9]+)|trunk)/docs/$ /$api_version/htdocs/docs/index.html break;rewrite ^/((([0-9]+\.)+[0-9]+)|trunk)/docs/(.*)$ /$api_version/htdocs/docs/$4 break;}if ($http_accept ~ "application/json; version=((([0-9]+\.)+[0-9]+)|trunk)") {set $api_version $1;}rewrite .* /$api_version/htdocs/index.php last;}location ~ \.php$ {fastcgi_pass   unix:/home/lnmp/php/var/run/php-fpm.sock;fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;include        fastcgi_params;}error_page  404              /404.html;location = /404.html {root   html;}error_page  500 502 503 504  /50x.html;location = /50x.html {root   html;}
}

注意:nginx if中的rewrite不能直接使用$1,而要先set。

参考资料:

how to use a variable inside a nginx “if” regular expression

http://stackoverflow.com/questions/5859848/how-to-use-a-variable-inside-a-nginx-if-regular-expression

apache [env=ps:http] %{ENV:ps}

http://www.askapache.com/htaccess/http-https-rewriterule-redirect.html

apache rewrite 变量 %{}

http://httpd.apache.org/docs/current/mod/mod_rewrite.html#RewriteCond

apache rewrite %N $N

http://httpd.apache.org/docs/current/mod/mod_rewrite.html#RewriteRule

apache [E=VAR:VAL] [env

http://httpd.apache.org/docs/2.2/rewrite/flags.html#flag_e

截图:

SpringCloud工作笔记048---RESTful API 中 HTTP 状态码的定义_以及把RESTFul版本号_放到http协议header中_以及RestFul设计时的两个误区相关推荐

  1. Spring Security OAuth2.0_实现分布式认证授权_转发明文token给微服务_Spring Security OAuth2.0认证授权---springcloud工作笔记153

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 然后关键来了,我们通过网关微服务来转发明文数据给微服务. 我们通过zuul配置前置过滤器,在前置过 ...

  2. 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍

    使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支付宝支付(暂不支持微信支付),支持手机短信验证码注册, ...

  3. API的HTTP状态码设计

    一.现状: 前天与后端开发人员讨论了API接口的设计.有以下三种方案: 1.原始HTTTP协议 HTTP状态码就是该Request的状态码,不应该与后端业务混在一起(这也是一部分人使用该方案的理由). ...

  4. aria2百度网盘 http返回头无效_接口测试第10期:Fiddler中查看HTTP请求中的状态码...

    关注后回复[软件测试]查看更多上期介绍了常见的HTTP请求方法,get请求.post请求,今天介绍HTTP请求中的状态码,以后也能分辨出哪些状态码是表示客户端错误,哪些是服务器错误.状态码在Fiddl ...

  5. linux查询日志中页面返回状态码,[linux shell] Shell脚本实现apache日志中的状态码分析...

    这篇文章主要介绍了Shell脚本实现apache日志中的状态码分析,本文先是介绍了按天切割日志的方法,然后给出了分析访问状态码的脚本,需要的朋友可以参考下 一.首先将apache日志按天切割 复制代码 ...

  6. 【总结】HTTP协议中的状态码(200、403、404、500等)

    [总结]HTTP协议中的状态码(200.403.404.500等) 当我们打开网页或刷新网页或点击超链接等操作时,服务器都会给出相应的响应 返回的状态也有很多种 现在大多都是遵循HTTP协议的,在HT ...

  7. SpringCloud工作笔记065---lombok的使用和原理_在开发工具STS_eclipse_Idea中集成lombok

    JAVA技术交流QQ群:170933152 简单说就是在类中不用再写:get set方法,hashcode toStirng equals方法了 eclipse中集成: update时,勾选上Forc ...

  8. springcloud工作笔记107---Springboot中MyBatis 自动转换 map-underscore-to-camel-case=true 开启驼峰命名映射

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 注意只有开启了这个配置,mybatis才会自动映射,但是即使开启了,也需要注意, 该配置的也要配置 ...

  9. SpringCloud工作笔记080---了解一下CXF

    拿来的,做为对CXF的了解 技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 APACHE CXF 入门详解 以前没有接触过CXF,项目需要学习,从 ...

最新文章

  1. python 函数性能分析
  2. hive ALLOW_UNQUOTED_CONTROL_CHARS
  3. border-radius圆角兼容方案
  4. GUN ARM汇编中标号的引用在汇编和C语言中区别(monitor_flash_len = _bss_start - _armboot_start;)
  5. TStrings和TStringLists类(经典有时间整理做个小例子)
  6. mysql转储表_Mysql导出表结构及表数据 mysqldump用法
  7. 如何在Word里打出带圈的数字?
  8. 产品读书《大败局 I》 《大败局II》
  9. andr实现微信小程序抓包
  10. html视频文件哪种格式好,常见的视频格式有哪些?
  11. java分布式文件存储服务实战
  12. mime类型总结 input_type=file限制
  13. LANP+KEEPALIVED集群(一)
  14. java实现HTTPS单向认证TLS指定加密套件(文章很详细,好文章!)
  15. pytorch 常用目标检测评价指标总结
  16. 安卓手机安装php服务器地址,利用Android手机搭建小型Web服务器
  17. 【“笨办法”学Python】42.对象、类及从属关系——类即是对象
  18. kali CeWL密码攻击工具 Linux字典生成工具 自定义单词列表生成器
  19. SQL语句执行顺序及建议
  20. 网易免费域名邮箱设置foxmail客户端登录

热门文章

  1. 多线程join方法解析
  2. 毕设日志2019.4.2——tf版本的faster rcnn的代码运行
  3. Python 实现进程间通信(网络编程)
  4. Promise 源码:静态方法
  5. 自定义可扩展叠加头部的下拉控件
  6. PowerDesigner逆向工程导入MYSQL数据库总结
  7. gfirefly 框架分析
  8. ORACLE数据库事务隔离级别
  9. A Filter of Java URL Encoding: GetQueryStringEn...
  10. 使用perl连接oracle数据库