简单地讲,HTTP web 服务是指以编程的方式直接使用 http 操作从远程服务器发送和接收数据。

  • 如果你要从服务器获取数据,使用http GET;
  • 如果你要向服务器发送新数据,使用http POST.

一些更高级的http Web 服务 API 也允许使用 http PUT 和 http DELETE 来创建、修改和删除数据。 换句话说,http 协议中的“verbs (动作)” (GET, POST, PUT 和 DELETE) 可以直接对应到应用层的操作:获取,创建,修改,删除数据。

这个方法主要的优点是简单, 它的简单证明是受欢迎的。数据 — 通常是xml或json — 可以事先创建好并静态的存储下来 ,或者由服务器端脚本动态生成, 并且所有主要的编程语言(当然包括 Python)都包含http 库用于下载数据。调试也很方便; 由于http web 服务中每一个资源都有一个唯一的地址(以url的形式存在), 你可以在浏览器中加载它并且立即看到原始的数据.

HTTP 特性

这里有一个 HTTP 头的具体例子。 你通过浏览器访问 <diveintomark.org> 。该网页包含一个背景图片, <wearehugh.com/m.jpg> 。当你的浏览器下载那张图片时,服务器的返回包含了下面的 http 头:

1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 200 OK
Date: Sun, 31 May 2009 17:14:04 GMT
Server: Apache
Last-Modified: Fri, 22 Aug 2008 04:28:16 GMT
ETag: "3075-ddc8d800"
Accept-Ranges: bytes
Content-Length: 12405
Cache-Control: max-age=31536000, public
Expires: Mon, 31 May 2010 17:14:04 GMT
Connection: close
Content-Type: image/jpeg

根据这个http头我们可以从中了解到http几个特性:

缓存

  • Cache-Control 和 Expires 头告诉浏览器(以及任何处于你和服务器之间的缓存代理服务器) 这张图片可以缓存长达一年。 如果在明年之前,你访问另外一个也包含这张图片的页面,你的浏览器会从缓存中加载这样图片而不会产生任何网络活动.

Last-Modified

Last-Modified告诉浏览器这张图片最后的修改时间为Fri, 22 Aug 2008 04:28:16 GMT。如果第二(第三,第四)次请求同样一个资源,你可以在你的请求中发送一个If-Modified-Since头,其值为你上次从服务器返回的时间。如果从那时开始,数据已经发成过变化,服务器会忽略If-Modified-Since头并返回新数据和200状态码给你。否则的话,服务器将发回一个特殊的http 304 状态码, 它的含义是“从上次请求到现在数据没有发生过变化.” 你可以在命令行上使用curl来测试:

1
2
3
4
5
6
7
8
you@localhost:~$ curl -I -H "If-Modified-Since: Fri, 22 Aug 2008 04:28:16 GMT" http://wearehugh.com/m.jpg
HTTP/1.1 304 Not Modified
Date: Sun, 31 May 2009 18:04:39 GMT
Server: Apache
Connection: close
ETag: "3075-ddc8d800"
Expires: Mon, 31 May 2010 18:04:39 GMT
Cache-Control: max-age=31536000, public

ETag

ETag 是另一个和 Last-Modified 达到同样目的的方法。使用ETag时,服务器在返回数据的同时在ETag头里返回一个哈希码(如何生成哈希码完全取决于服务器,唯一的要求是数据改变时哈希码也要改变) diveintomark.org引用的背景图片包含有ETag头。当你再次请求同样的数据时,你在If-None-Match头里放入ETag值。如果数据没有发生改变,服务器将会返回304状态码。同最后修改时间检查一样,服务器发回的只有304 状态码,不会再一次给你发送同样的数据。通过在请求中包含ETag 哈希码,你告诉服务器如果哈希值匹配就不需要重新发送同样的数据了,因为你仍然保留着上次收到的数据:

1
2
3
4
5
6
7
8
you@localhost:~$ curl -I -H "If-None-Match: \"3075-ddc8d800\"" http://wearehugh.com/m.jpg  ①
HTTP/1.1 304 Not Modified
Date: Sun, 31 May 2009 18:04:39 GMT
Server: Apache
Connection: close
ETag: "3075-ddc8d800"
Expires: Mon, 31 May 2010 18:04:39 GMT
Cache-Control: max-age=31536000, public

另外,http还有其他两个重要特性:

压缩

当我们谈论 http web 服务的时候, 你总是会讨论到在线路上来回运送文本数据。可能是xml,也可能是json,抑或仅仅是纯文本。不管是什么格式,文本的压缩性能很好。

http支持若干种压缩算法。最常见的两种是gzip 和 deflate。当你通过http请求资源时,你可以要求服务器以压缩格式返回资源。你在请求中包含一个Accept-encoding头,里面列出了你支持的压缩算法。如果服务器也支持其中的某一种算法,它就会返回给你压缩后的数据(同时通过Content-encoding头标识它使用的算法)。接下来的事情就是由你去解压数据了。

重定向

每一次你向http服务器请求资源的时候, 服务器都会在响应中包含一个状态码。 状态码200的意思是一切正常,这就是你请求的页面; 状态码404的意思是找不到页面; (你很可能在浏览网页的时候碰到过404)。300 系列的状态码意味着某种形式的重定向。

http 有多种方法表示一个资源已经被移动。最常见两个技术是状态码 302 和 301。 状态码 302 是一个 临时重定向; 它意味着, 资源被被临时从这里移动走了; (并且临时地址在Location[1]头里面给出)。状态码301是永久重定向; 它意味着,资源被永久的移动了; (并且在Location头里面给出了新的地址)。如果你得到302状态码和一个新地址, http规范要求你访问新地址来获得你要的资源,但是下次你要访问同样的资源的时候你应该重新尝试旧的地址。但是如果你得到301状态码和新地址, 你从今以后都应该使用新的地址。

URI

HTTP协议通过URI(Uniform Resource Identifiers,统一资源定位符)来访问资源。根据RFC 1808的官方定义,一个完整URI的组成如下:

1
http://myname:mypass@www.hahack.com:80/mydir/myfile.html?myvar=myvalue#myfrag
URI部分 意义
http 协议名称
myname 用户名(可选)
mypass 密码(可选)
www.hahack.com 主机网络地址
80 端口号(可选)
/mydir/myfile.html 资源路径
myvar=myvalue 查询字符串(可选)
myfrag 锚点(可选)

可见协议名称用“😕/”结束,用户名和密码以“:”分隔,以“@”结束,端口号与主机网络地址以“:”分隔,资源路径与查询字符串以“?”分隔,锚点以#开头。并且,只有协议名称、主机网络地址和资源路径是必须包含在URI里的。

一个更常见的例子如下:

1
http://www.hahack.com/

HTTP请求与响应

HTTP响应状态码

状态码 定义
1xx 报告 接收到请求,继续进程
2xx 成功 步骤成功接收,被理解,并被接受
3xx 重定向 为了完成请求,必须采取进一步措施
4xx 客户端出错 请求包括错的顺序或不能完成
5xx 服务器出错 服务器无法完成显然有效的请求

客户端错误

状态码 定义
“100” Continue 继续
“101” witching Protocols 交换协议

成功

状态码 定义
“200” OK
“201” Created 已创建
“202” Accepted 接收
“203” Non-Authoritative Information 非认证信息
“204” No Content 无内容
“205” Reset Content 重置内容
“206” Partial Content 部分内容

重定向

状态码 定义
“300” Multiple Choices 多路选择
“301” Moved Permanently 永久转移
“302” Found 暂时转移
“303” See Other 参见其它
“304” Not Modified 未修改
“305” Use Proxy 使用代理
“307” Temporary Redirect

客户方错误

状态码 定义
“400” Bad Request 错误请求
“401” Unauthorized 未认证
“402” Payment Required 需要付费
“403” Forbidden 禁止
“404” Not Found 未找到
“405” Method Not Allowed 方法不允许
“406” Not Acceptable 不接受
“407” Proxy Authentication Required 需要代理认证
“408” Request Time-out 请求超时
“409” Conflict 冲突
“410” Gone 失败
“411” Length Required 需要长度
“412” Precondition Failed 条件失败
“413” Request Entity Too Large 请求实体太大
“414” Request-URI Too Large 请求URI太长
“415” Unsupported Media Type 不支持媒体类型
“416” Requested range not satisfiable
“417” Expectation Failed

服务器错误

状态码 定义
“500” Internal Server Error 服务器内部错误
“501” Not Implemented 未实现
“502” Bad Gateway 网关失败
“503” Service Unavailable
“504” Gateway Time-out 网关超时
“505” HTTP Version not supported HTTP版本不支持

HTTP状态码是可扩展的。HTTP应用程序不需要理解所有已注册状态码的含义,尽管那样的理解显而易见是很合算的。但是,应用程序必须了解由第一位数字指定的状态码的类型,任何未被识别的响应应被看作是该类型的x00状态,有一个例外就是未被识别的响应不能缓存。例如,如果客户端收到一个未被识别的状态码431,则可以安全的假定请求有错,并且它会对待此响应就像它接收了一个状态码是400的响应。在这种情况下,用户代理(user agent)应当把实体和响应一起提交给用户,因为实体很可能包括人可读的关于解释不正常状态的信息。报文最后是实体信息,即客户请求得到的HTTP服务器上的资源内容。


  1. Location 的意思是 “看那边!” ↩︎

Comments