1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
6 class RequestHeaders(object):
7 '''A custom dictionary impementation for headers which ignores the case
8 of requests, since different HTTP libraries seem to mangle them.
10 def __init__(self
, dict_
):
11 if isinstance(dict_
, RequestHeaders
):
14 self
._dict
= dict((k
.lower(), v
) for k
, v
in dict_
.iteritems())
16 def get(self
, key
, default
=None):
17 return self
._dict
.get(key
.lower(), default
)
20 return repr(self
._dict
)
23 return repr(self
._dict
)
26 class Request(object):
29 def __init__(self
, path
, host
, headers
, arguments
={}):
30 self
.path
= path
.lstrip('/')
31 assert not '/' in host
, 'Host "%s" should not contain a slash' % host
33 self
.headers
= RequestHeaders(headers
)
34 self
.arguments
= arguments
37 def ForTest(path
, host
=None, headers
=None, arguments
=None):
39 host
or 'developer.chrome.com',
44 return 'Request(path=%s, host=%s, headers=%s)' % (
45 self
.path
, self
.host
, self
.headers
)
50 class _ContentBuilder(object):
51 '''Builds the response content.
56 def Append(self
, content
):
57 if isinstance(content
, unicode):
58 content
= content
.encode('utf-8', 'replace')
59 self
._buf
.append(content
)
66 return self
.ToString()
69 return len(self
.ToString())
72 self
._buf
= [''.join(self
._buf
)]
74 class Response(object):
75 '''The response from Get().
77 def __init__(self
, content
=None, headers
=None, status
=None):
78 self
.content
= _ContentBuilder()
79 if content
is not None:
80 self
.content
.Append(content
)
82 if headers
is not None:
83 self
.headers
.update(headers
)
87 def Ok(content
, headers
=None):
88 '''Returns an OK (200) response.
90 return Response(content
=content
, headers
=headers
, status
=200)
93 def Redirect(url
, permanent
=False):
94 '''Returns a redirect (301 or 302) response.
96 status
= 301 if permanent
else 302
97 return Response(headers
={'Location': url
}, status
=status
)
100 def BadRequest(content
, headers
=None):
101 '''Returns a bad request (400) response.
103 return Response(content
=content
, headers
=headers
, status
=400)
106 def Unauthorized(content
, method
, realm
, headers
={}):
107 '''Returns an unauthorized (401) response.
109 new_headers
= headers
.copy()
111 'WWW-Authentication': '%s realm="%s"' % (method
, realm
)})
112 return Response(content
=content
, headers
=headers
, status
=401)
115 def Forbidden(content
, headers
=None):
116 '''Returns an forbidden (403) response.
118 return Response(content
=content
, headers
=headers
, status
=403)
121 def NotFound(content
, headers
=None):
122 '''Returns a not found (404) response.
124 return Response(content
=content
, headers
=headers
, status
=404)
127 def NotModified(content
, headers
=None):
128 return Response(content
=content
, headers
=headers
, status
=304)
131 def InternalError(content
, headers
=None):
132 '''Returns an internal error (500) response.
134 return Response(content
=content
, headers
=headers
, status
=500)
137 def ThrottledError(content
, headers
=None):
138 '''Returns an HTTP throttle error (429) response.
140 return Response(content
=content
, headers
=headers
, status
=429)
142 def Append(self
, content
):
143 '''Appends |content| to the response content.
145 self
.content
.append(content
)
147 def AddHeader(self
, key
, value
):
148 '''Adds a header to the response.
150 self
.headers
[key
] = value
152 def AddHeaders(self
, headers
):
153 '''Adds several headers to the response.
155 self
.headers
.update(headers
)
157 def SetStatus(self
, status
):
160 def GetRedirect(self
):
161 if self
.headers
.get('Location') is None:
163 return (self
.headers
.get('Location'), self
.status
== 301)
165 def IsNotFound(self
):
166 return self
.status
== 404
168 def __eq__(self
, other
):
169 return (isinstance(other
, self
.__class
__) and
170 str(other
.content
) == str(self
.content
) and
171 other
.headers
== self
.headers
and
172 other
.status
== self
.status
)
174 def __ne__(self
, other
):
175 return not (self
== other
)
178 return 'Response(content=%s bytes, status=%s, headers=%s)' % (
179 len(self
.content
), self
.status
, self
.headers
)
184 class Servlet(object):
185 def __init__(self
, request
):
186 self
._request
= request
189 '''Returns a Response.
191 raise NotImplemented()