def renderHTTP(self, nevow_ctx): context = pmap({ NEVOW_REQUEST: IRequest(nevow_ctx), }) d = execute(context, v(nevow()) + self._interceptors) d.addCallback(lambda _: b'') return d
def test_default(self): """ Default content parsers. """ interceptors = [body_params()] request = m( content_type='application/x-www-form-urlencoded; charset="utf-8"', character_encoding='utf-8', body=BytesIO( urllib.urlencode([(b'a', b'1'), (b'b', b'2'), (b'b', b'3'), (b'c', u'\N{SNOWMAN}'.encode('utf-8')), (b'd', b'')]))) context = empty_context.set(REQUEST, request) self.assertThat( execute(context, interceptors), succeeded( ContainsDict({ REQUEST: ContainsDict({ 'form_params': Equals( pmap({ u'a': u'1', u'b': [u'2', u'3'], u'c': u'\N{SNOWMAN}', u'd': True })) }) })))
def test_simple(self): """ Invoke interceptor "enter" events then "leave" events in reverse. """ interceptors = [tracer('a'), tracer('b'), tracer('c')] self.assertThat([ execute(enqueue(empty_context, interceptors)), execute(empty_context, interceptors) ], AllMatch( succeeded( Equals({ TRACE: v(('enter', 'a'), ('enter', 'b'), ('enter', 'c'), ('leave', 'c'), ('leave', 'b'), ('leave', 'a')) }))))
def test_async_error_propagates(self): """ If an unhandled asynchronous error occurs in an interceptor it propogates along the execution. """ interceptors = [tracer('a'), tracer('b'), thrower('c'), tracer('d')] self.assertThat(execute(empty_context, interceptors), failed(After(lambda f: f.type, Is(TracingError))))
def test_unhandled(self): """ If nothing can handle the content type, return the request untouched. """ interceptors = [body_params()] context = empty_context.set(REQUEST, self.request()) self.assertThat(execute(context, interceptors), succeeded(Equals(context)))
def test_route_tuple(self): """ Routes can be specified as tuples. """ interceptor = route.router((u'/foo', route.GET, [tracer('a')])) context = empty_context.set(REQUEST, basic_request(uri=u'/foo')) self.assertThat( execute(context, [interceptor]), succeeded(Traced(Equals(v(('enter', 'a'), ('leave', 'a'))))))
def test_route_unmatched(self): """ If no route matches the request path, no ``ROUTE`` value is set on the context, and no route interceptors are enqueued. """ interceptor = route.router( route.route(u'/foo', route.GET, [tracer('a')])) context = empty_context.set(REQUEST, basic_request(uri=u'/bar')) self.assertThat( execute(context, [interceptor]), succeeded(MatchesAll(Equals(context), Not(Contains(ROUTE)))))
def test_handler(self): """ """ interceptors = [handler(lambda x: x)] value = object() context = empty_context.set(REQUEST, value) self.assertThat( execute(context, interceptors), succeeded(ContainsDict({ REQUEST: Is(value), RESPONSE: Is(value) })))
def test_after(self): """ Interceptor only has a leave function. """ interceptors = [tracer('a'), after(tracing('leave', 'b')), tracer('c')] self.assertThat( execute(empty_context, interceptors), succeeded( Traced( Equals( v(('enter', 'a'), ('enter', 'c'), ('leave', 'c'), ('leave', 'b'), ('leave', 'a'))))))
def test_on_request(self): """ Update the request. """ interceptors = [on_request(lambda req: ('enter', req))] self.assertThat( execute(self.context, interceptors), succeeded( ContainsDict({ REQUEST: Equals(('enter', 42)), RESPONSE: Equals(21) })))
def test_on_response(self): """ Update the response. """ interceptors = [on_response(lambda res: ('leave', res))] self.assertThat( execute(self.context, interceptors), succeeded( ContainsDict({ REQUEST: Equals(42), RESPONSE: Equals(('leave', 21)) })))
def test_only_enter(self): """ If the second function is ``None`` then do nothing in the leave stage. """ interceptors = [middleware(lambda req: ('enter', req), None)] self.assertThat( execute(self.context, interceptors), succeeded( ContainsDict({ REQUEST: Equals(('enter', 42)), RESPONSE: Equals(21) })))
def test_only_leave(self): """ If the first function is ``None`` then do nothing in the enter stage. """ interceptors = [middleware(None, lambda res: ('leave', res))] self.assertThat( execute(self.context, interceptors), succeeded( ContainsDict({ REQUEST: Equals(42), RESPONSE: Equals(('leave', 21)) })))
def test_custom(self): """ Custom content parsers. """ interceptors = [ body_params( default_parsers(json_options=dict(object_hook=lambda _: 42))) ] context = empty_context.set(REQUEST, self.request()) self.assertThat( execute(context, interceptors), succeeded( ContainsDict( {REQUEST: ContainsDict({'json_params': Equals(42)})})))
def test_default(self): """ Default content parsers. """ interceptors = [body_params()] context = empty_context.set(REQUEST, self.request()) self.assertThat( execute(context, interceptors), succeeded( ContainsDict({ REQUEST: ContainsDict( {'json_params': Equals(freeze(self.payload()))}) })))
def test_middleware(self): """ Apply a function to the `REQUEST` value on enter and another function to the `RESPONSE` value on leave. """ interceptors = [ middleware(lambda req: ('enter', req), lambda res: ('leave', res)) ] self.assertThat( execute(self.context, interceptors), succeeded( ContainsDict({ REQUEST: Equals(('enter', 42)), RESPONSE: Equals(('leave', 21)) })))
def test_termination_predicate(self): """ When a termination predicate is true, the "leave" phase is immediately entered. """ interceptors = [tracer('a'), tracer('b'), tracer('c')] context = terminate_when( empty_context, lambda context: ('enter', 'b') in context.get(TRACE)) self.assertThat( execute(context, interceptors), succeeded( ContainsDict({ TRACE: Equals( v(('enter', 'a'), ('enter', 'b'), ('leave', 'b'), ('leave', 'a'))) })))
def test_deferred(self): """ Any interceptor stage can return a `Deferred` and the execution will wait for it to resolve (or fail) before continuing. """ clock = Clock() interceptors = [tracer('a'), deferrer('b', clock, 1), tracer('c')] d = execute(empty_context, interceptors) self.assertThat(d, has_no_result()) clock.advance(1) self.assertThat( d, succeeded( Equals({ TRACE: v(('enter', 'a'), ('enter', 'b'), ('enter', 'c'), ('leave', 'c'), ('leave', 'b'), ('leave', 'a')) })))
def test_error_fumble(self): """ An interceptor that attempts but fails to handle an error, suppresses the original error and presents the new error. """ interceptors = [ tracer('a'), tracer('b'), fumbling_catcher('c'), tracer('d'), tracer('e'), thrower('f'), tracer('g') ] self.assertThat( execute(empty_context, interceptors), failed( MatchesStructure(type=Is(TracingError), value=MatchesStructure(source=Equals('c')))))
def test_error_handler(self): """ Interceptor only has an error function. """ def _swallow(marker): return lambda context, error: tracing('error', ( marker, 'from', error.failure.value.source))(context) interceptors = [ tracer('a'), error_handler(_swallow('b')), thrower('c'), tracer('d') ] self.assertThat( execute(empty_context, interceptors), succeeded( Traced( Equals( v(('enter', 'a'), ('error', ('b', 'from', 'c')), ('leave', 'a'))))))
def test_path_specificity(self): """ Ensure that more specific routes have a higher priority than less specific routes. """ interceptor = route.router( route.route(u'/bar', route.GET, [tracer('b')], u'b'), route.route(u'/bar/:id/*rest', route.GET, [tracer('d')], u'd'), route.route(u'/foo', route.GET, [tracer('a')], u'a'), route.route(u'/bar/:id', route.GET, [tracer('c')], u'c')) req = lambda uri: execute( empty_context.set(REQUEST, basic_request(uri=uri)), [interceptor]) self.assertThat( req(u'/foo'), succeeded(Traced(Equals(v(('enter', 'a'), ('leave', 'a')))))) self.assertThat( req(u'/bar'), succeeded(Traced(Equals(v(('enter', 'b'), ('leave', 'b')))))) self.assertThat( req(u'/bar/1'), succeeded(Traced(Equals(v(('enter', 'c'), ('leave', 'c')))))) self.assertThat( req(u'/bar/1/pa/th'), succeeded(Traced(Equals(v(('enter', 'd'), ('leave', 'd'))))))
def test_error_caught(self): """ Interceptors can define an "error" stage that is capable of receiving and handling propagating errors. """ interceptors = [ tracer('a'), tracer('b'), catcher('c'), tracer('d'), tracer('e'), thrower('f'), tracer('g') ] self.assertThat( execute(empty_context, interceptors), succeeded( Equals({ TRACE: v(('enter', 'a'), ('enter', 'b'), ('enter', 'c'), ('enter', 'd'), ('enter', 'e'), ('error', 'c', 'from', 'f'), ('leave', 'b'), ('leave', 'a')) })))
def test_default(self): """ Default content parsers. """ interceptors = [body_params()] request = m( content_type= 'multipart/form-data; boundary=---------------------------114772229410704779042051621609', body=open_test_data('data/multipart_request')) context = empty_context.set(REQUEST, request) self.assertThat( execute(context, interceptors), succeeded( ContainsDict({ REQUEST: ContainsDict({ 'multipart_params': MatchesDict({ u'name': Multipart(content_length=Equals(8), name=Equals(u'name'), headers=MatchesDict({ u'Content-Disposition': Equals(u'form-data; name="name"'), }), body=Equals(b'Some One')), u'email': Multipart(content_length=Equals(16), name=Equals(u'email'), headers=MatchesDict({ u'Content-Disposition': Equals(u'form-data; name="email"'), }), body=Equals(b'*****@*****.**')), u'avatar': Multipart( content_length=Equals(869), content_type=Equals(u'image/png'), filename=Equals(u'smiley-cool.png'), name=Equals(u'avatar'), headers=MatchesDict({ u'Content-Type': Equals(u'image/png'), u'Content-Disposition': Equals( u'form-data; name="avatar"; filename="smiley-cool.png"' ), }), body=After( lambda x: hashlib.sha256(x).hexdigest(), Equals( b'25fbe073db80f71a13fb8e0a190a76c0fda494d18849fa6fa87ea5a0924baa07' ))), # XXX: This syntax isn't supported by the multipart # parser, multiple things with the same name are # overwritten. u'attachments[]': Always(), }), 'form_params': MatchesDict({ u'name': Equals(u'Some One'), u'email': Equals(u'*****@*****.**') }) }) })))
def render(self, request): context = pmap({TWISTED_REQUEST: request}) execute(context, v(twisted()) + self._interceptors) return NOT_DONE_YET