1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 '''
32 urllib2 compatible Request object with additional functionality
33
34 It can therefore be supplied to urllib2 objects (like a CookieJar)
35 '''
36
37 from urllib2 import Request
38 from urlparse import urlparse, urlsplit
42 '''
43 A subclass of urllib2 Request to retain compatibility and make it usable
44 for cookies and whatever may be needed
45
46 @ivar parsed: It holds the result of the urlsplit(url) done in the constructor
47 for practical purposes
48 @type parsed: namedtuple result of urlsplit (check the Python docs)
49 '''
50
51 - def __init__(self, url, data=None, headers=None, origin_req_host=None, unverifiable=False):
52 '''
53 Constructor. It delegates construction to the base class
54 Request and initializes the member variables
55
56 It performs an additional call of Request.get_type and Request.get_host
57 to ensure that the Request object is properly initialized. Because this
58 is done by the urllib2 library, but we are just using the request
59
60 @param url: url to be requested in the HTTP request
61 @type url: str
62 @param data: data for the HTTP request body (which enforces a POST)
63 @type data: str
64 @param headers: dictionary of header name/header value
65 @type headers: dict
66 @param origin_req_host: request host of the origin transaction as per
67 RFC 2965 - Host name or IP address of the host
68 @type origin_req_host: str
69 @param unverifiable: if the request was not verified/requested by the end
70 user and it is rather automatic (redirection, download
71 of a picture inside a web page) - RFC 2965
72 @type unverifiable: bool
73 '''
74 if headers is None:
75 headers = dict()
76 Request.__init__(self, url, data, headers, origin_req_host, unverifiable)
77 self.parsed = urlsplit(url)
78
79 self.get_type()
80 self.get_host()
81
82
83 @property
85 '''
86 Property to return all the headers to be sent in a request
87
88 urllib2 distinguishes amongst normal headers and headers that will
89 not be used if the original request is redirected
90
91 Therefore it is impossible to request all headers in just one call
92
93 Although Request has a utility function, it returns a list of tuples
94 rather than a dictionary
95
96 This property returns a dictionary
97 '''
98 hdrs = self.unredirected_hdrs.copy()
99 hdrs.update(self.headers)
100 return hdrs
101
102
103 @property
105 '''
106 Property to have a handy alias for Request.get_method
107 '''
108 return self.get_method()
109
110
112 '''
113 Utility function to avoid cluttering external code with
114 string comparisons
115
116 @return: if the request will be a POST request
117 @rtype: bool
118 '''
119 return self.get_method() == 'POST'
120
121
123 '''
124 Utility function to avoid cluttering external code with
125 string comparisons
126
127 @return: if the request will be a GET request
128 @rtype: bool
129 '''
130 return self.get_method() == 'GET'
131
132
133 @property
135 '''
136 Property to have a handy alias for Request.get_type or
137 parsed.scheme
138 '''
139
140 return self.parsed.scheme
141
142
143 @property
145 '''
146 Property to have a handy alias for Request.get_host or
147 parsed.netloc
148 '''
149
150 return self.parsed.netloc
151
152
153 @property
155 '''
156 Property to have a handy alias for Request.get_data
157 '''
158 return self.get_data()
159
160
161 - def clone(self, url=None):
162 '''
163 Clone a request with a change of url to support redirection
164
165 By using the normal/unredirected header separation in Request it is
166 easy to clone for a redirection by only supplying the new headers
167 to the class
168
169 @param url: url to redirect to if needed. Default of None for no
170 redirection
171 @type url: str|None
172 @return: a cloned object
173 @rtype: L{HttxRequest}
174 '''
175
176
177 if not url:
178 url = self.get_full_url()
179 headers = self.allheaders
180 else:
181 headers = self.headers
182
183 return self.__class__(url, self.data, headers, self.origin_req_host, self.unverifiable)
184
185
187 '''
188 Deepcopy support.
189
190 @param memo: standard __deepcopy__ parameter to avoid circular references
191 @type memo: dict
192 @return: a cloned object
193 @rtype: L{HttxRequest}
194 '''
195 return self.clone()
196