コード例 #1
0
ファイル: time_zone.py プロジェクト: cristidomsa/Ally-Py
    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)
コード例 #2
0
ファイル: parsing.py プロジェクト: cristidomsa/Ally-Py
    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)
コード例 #3
0
ファイル: error_input.py プロジェクト: cristidomsa/Ally-Py
 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))
コード例 #4
0
    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)
コード例 #5
0
    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()
コード例 #6
0
ファイル: parameter.py プロジェクト: cristidomsa/Ally-Py
    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))
コード例 #7
0
    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)
コード例 #8
0
    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'))
コード例 #9
0
    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
コード例 #10
0
ファイル: method_invoker.py プロジェクト: cristidomsa/Ally-Py
    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)
コード例 #11
0
    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]
コード例 #12
0
ファイル: parameter.py プロジェクト: cristidomsa/Ally-Py
    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))
コード例 #13
0
ファイル: uri.py プロジェクト: cristidomsa/Ally-Py
    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
コード例 #14
0
ファイル: rendering.py プロジェクト: cristidomsa/Ally-Py
    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'
                )
コード例 #15
0
    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