def _readHeader(sok, rest=''): responses = rest rest = '' while True: response = yield _asyncRead(sok) if response is _CLOSED: raise ValueError('Premature close') responses += response match = REGEXP.RESPONSE.match(responses) if match: break # TODO: check some max. statusline + header size (or bail). if match.end() < len(responses): rest = responses[match.end():] statusAndHeaders = match.groupdict() headers = parseHeaders(statusAndHeaders['_headers']) del statusAndHeaders['_headers'] statusAndHeaders['Headers'] = headers if statusAndHeaders['StatusCode'] == '100': # 100 Continue response, eaten it - and then read the real response. statusAndHeaders, rest = yield _readHeader(sok, rest=rest) raise StopIteration((statusAndHeaders, rest))
def _readHeader(sok, rest=''): responses = rest rest = '' while True: response = yield _asyncRead(sok) if response is _CLOSED: raise ValueError('Premature close') responses += response match = REGEXP.RESPONSE.match(responses) if match: # TODO: check some max. statusline + header size (or bail). break if match.end() < len(responses): rest = responses[match.end():] statusAndHeaders = match.groupdict() headers = parseHeaders(statusAndHeaders['_headers']) del statusAndHeaders['_headers'] statusAndHeaders['Headers'] = headers if statusAndHeaders['StatusCode'] == '100': # 100 Continue response, eaten it - and then read the real response. statusAndHeaders, rest = yield _readHeader(sok, rest=rest) raise StopIteration((statusAndHeaders, rest))
def updateResponseHeaders(headers, match, addHeaders=None, removeHeaders=None, requireAbsent=None): requireAbsent = set(requireAbsent or []) addHeaders = addHeaders or {} removeHeaders = removeHeaders or [] headersDict = parseHeaders(match.groupdict()['_headers']) matchStartHeaders = match.start('_headers') matchEnd = match.end() _statusLine = headers[:matchStartHeaders - CRLF_LEN] _headers = headers[matchStartHeaders - CRLF_LEN:matchEnd - CRLF_LEN] _body = headers[matchEnd:] notAbsents = requireAbsent.intersection(set(headersDict.keys())) if notAbsents: raise ValueError('Response headers contained disallowed items: %s' % ', '.join(notAbsents)) for header in removeHeaders: headerRe = _removeHeaderReCache.get(header, None) if headerRe is None: headerRe = re.compile(r'\r\n%s:.*?\r\n' % re.escape(header), flags=re.I) _removeHeaderReCache[header] = headerRe _headers = headerRe.sub(CRLF, _headers, count=1) for header, value in addHeaders.items(): _headers += '%s: %s\r\n' % (header, value) return _statusLine + _headers + CRLF, _body
def testRedirectWithPostedRedirectPath(self): registry = ObjectRegistry(self.tempdir, name='name', redirectPath='/redirect') registry.registerKeys(keys=['key1', 'key2'], booleanKeys=['enabled1', 'enabled2']) data = urlencode([('key1', 'value1'), ('enabled1', 'on'), ('redirectPath', '/object?id={}')]) header, _ = asString( registry.handleRequest(Method='POST', path='/objects/add', Body=data, session={})).split(CRLF * 2) redirectLocation = parseHeaders(header + CRLF)['Location'] path, objectid = redirectLocation.split('=') self.assertEquals('/object?id', path) self.assertEquals( { objectid: { 'key1': 'value1', 'key2': '', 'enabled1': True, 'enabled2': False } }, registry.listObjects())
def _readHeaders(self): match = REGEXP.REQUEST.match(self._dataBuffer) if not match: return # for more data self.request = match.groupdict() self.request['Body'] = '' self.request['Headers'] = parseHeaders(self.request['_headers']) matchEnd = match.end() self._dataBuffer = self._dataBuffer[matchEnd:] if 'Content-Type' in self.request['Headers']: cType, pDict = parseHeader(self.request['Headers']['Content-Type']) if cType.startswith('multipart/form-data'): self._tempfile = TemporaryFile('w+b') #self._tempfile = open('/tmp/mimetest', 'w+b') self._tempfile.write('Content-Type: %s\r\n\r\n' % self.request['Headers']['Content-Type']) self.setCallDealer(lambda: self._readMultiForm(pDict['boundary'])) return if 'Expect' in self.request['Headers']: self._sok.send('HTTP/1.1 100 Continue\r\n\r\n') if self._reactor.getOpenConnections() > self._maxConnections: self.request['ResponseCode'] = 503 return self._finalize(self._errorHandler) if self.request['Method'] in ['POST', 'PUT']: self.setCallDealer(self._readBody) else: self.finalize()
def _readHeaders(self): match = REGEXP.REQUEST.match(self._dataBuffer) if not match: return # for more data self.request = match.groupdict() self.request['Body'] = '' self.request['Headers'] = parseHeaders(self.request['_headers']) matchEnd = match.end() self._dataBuffer = self._dataBuffer[matchEnd:] if 'Content-Type' in self.request['Headers']: cType, pDict = parseHeader(self.request['Headers']['Content-Type']) if cType.startswith('multipart/form-data'): self._tempfile = TemporaryFile('w+b') #self._tempfile = open('/tmp/mimetest', 'w+b') self._tempfile.write('Content-Type: %s\r\n\r\n' % self.request['Headers']['Content-Type']) self.setCallDealer( lambda: self._readMultiForm(pDict['boundary'])) return if 'Expect' in self.request['Headers']: self._sok.send('HTTP/1.1 100 Continue\r\n\r\n') if self._reactor.getOpenConnections() > self._maxConnections: self.request['ResponseCode'] = 503 return self._finalize(self._errorHandler) if self.request['Method'] in ['POST', 'PUT']: self.setCallDealer(self._readBody) else: self.finalize()
def testInjectAnyCookie(self): sessions = [] def handleRequest(session=None, *args, **kwargs): sessions.append(session) yield utils.okHtml + '<html/>' self.observer.handleRequest = handleRequest headers = asString(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={'Cookie': '%s=%s' % (self.cookiestore.cookieName(), 'injected_id')})).split(CRLF*2,1)[0] headers = parseHeaders(headers) self.assertTrue('injected_id' not in headers['Set-Cookie'])
def testInjectAnyCookie(self): sessions = [] class MyObserver(Observable): def handleRequest(self, session=None, *args, **kwargs): sessions.append(session) yield utils.okHtml + '<html/>' self.handler.addObserver(MyObserver()) headers = asString(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={'Cookie': '%s=%s' % (self.cookiestore.cookieName(), 'injected_id')})).split(CRLF*2,1)[0] headers = parseHeaders(headers) self.assertTrue('injected_id' not in headers['Set-Cookie'])
def parseHttpResponse(response): _match = REGEXP.RESPONSE.match(response) if not _match: return ((None, None), 'Unexpected response (not a valid HTTP Response): {0}'.format(_shorten(response))) body = response[_match.end():] # Slice can result in an empty string statusAndHeaders = _match.groupdict() _headers = parseHeaders(statusAndHeaders['_headers']) del statusAndHeaders['_headers'] statusAndHeaders['Headers'] = _headers return ((statusAndHeaders, body), None)
def testRetrieveCookie(self): sessions = [] def handleRequest(session=None, *args, **kwargs): sessions.append(session) yield utils.okHtml + '<html/>' self.observer.handleRequest = handleRequest headers = asString(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={})).split(CRLF*2,1)[0] headers = parseHeaders(headers) self.assertTrue('Set-Cookie' in headers, headers) cookie = findCookies(headers, self.cookiestore.cookieName(), 'Set-Cookie')[0] consume(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={'Cookie': '{0}={1}'.format(self.cookiestore.cookieName(), cookie)})) self.assertEquals(sessions[0], sessions[1]) self.assertEquals(id(sessions[0]),id(sessions[1]))
def testRetrieveCookie(self): sessions = [] class MyObserver(Observable): def handleRequest(self, *args, **kwargs): session = self.ctx.session sessions.append(session) yield utils.okHtml + '<html/>' self.handler.addObserver(MyObserver()) headers = asString(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={})).split(CRLF*2,1)[0] headers = parseHeaders(headers) self.assertTrue('Set-Cookie' in headers, headers) cookie = findCookies(headers, self.cookiestore.cookieName(), 'Set-Cookie')[0] consume(self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={'Cookie': '{0}={1}'.format(self.cookiestore.cookieName(), cookie)})) self.assertEquals(sessions[0], sessions[1]) self.assertEquals(id(sessions[0]),id(sessions[1]))
def parseHttpResponse(response): _match = REGEXP.RESPONSE.match(response) if not _match: return ((None, None), 'Unexpected response (not a valid HTTP Response): {0}'.format( _shorten(response))) body = response[_match.end():] # Slice can result in an empty string statusAndHeaders = _match.groupdict() for key, value in statusAndHeaders.items(): if key == '_headers': continue statusAndHeaders[key] = value.decode() statusAndHeaders['Headers'] = parseHeaders( statusAndHeaders.pop('_headers')) return ((statusAndHeaders, body), None)
def testRedirectWithPostedRedirectPathButWithoutIdentifier(self): def validate(**kwargs): raise ValueError('oops') registry = ObjectRegistry(self.tempdir, name='name', redirectPath='/redirect', validate=validate) registry.registerKeys(keys=['key1', 'key2'], booleanKeys=['enabled1', 'enabled2']) data = urlencode([('key1', 'value1'), ('enabled1', 'on'), ('redirectPath', '/object?id={}')]) header, _ = asString( registry.handleRequest(Method='POST', path='/objects/add', Body=data, session={})).split(CRLF * 2) redirectLocation = parseHeaders(header + CRLF)['Location'] path, objectid = redirectLocation.split('#') self.assertEquals('/redirect', path) self.assertEqual('', objectid) self.assertEquals({}, registry.listObjects())
def testNoKeySendDoesNotChangeOldValue(self): registry = ObjectRegistry(self.tempdir, name='name', redirectPath='/redirect') registry.registerKeys(keys=['key2', 'key1'], booleanKeys=['enabled1', 'enabled2']) object1id = registry.addObject(key1=["object1"], key2=["value2"], enabled1=['on']) self.assertEquals( { 'key1': 'object1', 'key2': 'value2', 'enabled1': True, 'enabled2': False, }, registry.listObjects()[object1id]) data = urlencode([ ('identifier', object1id), ('key1', 'value1'), ('enabled2', 'on'), ]) header, _ = asString( registry.handleRequest(Method='POST', path='/objects/update', Body=data, session={})).split(CRLF * 2) redirectLocation = parseHeaders(header + CRLF)['Location'] path, objectid = redirectLocation.split('#') self.assertEquals(object1id, objectid) self.assertEquals( { 'key1': 'value1', 'key2': 'value2', 'enabled1': False, 'enabled2': True, }, registry.listObjects()[object1id])
def _headerFragment(self): self._responseBuffer += self._sok.recv(self._recvSize) match = REGEXP.RESPONSE.match(self._responseBuffer) if not match: if not self._timer: self._startTimer() return #for more data self._stopTimer() if match.end() < len(self._responseBuffer): restData = self._responseBuffer[match.end():] else: restData = '' response = match.groupdict() response['Headers'] = parseHeaders(response['_headers']) self._chunked = 'Transfer-Encoding' in response['Headers'] and response['Headers']['Transfer-Encoding'] == 'chunked' del response['_headers'] response['Client'] = self._peername self._handler.send(response) if restData: self._sendFragment(restData) self._reactor.removeReader(self._sok) self._reactor.addReader(self._sok, self._bodyFragment) self._startTimer()
def _headerFragment(self): self._responseBuffer += self._sok.recv(self._recvSize) match = REGEXP.RESPONSE.match(self._responseBuffer) if not match: if not self._timer: self._startTimer() return #for more data self._stopTimer() if match.end() < len(self._responseBuffer): restData = self._responseBuffer[match.end():] else: restData = '' response = match.groupdict() response['Headers'] = parseHeaders(response['_headers']) self._chunked = 'Transfer-Encoding' in response[ 'Headers'] and response['Headers']['Transfer-Encoding'] == 'chunked' del response['_headers'] response['Client'] = self._peername self._handler.send(response) if restData: self._sendFragment(restData) self._reactor.removeReader(self._sok) self._reactor.addReader(self._sok, self._bodyFragment) self._startTimer()
def _parseHeaders(regexp, header): headers = regexp.match(header).groupdict() headers['Headers'] = parseHeaders(headers.pop('_headers')) return headers