简单地讲,HTTP web 服务是指以编程的方式直接使用 http 操作从远程服务器发送和接收数据。
一些更高级的http Web 服务 API 也允许使用 http PUT 和 http DELETE 来创建、修改和删除数据。 换句话说,http 协议中的“verbs (动作)” (GET, POST, PUT 和 DELETE) 可以直接对应到应用层的操作:获取,创建,修改,删除数据。
这个方法主要的优点是简单, 它的简单证明是受欢迎的。数据 — 通常是xml或json — 可以事先创建好并静态的存储下来 ,或者由服务器端脚本动态生成, 并且所有主要的编程语言(当然包括 Python)都包含http 库用于下载数据。调试也很方便; 由于http web 服务中每一个资源都有一个唯一的地址(以url的形式存在), 你可以在浏览器中加载它并且立即看到原始的数据.
这里有一个 HTTP 头的具体例子。 你通过浏览器访问 <diveintomark.org> 。该网页包含一个背景图片, <wearehugh.com/m.jpg> 。当你的浏览器下载那张图片时,服务器的返回包含了下面的 http 头:
1 | HTTP/1.1 200 OK |
根据这个http头我们可以从中了解到http几个特性:
Last-Modified告诉浏览器这张图片最后的修改时间为Fri, 22 Aug 2008 04:28:16 GMT
。如果第二(第三,第四)次请求同样一个资源,你可以在你的请求中发送一个If-Modified-Since头,其值为你上次从服务器返回的时间。如果从那时开始,数据已经发成过变化,服务器会忽略If-Modified-Since头并返回新数据和200状态码给你。否则的话,服务器将发回一个特殊的http 304 状态码, 它的含义是“从上次请求到现在数据没有发生过变化.” 你可以在命令行上使用curl来测试:
1 | you@localhost:~$ curl -I -H "If-Modified-Since: Fri, 22 Aug 2008 04:28:16 GMT" http://wearehugh.com/m.jpg |
ETag 是另一个和 Last-Modified 达到同样目的的方法。使用ETag时,服务器在返回数据的同时在ETag头里返回一个哈希码(如何生成哈希码完全取决于服务器,唯一的要求是数据改变时哈希码也要改变) diveintomark.org引用的背景图片包含有ETag头。当你再次请求同样的数据时,你在If-None-Match头里放入ETag值。如果数据没有发生改变,服务器将会返回304状态码。同最后修改时间检查一样,服务器发回的只有304 状态码,不会再一次给你发送同样的数据。通过在请求中包含ETag 哈希码,你告诉服务器如果哈希值匹配就不需要重新发送同样的数据了,因为你仍然保留着上次收到的数据:
1 | you@localhost:~$ curl -I -H "If-None-Match: \"3075-ddc8d800\"" http://wearehugh.com/m.jpg ① |
另外,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状态码和新地址, 你从今以后都应该使用新的地址。
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/ |
状态码 | 定义 |
---|---|
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服务器上的资源内容。
Location 的意思是 “看那边!” ↩︎