Monday, September 22, 2008

[REST] http request method

》Http request method的特性
  • safe: 不改变服务器端状态,get和head是safe的操作
  • indepment:幂等性,就是多个请求和单个请求执行的效果是一样的,get,head,put,delete都是indepment,而post,options,trace是非indepment的。
》OPTIONS
获得request/response链上的通信选项,response不能缓存。
》GET
从服务器端取回资源。
》HEAD
与GET一样,但是response不能包含message-body。一般用来检验资源有效性,是否可访问,是否被修改,这样客户端可以采取进一步的动作,比如直接采用本地cache返回到用户。
》POST
The POST method is used to request that the origin server accept the entity enclosed in the request as a new
subordinate of the resource identified by the Request-URI in the Request-Line.
如果entity对应的资源已经被创建,那么返回201(created),message-body需要说明请求状态,对新资源的引用(服务器上已经创建的资源为新资源,不是指请求中携带的entity),以及指定Location header。
如果entity对应的资源不存在,那么创建这个资源,并且返回200(OK,response中携带message-body)或者204(NO CONTENT,response中没有message-body)。
response不应该被缓存。
》PUT
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. 如果REquest-uri指向已经存在的资源,那么使用entity更新这个资源,否则创建资源。
如果entity对应的资源不存在,那么创建这个资源,并且返回200(OK,response中携带message-body)或者204(NO CONTENT,response中没有message-body)。
response不应该被缓存。
》DELETE
The DELETE method requests that the origin server delete the resource identified by the Request-URI.
request不应该包含message-body(http协议中并没有这样规定,是我使用HttpURLConnection时,设置request method为delete,setDoOutput(true)的时候包的错)。
response不应该被缓存。
》PUT vs POST
put与post最大的不同在于,post请求中的request-uri表示用来处理附带在request的entity的资源,比如一个data-accepting process,而put的request-uri就是表示附带在请求中的entity。
servlet API对他们的支持也不同,servlet APi对post提交的form-data-format(field1=value1&field2=value&...&fieldn=valuen)提供了内置的支持,使用HttpServletRequest.getParameter(fieldn)就可以得到值,而如果采用Put的请求方法,HttpServletRequest.getParameter(fieldn)只能得到null(只能使用HttpServletRequest.getReader()来获得message-body)。
* 如果是url中携带参数,那么HttpServletRequest.getParameter(fieldn)总能取得值,和request method没有关系
》TRACE
The TRACE method is used to invoke a remote, application-layer loop-back of the request message. 不太清楚。。。。
》HTTP
http协议是字符协议(http协议头必须是字符),但是http协议的消息体可以是文本字符也可以是二进制数据(当然也可以对二进制数据进行编码,比如Base64)。对于java来说,已经实现了对http协议的封装,客户端可以使用HttpURLConnection的getInputStream()和getOutputStream()来写出和读取二进制流,而在服务器端使用servlet API,request.getInputStream(), response.getOutputStream()也可以来读取和写出二进制流。
考虑背后的http协议解析过程,无论字符还是二进制最终都会以二进制方式在网路上传输,接受方会根据找到的第一个空行来区分http消息头和消息体,消息头总是字符,而消息体就取决于开发人员了....

NOTE: 详细信息可以参考rfc2616-Hypertext Transfer Protocol

》HttpUrlConnection
这个Api的确不好用,javadoc也没说清楚,很多事情是写代码实验才有结论。
  • 只有调用HttpUrlConnecton.getInputStream()或者其他从连接取回响应信息的方法,比如HttpURLConnection.getResponseCode()之类的方法之后,HttpURLConnection才会向服务器端提交数据,否则根本不会发送消息体数据。
  • DELETE请求方法不能有消息体
  • 如果向远程提交消息体数据,那么必须setDoOutput(true)。

No comments: