def process(self, chain, request:Request, response:ErrorResponseHTTP, **keyargs): ''' @see: HandlerProcessor.process Provides the time zone support for the request converter. ''' assert isinstance(request, Request), 'Invalid request %s' % request timeZoneStr = TIME_ZONE.fetch(request) if timeZoneStr: try: timeZoneStr = timezone(timeZoneStr) except UnknownTimeZoneError: TIME_ZONE_ERROR.set(response) if response.errorMessages is None: response.errorMessages = [] response.errorMessages.append('Unknown time zone \'%s\'' % timeZoneStr) return else: timeZoneStr = self.defaultTZ timeZoneVal = CONTENT_TIME_ZONE.fetch(request) if timeZoneVal: try: timeZoneVal = timezone(timeZoneVal) except UnknownTimeZoneError: TIME_ZONE_ERROR.set(response) addError(response, 'Unknown content time zone \'%(timeZone)s\'', timeZone=timeZoneVal) return else: timeZoneVal = self.defaultTZ request.converterContent = ConverterTimeZone(request.converterContent, self.baseTZ, timeZoneStr, timeZoneVal)
def process(self, chain, processing, request:Request, requestCnt:RequestContent, response:ErrorResponse, responseCnt:ResponseContent, Target:TargetContent, **keyargs): ''' Parse the request content. ''' assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain assert isinstance(processing, Processing), 'Invalid processing %s' % processing assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(requestCnt, RequestContent), 'Invalid request content %s' % requestCnt assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt assert isinstance(response, ErrorResponse), 'Invalid response %s' % response if response.isSuccess is False: return # Skip in case the response is in error if not request.invoker: return assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker if not request.invoker.decodingContent: return target = Target(arg=chain.arg, converter=request.converterContent) assert isinstance(target, TargetContent), 'Invalid target %s' % target # Resolving the character set if requestCnt.charSet: try: codecs.lookup(requestCnt.charSet) except LookupError: requestCnt.charSet = self.charSetDefault else: requestCnt.charSet = self.charSetDefault if not requestCnt.type: requestCnt.type = responseCnt.type if not processing.wingIn(chain, True, decoding=request.invoker.decodingContent, target=target).execute(CONSUMED): if RequestContent.doFetchNextContent in requestCnt and requestCnt.doFetchNextContent: chain.arg.requestCnt = requestCnt.doFetchNextContent() else: chain.arg.requestCnt = None # We process the chain with the next content or no content. elif response.isSuccess is not False: ENCODING_UNKNOWN.set(response) addError(response, 'Content type \'%(type)s\' not supported for parsing', type=requestCnt.type)
def process(self, chain, request:Request, response:Response, **keyargs): ''' @see: HandlerProcessor.process Provides the input error handling. ''' assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response if response.isSuccess is not False: return # Skip in case the response is not in error if response.errorInput is None: return # No input error to handle. assert isinstance(response.errorInput, InputError), 'Invalid input error %s' % response.errorInput if response.errorInput.messages: if request.invoker: assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker bindType = None if request.invoker.method == GET: for inp in request.invoker.inputs: assert isinstance(inp, Input), 'Invalid input %s' % inp if isinstance(inp.type, TypeProperty) and inp.type.parent == request.invoker.target: assert isinstance(inp.type, TypeProperty) bindType = inp.type elif request.invoker.method == INSERT or request.invoker.method == UPDATE: bindType = request.invoker.target elif request.invoker.method == DELETE: for inp in request.invoker.inputs: assert isinstance(inp, Input), 'Invalid input %s' % inp if isinstance(inp.type, TypeProperty): bindType = inp.type if bindType: response.errorInput.messageByType[bindType] = response.errorInput.messages response.errorInput.messages = [] addError(response, str(response.errorInput))
def process(self, chain, processing, request: Request, requestCnt: RequestContent, response: ErrorResponse, responseCnt: ResponseContent, Target: TargetContent, **keyargs): ''' Parse the request content. ''' assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain assert isinstance(processing, Processing), 'Invalid processing %s' % processing assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance( requestCnt, RequestContent), 'Invalid request content %s' % requestCnt assert isinstance( responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt assert isinstance(response, ErrorResponse), 'Invalid response %s' % response if response.isSuccess is False: return # Skip in case the response is in error if not request.invoker: return assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker if not request.invoker.decodingContent: return target = Target(arg=chain.arg, converter=request.converterContent) assert isinstance(target, TargetContent), 'Invalid target %s' % target # Resolving the character set if requestCnt.charSet: try: codecs.lookup(requestCnt.charSet) except LookupError: requestCnt.charSet = self.charSetDefault else: requestCnt.charSet = self.charSetDefault if not requestCnt.type: requestCnt.type = responseCnt.type if not processing.wingIn(chain, True, decoding=request.invoker.decodingContent, target=target).execute(CONSUMED): if RequestContent.doFetchNextContent in requestCnt and requestCnt.doFetchNextContent: chain.arg.requestCnt = requestCnt.doFetchNextContent() else: chain.arg.requestCnt = None # We process the chain with the next content or no content. elif response.isSuccess is not False: ENCODING_UNKNOWN.set(response) addError(response, 'Content type \'%(type)s\' not supported for parsing', type=requestCnt.type)
def process(self, chain, request:Request, requestCnt:RequestContent, response:ErrorResponse, decoding:Context, target:Target, **keyargs): ''' @see: HandlerProcessor.process Parse the request object. ''' assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(requestCnt, RequestContent), 'Invalid request content %s' % requestCnt assert isinstance(target, Target), 'Invalid support %s' % target assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker # Check if the response is for this parser if requestCnt.type not in self.contentTypes: assert log.debug('The content type \'%s\' is not for this %s parser', requestCnt.type, self) or True return chain.cancel() # We need to stop the chain if we have been able to provide the parsing if requestCnt.source is None: CONTENT_MISSING.set(response) return assert isinstance(requestCnt.source, IInputStream), 'Invalid request content stream %s' % requestCnt.source assert isinstance(requestCnt.charSet, str), 'Invalid request content character set %s' % requestCnt.charSet try: self.parse(requestCnt.source, requestCnt.charSet, decoding, target) except InputError as e: assert isinstance(e, InputError) INPUT_ERROR.set(response) response.errorInput = e assert log.debug('User input exception: %s', e, exc_info=True) or True else: if target.failures: CONTENT_BAD.set(response) for name, definitions, values, messages in self.indexFailures(target.failures): if values: if name: messages.append('Invalid values \'%(values)s\' for \'%(name)s\'') else: messages.append('Invalid values \'%(values)s\'') addError(response, messages, definitions, name=name, values=values) if not name: defins = [] for defin in request.invoker.definitions: assert isinstance(defin, Definition), 'Invalid definition %s' % defin if defin.category == self.category: defins.append(defin) if defins: addError(response, 'The available content', defins) if isinstance(requestCnt.source, IClosable): requestCnt.source.close()
def process(self, chain, request:Request, response:ErrorResponseHTTP, Target:TargetParameter, **keyargs): ''' Process the parameters into arguments. ''' assert isinstance(chain, Chain), 'Invalid chain %s' % chain assert isinstance(request, Request), 'Invalid request %s' % request assert issubclass(Target, TargetParameter), 'Invalid target class %s' % Target if response.isSuccess is False: return # Skip in case the response is in error if not request.invoker: return # No invoker available assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker illegal = None decodings = request.invoker.decodingsParameter if not decodings: if request.parameters: illegal = set(name for name, value in request.parameters) else: assert isinstance(decodings, dict), 'Invalid decodings %s' % decodings target = Target(arg=chain.arg, converter=request.converterPath) assert isinstance(target, TargetParameter), 'Invalid target %s' % target visited = set() if request.parameters: for name, value in request.parameters: decoding = decodings.get(name) if decoding is None: if illegal is None: illegal = set() illegal.add(name) else: assert isinstance(decoding, Decoding), 'Invalid decoding definition %s' % decoding assert isinstance(decoding.doDecode, IDo), 'Invalid do decode %s' % decoding.doDecode decoding.doDecode(target, value) visited.add(name) for name, decoding in decodings.items(): if name not in visited and decoding.doDefault: decoding.doDefault(target) if target.failures: PARAMETER_INVALID.set(response) for name, definitions, values, messages in self.indexFailures(target.failures): addError(response, messages, 'Invalid values \'%(values)s\' for \'%(name)s\'', definitions, name=name, values=values) if illegal: PARAMETER_ILLEGAL.set(response) addError(response, 'Unknown parameters %(parameters)s', parameters=sorted(illegal))
def process(self, chain, request: Request, response: Response, Target: TargetPath, **keyargs): ''' Provide the invoker based on the request method to be used in getting the data for the response. ''' assert isinstance(chain, Chain), 'Invalid chain %s' % chain assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response assert issubclass(Target, TargetPath), 'Invalid target class %s' % Target if response.isSuccess is False: return # Skip in case the response is in error assert isinstance(request.node, Node), 'Invalid request node %s' % request.node assert isinstance(request.node.invokers, dict) and request.node.invokers, \ 'Invalid request node invokers %s' % request.node.invokers request.invoker = request.node.invokers.get(request.method) if request.invoker is None: if response.allows is None: response.allows = set() response.allows.update(request.node.invokers) METHOD_NOT_AVAILABLE.set(response) return if not request.nodesValues: return assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker if not request.invoker.decodingsPath: return target = Target(arg=chain.arg, converter=request.converterPath) assert isinstance(target, TargetPath), 'Invalid target %s' % target for node, decoding in request.invoker.decodingsPath.items(): assert isinstance(decoding, Decoding), 'Invalid decoding %s' % decoding assert isinstance(decoding.doDecode, IDo), 'Invalid do decode %s' % decoding.doDecode decoding.doDecode(target, request.nodesValues[node]) if target.failures: PATH_ERROR.set(response) for type, values, messages in self.indexFailures(target.failures): addError(response, 'Expected type \'%(type)s\' instead of: %(values)s', messages, type=type, values=values)
def process(self, chain, requestCnt:RequestContent, response:ErrorResponseHTTP, **keyargs): ''' @see: HandlerProcessor.process Process the multi part data. ''' assert isinstance(requestCnt, RequestContent), 'Invalid request content %s' % requestCnt assert isinstance(response, ErrorResponseHTTP), 'Invalid response %s' % response if requestCnt.previousContent is None: return # If there is no previous content it means that this is not a multi part request content. multiCnt = requestCnt.previousContent assert isinstance(multiCnt, RequestContent), 'Invalid request content %s' % multiCnt if not multiCnt.type or not self._reMultipart.match(multiCnt.type): return assert log.debug('Content type %s is multi part form data', multiCnt.type) or True content, parameters = requestCnt, [] while True: if content.disposition != self.contentDisposition: MUTLIPART_ERROR.set(response) return addError(response, 'Invalid multipart form data content disposition \'%s\'' % content.disposition) name = content.dispositionAttr.pop(self.attrContentDispositionFile, None) if name is not None: content.name = name break name = content.dispositionAttr.pop(self.attrContentDispositionName, None) if not name: MUTLIPART_ERROR.set(response) return addError(response, 'Missing the content disposition header attribute name') parameters.append((name, str(content.source.read(), requestCnt.charSet))) content = content.doFetchNextContent() if not content: break assert isinstance(content, RequestContent), 'Invalid request content %s' % content if parameters: requestCnt.type = self.contentTypeUrlEncoded requestCnt.charSet = self.charSet requestCnt.doFetchNextContent = lambda: content requestCnt.source = BytesIO(urlencode(parameters).encode(self.charSet, 'replace'))
def process(self, chain, register: Register, request: Request, response: ErrorResponse, **keyargs): ''' @see: HandlerProcessor.process Parse the request object. ''' assert isinstance(register, Register), 'Invalid register %s' % register assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, ErrorResponse), 'Invalid response %s' % response if response.isSuccess is not False: return # Not in error. if not response.code: return definitions = None if request.invoker: assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker if request.invoker.definitions: definitions = request.invoker.definitions if register.definitions: if definitions is None: definitions = register.definitions else: definitions = itertools.chain(definitions, register.definitions) if definitions is None: return # No definitions to process. for code, verifier, messages in self.errors: if code != response.code: continue verified, unverified = [], [] for defin in definitions: assert isinstance(verifier, IVerifier), 'Invalid verifier %s' % verifier if verifier.isValid(defin): verified.append(defin) else: unverified.append(defin) if verified: addError(response, messages, verified) definitions = unverified
def process(self, chain, request:Request, response:Response, Target:TargetPath, **keyargs): ''' Provide the invoker based on the request method to be used in getting the data for the response. ''' assert isinstance(chain, Chain), 'Invalid chain %s' % chain assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance(response, Response), 'Invalid response %s' % response assert issubclass(Target, TargetPath), 'Invalid target class %s' % Target if response.isSuccess is False: return # Skip in case the response is in error assert isinstance(request.node, Node), 'Invalid request node %s' % request.node assert isinstance(request.node.invokers, dict) and request.node.invokers, \ 'Invalid request node invokers %s' % request.node.invokers request.invoker = request.node.invokers.get(request.method) if request.invoker is None: if response.allows is None: response.allows = set() response.allows.update(request.node.invokers) METHOD_NOT_AVAILABLE.set(response) return if not request.nodesValues: return assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker if not request.invoker.decodingsPath: return target = Target(arg=chain.arg, converter=request.converterPath) assert isinstance(target, TargetPath), 'Invalid target %s' % target for node, decoding in request.invoker.decodingsPath.items(): assert isinstance(decoding, Decoding), 'Invalid decoding %s' % decoding assert isinstance(decoding.doDecode, IDo), 'Invalid do decode %s' % decoding.doDecode decoding.doDecode(target, request.nodesValues[node]) if target.failures: PATH_ERROR.set(response) for type, values, messages in self.indexFailures(target.failures): addError(response, 'Expected type \'%(type)s\' instead of: %(values)s', messages, type=type, values=values)
def process(self, chain, request:HeadersRequire, requestCnt:RequestContent, response:Response, **keyargs): ''' @see: HandlerProcessor.process Provides the content type decode for the request. ''' assert isinstance(requestCnt, RequestContent), 'Invalid request content %s' % requestCnt assert isinstance(response, Response), 'Invalid response %s' % response assert isinstance(request.headers, dict), 'Invalid headers %s' % request.headers value = CONTENT_DISPOSITION.decode(request) if value: if len(value) > 1: if response.isSuccess is False: return # Skip in case the response is in error HEADER_ERROR.set(response) response.text = 'Invalid \'%s\'' % CONTENT_DISPOSITION.name addError('Invalid value \'%(value)s\' for header \'%(header)s\', expected only one value entry', value=value, header=CONTENT_DISPOSITION.name) return value, attributes = value[0] requestCnt.disposition = value requestCnt.dispositionAttr = attributes if CONTENT_DISPOSITION_ATTR_FILENAME in attributes: requestCnt.name = attributes[CONTENT_DISPOSITION_ATTR_FILENAME]
def process(self, chain, request: Request, response: ErrorResponseHTTP, Target: TargetParameter, **keyargs): ''' Process the parameters into arguments. ''' assert isinstance(chain, Chain), 'Invalid chain %s' % chain assert isinstance(request, Request), 'Invalid request %s' % request assert issubclass(Target, TargetParameter), 'Invalid target class %s' % Target if response.isSuccess is False: return # Skip in case the response is in error if not request.invoker: return # No invoker available assert isinstance(request.invoker, Invoker), 'Invalid invoker %s' % request.invoker illegal = None decodings = request.invoker.decodingsParameter if not decodings: if request.parameters: illegal = set(name for name, value in request.parameters) else: assert isinstance(decodings, dict), 'Invalid decodings %s' % decodings target = Target(arg=chain.arg, converter=request.converterPath) assert isinstance(target, TargetParameter), 'Invalid target %s' % target visited = set() if request.parameters: for name, value in request.parameters: decoding = decodings.get(name) if decoding is None: if illegal is None: illegal = set() illegal.add(name) else: assert isinstance( decoding, Decoding ), 'Invalid decoding definition %s' % decoding assert isinstance( decoding.doDecode, IDo), 'Invalid do decode %s' % decoding.doDecode decoding.doDecode(target, value) visited.add(name) for name, decoding in decodings.items(): if name not in visited and decoding.doDefault: decoding.doDefault(target) if target.failures: PARAMETER_INVALID.set(response) for name, definitions, values, messages in self.indexFailures( target.failures): addError(response, messages, 'Invalid values \'%(values)s\' for \'%(name)s\'', definitions, name=name, values=values) if illegal: PARAMETER_ILLEGAL.set(response) addError(response, 'Unknown parameters %(parameters)s', parameters=sorted(illegal))
def process(self, chain, register:Register, request:Request, response:ErrorResponseHTTP, responseCnt:ResponseContent, **keyargs): ''' @see: HandlerProcessor.process Process the URI to a resource path. ''' assert isinstance(register, Register), 'Invalid register %s' % register assert isinstance(request, Request), 'Invalid required request %s' % request assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt if response.isSuccess is False: return # Skip in case the response is in error assert isinstance(request.uri, str), 'Invalid request URI %s' % request.uri paths = request.uri.split('/') i = paths[-1].rfind('.') if len(paths) > 0 else -1 if i < 0: clearExtension = True extension = None else: clearExtension = i == 0 extension = paths[-1][i + 1:].lower() paths[-1] = paths[-1][0:i] paths = [unquote(p) for p in paths] if not paths[-1]: paths.pop() if extension: if Request.extension in request: request.extension = extension responseCnt.type = request.extension node = register.root for k, path in enumerate(paths): assert isinstance(node, Node), 'Invalid node %s' % node if node.childByName: if path not in node.childByName: PATH_NOT_FOUND.set(response) addError(response, 'Unknown item \'%(item)s\', maybe you meant: %(paths)s', item=path, paths=['%s/%s/%s' % ('/'.join(paths[:k]), item, '/'.join(paths[k:])) for item in sorted(node.childByName)]) return node = node.childByName[path] continue if node.child: if Request.nodesValues in request: if request.nodesValues is None: request.nodesValues = {} request.nodesValues[node] = path node = node.child continue PATH_NOT_FOUND.set(response) addError(response, 'No more path items expected after \'%(path)s\'', path='/'.join(paths[:k])) return if not node.invokers: PATH_NOT_FOUND.set(response) if node.childByName: addError(response, 'Expected additional path items, maybe you meant: %(paths)s', paths=['%s/%s' % ('/'.join(paths), item) for item in sorted(node.childByName)]) else: addError(response, 'Expected a value path item') return if not clearExtension and node.hasMandatorySlash: # We need to check if the last path element is not a string property ant there might be confusion # with the extension MISSING_SLASH.set(response) addError(response, 'Unclear extension, you need to add a trailing slash to URI, something like: %(paths)s', paths=['%s/.%s' % ('/'.join(paths), extension), '%s.%s/' % ('/'.join(paths), extension)]) return assert log.debug('Found resource for URI %s', request.uri) or True PATH_FOUND.set(response) if Request.node in request: request.node = node
def process(self, chain, processing, request: Request, response: ErrorResponse, responseCnt: ResponseContent, **keyargs): ''' @see: HandlerBranching.process Create the render for the response object. ''' assert isinstance(chain, Chain), 'Invalid chain %s' % chain assert isinstance(processing, Processing), 'Invalid processing %s' % processing assert isinstance(request, Request), 'Invalid request %s' % request assert isinstance( responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt # Resolving the character set if responseCnt.charSet: try: codecs.lookup(responseCnt.charSet) except LookupError: responseCnt.charSet = None else: responseCnt.charSet = None if not responseCnt.charSet: if Request.accCharSets in request and request.accCharSets is not None: for charSet in request.accCharSets: try: codecs.lookup(charSet) except LookupError: continue responseCnt.charSet = charSet break if not responseCnt.charSet: responseCnt.charSet = self.charSetDefault resolved = False if responseCnt.type: if chain.branch(processing).execute(CONSUMED): if response.isSuccess is not False: ENCODING_UNKNOWN.set(response) addError( response, 'Content type \'%(type)s\' not supported for rendering', type=responseCnt.type) else: resolved = True if not resolved: # Adding None in case some encoder is configured as default. if Request.accTypes in request and request.accTypes is not None: contentTypes = itertools.chain(request.accTypes, self.contentTypeDefaults) else: contentTypes = self.contentTypeDefaults for contentType in contentTypes: responseCnt.type = contentType if not chain.branch(processing).execute(CONSUMED): break else: ENCODING_UNKNOWN.set(response) addError( response, 'There is no renderer available', 'This is more likely a setup issues since the default content types should have resolved the renderer' )
def process(self, chain, register: Register, request: Request, response: ErrorResponseHTTP, responseCnt: ResponseContent, **keyargs): ''' @see: HandlerProcessor.process Process the URI to a resource path. ''' assert isinstance(register, Register), 'Invalid register %s' % register assert isinstance(request, Request), 'Invalid required request %s' % request assert isinstance( responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt if response.isSuccess is False: return # Skip in case the response is in error assert isinstance(request.uri, str), 'Invalid request URI %s' % request.uri paths = request.uri.split('/') i = paths[-1].rfind('.') if len(paths) > 0 else -1 if i < 0: clearExtension = True extension = None else: clearExtension = i == 0 extension = paths[-1][i + 1:].lower() paths[-1] = paths[-1][0:i] paths = [unquote(p) for p in paths] if not paths[-1]: paths.pop() if extension: if Request.extension in request: request.extension = extension responseCnt.type = request.extension node = register.root for k, path in enumerate(paths): assert isinstance(node, Node), 'Invalid node %s' % node if node.childByName: if path not in node.childByName: PATH_NOT_FOUND.set(response) addError( response, 'Unknown item \'%(item)s\', maybe you meant: %(paths)s', item=path, paths=[ '%s/%s/%s' % ('/'.join(paths[:k]), item, '/'.join(paths[k:])) for item in sorted(node.childByName) ]) return node = node.childByName[path] continue if node.child: if Request.nodesValues in request: if request.nodesValues is None: request.nodesValues = {} request.nodesValues[node] = path node = node.child continue PATH_NOT_FOUND.set(response) addError(response, 'No more path items expected after \'%(path)s\'', path='/'.join(paths[:k])) return if not node.invokers: PATH_NOT_FOUND.set(response) if node.childByName: addError( response, 'Expected additional path items, maybe you meant: %(paths)s', paths=[ '%s/%s' % ('/'.join(paths), item) for item in sorted(node.childByName) ]) else: addError(response, 'Expected a value path item') return if not clearExtension and node.hasMandatorySlash: # We need to check if the last path element is not a string property ant there might be confusion # with the extension MISSING_SLASH.set(response) addError( response, 'Unclear extension, you need to add a trailing slash to URI, something like: %(paths)s', paths=[ '%s/.%s' % ('/'.join(paths), extension), '%s.%s/' % ('/'.join(paths), extension) ]) return assert log.debug('Found resource for URI %s', request.uri) or True PATH_FOUND.set(response) if Request.node in request: request.node = node