httplib库浅析
目录:/usr/lib64/python2.7
库依赖:
from array import array
import os
import re
import socket
from sys import py3kwarning
from urlparse import urlsplit
import warnings
行数: 1409
工作流程:
(null)
|
| HTTPConnection()
v
Idle
|
| putrequest()
v
Request-started
|
| ( putheader() )* endheaders()
v
Request-sent
|
| response = getresponse()
v
Unread-response [Response-headers-read]
|\____________________
| |
| response.read() | putrequest()
v v
Idle Req-started-unread-response
______/|
/ |
response.read() | | ( putheader() )* endheaders()
v v
Request-started Req-sent-unread-response
|
| response.read()
v
Request-sent
类目:
"HTTP"
"HTTPResponse"
"HTTPConnection"
"HTTPException"
"NotConnected"
"UnknownProtocol"
"UnknownTransferEncoding"
"UnimplementedFileMode"
"IncompleteRead"
"InvalidURL"
"ImproperConnectionState"
"CannotSendRequest"
"CannotSendHeader"
"ResponseNotReady"
"BadStatusLine"
"error"
"responses"
关键类
HTTPConnection
初始化:
def __init__(self, host, port=None, strict=None,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None):
self.timeout = timeout
self.source_address = source_address
self.sock = None
self._buffer = []
self.__response = None
self.__state = _CS_IDLE
self._method = None
self._tunnel_host = None
self._tunnel_port = None
self._tunnel_headers = {}
self._set_hostport(host, port)
if strict is not None:
self.strict = strict
评论:指定host&port即可。初始化时会设置一些对象属性,其中self._set_hostport(host, port)会对host和port进行解析,源码如下:
def _set_hostport(self, host, port):
if port is None:
i = host.rfind(':')
j = host.rfind(']') # ipv6 addresses have [...]
if i > j:
try:
port = int(host[i+1:])
except ValueError:
if host[i+1:] == "": # http://foo.com:/ == http://foo.com/
port = self.default_port
else:
raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
host = host[:i]
else:
port = self.default_port
if host and host[0] == '[' and host[-1] == ']':
host = host[1:-1]
self.host = host
self.port = port
发送请求:
def request(self, method, url, body=None, headers={}):
"""Send a complete request to the server."""
self._send_request(method, url, body, headers)
def _send_request(self, method, url, body, headers):
# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
skips['skip_host'] = 1
if 'accept-encoding' in header_names:
skips['skip_accept_encoding'] = 1
self.putrequest(method, url, **skips)
if body is not None and 'content-length' not in header_names:
self._set_content_length(body)
for hdr, value in headers.iteritems():
self.putheader(hdr, value)
self.endheaders(body)
评论:method和url由你请求的服务器提供的api决定,body和headers由你执行的动作决定。这里多说一句,我使用的服务器提供的api需要基本验证(Basic Authentication),这一步需要在headers上增加一个键值对,下面再详谈。
得到回应(对象):
def getresponse(self, buffering=False):
"Get the response from the server."
# if a prior response has been completed, then forget about it.
if self.__response and self.__response.isclosed():
self.__response = None
#
# if a prior response exists, then it must be completed (otherwise, we
# cannot read this response's header to determine the connection-close
# behavior)
#
# note: if a prior response existed, but was connection-close, then the
# socket and response were made independent of this HTTPConnection
# object since a new request requires that we open a whole new
# connection
#
# this means the prior response had one of two states:
# 1) will_close: this connection was reset and the prior socket and
# response operate independently
# 2) persistent: the response was retained and we await its
# isclosed() status to become true.
#
if self.__state != _CS_REQ_SENT or self.__response:
raise ResponseNotReady()
args = (self.sock,)
kwds = {"strict":self.strict, "method":self._method}
if self.debuglevel > 0:
args += (self.debuglevel,)
if buffering:
kwds["buffering"] = True;
response = self.response_class(*args, **kwds)
response.begin()
assert response.will_close != _UNKNOWN
self.__state = _CS_IDLE
if response.will_close:
# this effectively passes the connection to the response
self.close()
else:
# remember this, so we can tell when it is complete
self.__response = response
return response
base64库简介
Base64编码是一种“防君子不防小人”的编码方式。广泛应用于MIME协议,作为电子邮件的传输编码,生成的编码可逆,后一两位可能有“=”,生成的编码都是ascii字符。
优点:速度快,ascii字符,肉眼不可理解
缺点:编码比较长,非常容易被破解,仅适用于加密非关键信息的场合
执行服务器的基本验证信息需要进行base64编码转换。
项目实践(测试部分)
import httplib
import base64
auth = base64.b64encode('lin'+ ':'+ '123')
headers = {"Authorization": "Basic "+ auth}
url = "http://192.168.222.128:8080/kie-server/services/rest/server"
conn = httplib.HTTPConnection("192.168.222.128",8080)
conn.request(method="GET", url=url,headers=headers)
response = conn.getresponse()
res = response.read()
print res
结果:
(xcdw_env_new) [xcdw@localhost rule]$ python httptest.py
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response type="SUCCESS" msg="Kie Server info">
<kie-server-info>
<capabilities>KieServer</capabilities>
<capabilities>BRM</capabilities>
<capabilities>BPM</capabilities>
<capabilities>BPM-UI</capabilities>
<capabilities>BRP</capabilities>
<location>http://192.168.222.128:8080/kie-server/services/rest/server</location>
<messages>
<content>Server KieServerInfo{serverId='tomcat-kieserver', version='6.5.0.Final', location='http://192.168.222.128:8080/kie-server/services/rest/server'}started successfully at Tue Dec 20 17:13:15 PST 2016</content>
<severity>INFO</severity>
<timestamp>2016-12-20T17:13:15.293-08:00</timestamp>
</messages>
<name>tomcat-kieserver</name>
<id>tomcat-kieserver</id>
<version>6.5.0.Final</version>
</kie-server-info>
</response>