RESTful与伪RESTful

REST

关于RESTful,前几年就开始火了,其崛起是跟各大互联网开放平台的OPENAPI息息相关的,twitter的API就是声称完全RESTful的,不过其实呢,还是有些是伪RESTful的。那么,什么是RESTful呢?

REST很早(2000年)就有个博士( Roy Fielding,HTTP规范的主要编写者之一)提出来了,英文全称是REpresentational State Transfer,直译过来就是表述性状态转移,看起来更像物理学概念有木有?其核心理念就是把提供服务的所有事物定义一个ID,而这个ID在HTTP服务中通常是一个URI,然后使用标准的HTTP方法(HTTP Method,比如GET, POST, PUT, DELETE, HEAD,TRACE等)来提供同一个资源的不同服务(通常就是CRUD)。至于无状态这一点,HTTP都是无状态了,实际上也可以不用去深究。

那么,RESTful究竟是怎样一种风格呢?看几个例子:

http://www.zhihu.com/people/jiacheo

http://weibo.com/1790181393/AxqXitFF6

http://weibo.com/1790181393

看出来了没有,这里的URI都是 资源URI+资源ID组成的,也就是说,我们要访问一个资源的某种服务的时候,可以直接附上ID,就能获取了,如果要修改资源呢?HTTP方法中有POST, PUT, DELETE等可以对应用来新增/修改/删除资源的操作,但是现实中,我们大多数人用的浏览器都仅支持GET和POST两个方法,所以这个时候RESTful的理念在WEB站点中就无法完美实现了。上面说到,RESTful火起来那段时间刚好是各大开放平台开始崛起的时间,因为他们的OPENAPI大多数是RESTful风格的,由于提供API比展示页面要简单很多,仅提供CRUD操作就可以实现了,这么一来,HTTP METHOD就足够用了,而且各种编程语言提供的httpclient基本也都支持这几个方法,所以RESTful能在OPENAPI中大行其道跟API的简洁性是分不开的。

不能简单的认为没有后缀名的URI就是RESTful的,也不能认为有后缀名的URI就不是RESTful的,RESTful风格不在于你有没有后缀名(RESTful的API接口中,后缀名通常是为了实现区分返回的数据格式,如xml/json等),而是在于你的URI定义是不是对应到一个资源(这里通常是个名词),而不是一个操作(通常是动词)。由于浏览器不支持更多的HTTP方法,所以伪RESTful诞生了。

怎样的URI是伪RESTful呢?比如说这个:

http://www.zhihu.com/people/edit

这个是以动词结尾的URI,定位到的不是一个资源,而是一个动作(编辑),这个页面主要是用于编辑个人资料的时候使用的,如果要RESTful化,该怎么设计呢?

http://www.zhihu.com/people?to=edit

谁说RESTful不能有URL参数的?没有参数你如何实现复杂的查询(query)?

上面说到twitter的api中也有伪RESTful的,咱们来瞧瞧:

http://api.twitter.com/users/show.format

这里的URI是定位到show这个动作,然后传入的参数是用户的ID, 实际上, 如果遵循RESTful风格的话,可以这么搞

http://api.twitter.com/users/id.format 或者 http://api.twitter.com/users.format?id=

伪RESTful也是有存在的价值的,由于浏览器的原因,仅通过HTTP方法无法支持所有的资源的操作,那么何不把对资源的操作也定义一个URI呢?这样一来,伪RESTful其实对网站的开发者更友好,因为他一看这个URI就能知道对应后台的controller(MVC中的C)中的哪一个处理器,在写代码,调试的时候也有优势,不用去看POST的参数中对应的action(动作)究竟是谁,直接就知道了。

那么RESTful与伪RESTful孰优孰劣呢?其实没有什么定论,适合就好,管他是不是RESTful呢(你是处女座?当我没说)!但是当你在对外宣称你提供的API是标准的RESTful风格的时候,就要好好审视一下自己的API是不是标准的RESTful风格了。

国内的网站RESTful风格的也有,比如新浪微博,他的访问页面基本上都是标准的RESTful风格的(修改数据的URL我没研究,不能下定论)所以关于RESTful与伪RESTful,你是怎么看的呢?

apache & tomcat https配置

出于安全的考虑,一是确实能带来一点安全性提升,二是让用户看起来安全,一些网站开始要使用https协议来提供服务(web,api),刚好我们新产品是面向企业级的用户,需要提供https服务和接口,所以就遇到了配置问题。

首先这篇文章是在你申请好了https(ssl)证书之后该干的事。本文介绍是linux系统下的apache2的https配置,windows下的基本相同,就是一些文件的路径写法不一样还有模块的安装不一样。

使用apache2的话,他自己内建了(build-in)mod_ssl 模块,不需要额外编译和安装,如果你用的apache1.*系列的,可以使用 sudo yum install mod_ssl 来给apache安装mod_ssl

如果是内建的mod_ssl, 不需要再httpd.conf里面配置LoadModule,默认是可以直接用的,如果是自己安装的,则需要LoadModule一下。下面讲具体配置

1. 首先你申请到https证书后,服务提供商会给你如下几个文件。

server.crt

server.key

ca.pem

sub.class1.server.ca.pem

说明一下, server.crt 是服务提供商颁发给你的证书,是一个纯文本文件,一般以

-----BEGIN CERTIFICATE-----

开头,以

-----END CERTIFICATE-----

结尾,前后都没有多余的空格。

server.key就是这个证书的私钥文件,用来解密用的,也是一个纯文本文件,以

-----BEGIN RSA PRIVATE KEY-----

开头,以

-----END RSA PRIVATE KEY-----

结尾,首位也都不带空格。

另外两个*.pem文件,是CA证书,其中ca.pem是root证书,sub.class1.server.ca.pem 则是颁发证书的网站给你的的这个https的证书的服务商证书,也就是说你要认证你的https(ssl)证书必须先通过这个sub.class1.server.ca.pem再通过ca.pem来完成整个链路的验证.

2. 接下来就是apache配置证书文件的路径了

先把上述文件都统一放到一个目录,要注意保障文件的安全,不要被盗用或者删除。这里我们放在 /var/www/ssl 目录下面

打开httpd-ssl.conf文件(一般在%apache安装目录%/conf/extra下面

首先配置证书文件:

SSLCertificateFile "/var/www/ssl/server.crt"
找到相应的项,有的话就覆盖,没有的话就新建一个,指定证书文件的位置
接下来是配置证书私钥文件:
SSLCertificateKeyFile "/var/www/ssl/server.key"
配置方法同上
最后配置证书链路文件路径
上面说到,我们证书要先通过sub....pem然后在通过root认证,所以需要把这两个文件合并。
cat  sub.class1.server.ca.pem  ca.pem  > ca.chain.pem.crt
然后定位到这个ca.chain.pem文件
SSLCertificateChainFile "/www/var/ssl/ca.chain.pem.crt"
至此,整个证书的配置就OK了,可以重启下apache,访问以下你的https://域名/ 就能看到已经生效。
3. 配置完证书后,配置一下apache请求转发给tomcat,有多种方式,可以用mod_jk,也可以用ProxyPass,我这里用ProxyPass。
还是编辑同一个文件httpd-ssl.conf
在<VirtualHost _default_:443>定义块的里面,添加ProxyPass

ProxyPass / ajp://localhost:7204/
ProxyPassReverse / ajp://localhost:7204/

我这里是把请求转发给ajp去处理,tomcat默认都会有ajp的端口,因为我应用比较多,为了区分开了,所以我自己使用了7204端口,如果默认的话,应该是8009端口,是在不清楚可以看下tomcat的配置(%tomcat安装目录%/conf/server.xml内的Connector protocol="AJP/1.3" 这个配置项)
如果我这里使用ProxyPass / http://localhost:8080/ 可不可以,答案是可以的,但是你的tomcat在处理request的时候,无法分辨用户访问的url是不是https的(当然apache可以配置保留用户的原始请求url给tomcat)
4. 大部分的https的ssl证书是颁布给某个子域名的,如果你的所有子域名都需要上https,建议使用购买一个可以多次使用的。对了,一开始可以申请startssl来用一下,可以免费使用30天,测试完了,可以再买高端的。
运行起来了,但遇到如下情况,该怎么办
nosecure
不要慌, 这时候你的https已经生效了,唯一的问题是你的页面请求的资源使用了其他非https的资源,比如cdn的图片,css等的引用,如果是js资源,建议都要使用https,不然浏览器会认为很不安全的哦。

通过apache proxy访问tomcat ERR_CONNECTION_RESET 问题排查

0. 这是个钓鱼贴你造么,看到后面你就造了。

1. 现象, 通过浏览器访问 www.qipeng.com 返回页面链接被重置

查看apache-access 日志, 是有发起请求的, 说明在proxy那里存在问题

2. ping www.qipeng.com 结果是DNS已经生效的
1
3. 改用mod_jk, 而不是proxy来处理请求转发, 发现服务器身上是可以curl通的
2
注意这台curl的机器不是企朋的服务器本身, 而是在服务器上随便找的
4. 然后用本地访问依旧是
3
5. 怀疑是DNS问题, 于是本地配置了hosts, 把www.qipeng.com 强制指向 223.4.49.236
结果还是一样, 本地配置别的域名 weike.taovip.com 指向 223.4.49.236, 访问这个域名, 结果是正确的, 我嚓, 这个正是我的企朋的页面!
4
6. 那么到底他妈的问题出在哪里呢,难道我被我自己墙了?找其他同事, 结果也是一样的- -||
找了半天, 突然想起老大好像昨天刚申请域名备案, 于是开始往这方面靠, 结果真正的原因是域名正在备案中, 期间访问不了, 呵呵! 天朝, 我又涨姿势了!
7. 解决方案
7.1 其实不需要解决, 产品也是刚做, 还没啥用户, 自己本地配置个其他域名先顶一阵等备案好了就OK了.
7.2 真的必须要访问的话可以找个国外的服务器, 先跑一跑, 前提是你的程序没有太多其他的依赖, 否则得不偿失.
7.3 知乎某知友的对策: http://www.zhihu.com/question/19794926