Exemplo n.º 1
0
    def _process(self, method):
        assert isinstance(method, str), 'Invalid method %s' % method
        proc = self.server.processing
        assert isinstance(proc, Processing), 'Invalid processing %s' % proc

        request, requestCnt = proc.ctx.request(), proc.ctx.requestCnt()
        assert isinstance(request, RequestHTTP), 'Invalid request %s' % request
        assert isinstance(
            requestCnt,
            RequestContentHTTP), 'Invalid request content %s' % requestCnt

        if RequestHTTP.clientIP in request:
            request.clientIP = self.client_address[0]
        url = urlparse(self.path)
        request.scheme, request.method = HTTP, method.upper()
        request.headers = dict(self.headers)
        request.uri = url.path.lstrip('/')
        request.parameters = parse_qsl(url.query, True, False)

        requestCnt.source = self.rfile

        chain = Chain(proc)
        chain.process(
            **proc.fillIn(request=request,
                          requestCnt=requestCnt,
                          response=proc.ctx.response(),
                          responseCnt=proc.ctx.responseCnt())).doAll()

        response, responseCnt = chain.arg.response, chain.arg.responseCnt
        assert isinstance(response,
                          ResponseHTTP), 'Invalid response %s' % response
        assert isinstance(
            responseCnt,
            ResponseContentHTTP), 'Invalid response content %s' % responseCnt

        if ResponseHTTP.headers in response and response.headers is not None:
            for name, value in response.headers.items():
                self.send_header(name, value)

        assert isinstance(
            response.status,
            int), 'Invalid response status code %s' % response.status
        if ResponseHTTP.text in response and response.text:
            text = response.text
        elif ResponseHTTP.code in response and response.code:
            text = response.code
        else:
            text = None
        self.send_response(response.status, text)
        self.end_headers()

        if ResponseContentHTTP.source in responseCnt and responseCnt.source is not None:
            if isinstance(responseCnt.source, IInputStream):
                source = readGenerator(responseCnt.source)
            else:
                source = responseCnt.source

            for bytes in source:
                self.wfile.write(bytes)
Exemplo n.º 2
0
    def __call__(self, context, respond):
        '''
        Process the WSGI call.
        '''
        assert isinstance(context, dict), 'Invalid context %s' % context
        assert callable(respond), 'Invalid respond callable %s' % respond

        responseHeaders = dict(self.defaultHeaders)
        path, scheme = context['PATH_INFO'], context['wsgi.url_scheme']
        if path.startswith('/'): path = path[1:]

        for regex, processing in self.pathProcessing:
            match = regex.match(path)
            if match:
                uriRoot = path[:match.end()]
                if not uriRoot.endswith('/'): uriRoot += '/'

                assert isinstance(processing, Processing), 'Invalid processing %s' % processing
                req, reqCnt = processing.contexts['request'](), processing.contexts['requestCnt']()
                rsp, rspCnt = processing.contexts['response'](), processing.contexts['responseCnt']()

                assert isinstance(req, RequestHTTP), 'Invalid request %s' % req
                assert isinstance(reqCnt, RequestContentHTTP), 'Invalid request content %s' % reqCnt
                assert isinstance(rsp, ResponseHTTP), 'Invalid response %s' % rsp
                assert isinstance(rspCnt, ResponseContentHTTP), 'Invalid response content %s' % rspCnt

                req.scheme, req.uriRoot, req.uri = scheme, uriRoot, path[match.end():]
                break
        else:
            respond('404 Not Found', list(responseHeaders.items()))
            return ()

        req.method = self.methods.get(context['REQUEST_METHOD'], self.methodUnknown)
        req.parameters = parse_qsl(context['QUERY_STRING'], True, False)
        prefix, prefixLen = self.headerPrefix, len(self.headerPrefix,)
        req.headers = {hname[prefixLen:].replace('_', '-'):hvalue
                       for hname, hvalue in context.items() if hname.startswith(prefix)}
        req.headers.update({hname.replace('_', '-'):hvalue
                            for hname, hvalue in context.items() if hname in self.headers})
        reqCnt.source = context.get('wsgi.input')

        Chain(processing).process(request=req, requestCnt=reqCnt, response=rsp, responseCnt=rspCnt).doAll()

        assert isinstance(rsp.code, Code), 'Invalid response code %s' % rsp.code

        responseHeaders.update(rsp.headers)
        if ResponseHTTP.text in rsp: status = '%s %s' % (rsp.code.code, rsp.text)
        else:
            text = self.responses.get(rsp.code.code)
            if text is not None: status = '%s %s' % (rsp.code.code, text[0])
            else: status = str(rsp.code.code)

        respond(status, list(responseHeaders.items()))

        if rspCnt.source is not None:
            if isinstance(rspCnt.source, IOutputStream): return readGenerator(rspCnt.source)
            return rspCnt.source
        return ()
Exemplo n.º 3
0
    def _process(self, method):
        url = urlparse(self.path)
        path = url.path.lstrip("/")

        for regex, processing in self.pathProcessing:
            match = regex.match(path)
            if match:
                uriRoot = path[: match.end()]
                if not uriRoot.endswith("/"):
                    uriRoot += "/"

                assert isinstance(processing, Processing), "Invalid processing %s" % processing
                req, reqCnt = processing.contexts["request"](), processing.contexts["requestCnt"]()
                rsp, rspCnt = processing.contexts["response"](), processing.contexts["responseCnt"]()
                chain = processing.newChain()

                assert isinstance(chain, Chain), "Invalid chain %s" % chain
                assert isinstance(req, RequestHTTP), "Invalid request %s" % req
                assert isinstance(reqCnt, RequestContentHTTP), "Invalid request content %s" % reqCnt
                assert isinstance(rsp, ResponseHTTP), "Invalid response %s" % rsp
                assert isinstance(rspCnt, ResponseContentHTTP), "Invalid response content %s" % rspCnt

                req.scheme, req.uriRoot, req.uri = "http", uriRoot, path[match.end() :]
                req.parameters = parse_qsl(url.query, True, False)
                break
        else:
            self.send_response(404)
            self.end_headers()
            return

        req.method = method
        req.headers = dict(self.headers)
        reqCnt.source = self.rfile

        chain.process(request=req, requestCnt=reqCnt, response=rsp, responseCnt=rspCnt)

        assert isinstance(rsp.code, Code), "Invalid response code %s" % rsp.code

        if ResponseHTTP.headers in rsp:
            for name, value in rsp.headers.items():
                self.send_header(name, value)

        if ResponseHTTP.text in rsp:
            self.send_response(rsp.code.code, rsp.text)
        else:
            self.send_response(rsp.code.code)

        self.end_headers()

        if rspCnt.source is not None:
            if isinstance(rspCnt.source, IOutputStream):
                source = readGenerator(rspCnt.source)
            else:
                source = rspCnt.source

            for bytes in source:
                self.wfile.write(bytes)
Exemplo n.º 4
0
    def process(self, chain, request:Request, response:Response, responseCnt:ResponseContent, **keyargs):
        '''
        @see: HandlerProcessor.process
        
        Provide the file content as a response.
        '''
        assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain
        assert isinstance(request, Request), 'Invalid request %s' % request
        assert isinstance(response, Response), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt

        if request.method != GET:
            response.allows |= GET
            response.code, response.text = METHOD_NOT_AVAILABLE, 'Path only available for GET'
            chain.proceed()
            return

        # Make sure the given path points inside the repository
        entryPath = normOSPath(join(self.repositoryPath, normZipPath(unquote(request.uri))))
        if not entryPath.startswith(self.repositoryPath):
            response.code, response.text = RESOURCE_NOT_FOUND, 'Out of repository path'
            chain.proceed()
            return

        # Initialize the read file handler with None value
        # This will be set upon successful file open
        rf = None
        if isfile(entryPath):
            rf = open(entryPath, 'rb')
        else:
            linkPath = entryPath
            while len(linkPath) > len(self.repositoryPath):
                if isfile(linkPath + self._linkExt):
                    with open(linkPath + self._linkExt) as f: links = json.load(f)
                    subPath = normOSPath(entryPath[len(linkPath):]).lstrip(sep)
                    for linkType, *data in links:
                        if linkType in self._linkTypes:
                            # make sure the subpath is normalized and uses the OS separator
                            if not self._isPathDeleted(join(linkPath, subPath)):
                                rf = self._linkTypes[linkType](subPath, *data)
                                if rf is not None: break
                    break
                subLinkPath = dirname(linkPath)
                if subLinkPath == linkPath:
                    break
                linkPath = subLinkPath

        if rf is None:
            response.code, response.text = METHOD_NOT_AVAILABLE, 'Invalid content resource'
            chain.proceed()
            return

        response.code = RESOURCE_FOUND
        responseCnt.source = readGenerator(rf)
Exemplo n.º 5
0
    def __call__(self, context, respond):
        '''
        Process the WSGI call.
        '''
        assert isinstance(context, dict), 'Invalid context %s' % context
        assert callable(respond), 'Invalid respond callable %s' % respond
        
        proc = self.processing
        assert isinstance(proc, Processing), 'Invalid processing %s' % proc
        
        request, requestCnt = proc.ctx.request(), proc.ctx.requestCnt()
        assert isinstance(request, RequestHTTP), 'Invalid request %s' % request
        assert isinstance(requestCnt, RequestContentHTTP), 'Invalid request content %s' % requestCnt

        if RequestHTTP.clientIP in request:
            request.clientIP = context.get('HTTP_X_FORWARDED_FOR')
            if request.clientIP: request.clientIP = request.clientIP.split(',')[-1].strip()
            else: request.clientIP = context.get('REMOTE_ADDR')

        request.scheme, request.method = context.get('wsgi.url_scheme', '').upper(), context.get('REQUEST_METHOD', '').upper()
        request.uri = context.get('PATH_INFO', '').lstrip('/')
        if RequestHTTP.headers in request:
            request.headers = {}
            for hname, hvalue in context.items():
                if hname.startswith(self.headerPrefix):
                    request.headers[hname[self.headerPrefixLen:].replace('_', '-')] = hvalue
                elif hname in self.headers:
                    request.headers[hname.replace('_', '-')] = hvalue
        if RequestHTTP.parameters in request: request.parameters = parse_qsl(context.get('QUERY_STRING', ''), True, False)

        if RequestContentHTTP.source in requestCnt: requestCnt.source = context.get('wsgi.input')

        arg = proc.execute(FILL_ALL, request=request, requestCnt=requestCnt)
        response, responseCnt = arg.response, arg.responseCnt
        assert isinstance(response, ResponseHTTP), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContentHTTP), 'Invalid response content %s' % responseCnt

        responseHeaders = dict(self.defaultHeaders)
        if ResponseHTTP.headers in response and response.headers is not None: responseHeaders.update(response.headers)
        
        assert isinstance(response.status, int), 'Invalid response status code %s' % response.status
        if ResponseHTTP.text in response and response.text: status = '%s %s' % (response.status, response.text)
        elif ResponseHTTP.code in response and response.code: status = '%s %s' % (response.status, response.code)
        else: status = str(response.status)
        respond(status, list(responseHeaders.items()))

        if ResponseContentHTTP.source in responseCnt and responseCnt.source is not None:
            if isinstance(responseCnt.source, IInputStream): return readGenerator(responseCnt.source)
            return responseCnt.source
        return ()
Exemplo n.º 6
0
    def default(self, *vpath, **params):
        request, response = cherrypy.request, cherrypy.response
        path = '/'.join(vpath)

        for regex, processing in self.pathProcessing:
            match = regex.match(path)
            if match:
                uriRoot = path[:match.end()]
                if not uriRoot.endswith('/'): uriRoot += '/'

                assert isinstance(processing, Processing), 'Invalid processing %s' % processing
                req, reqCnt = processing.contexts['request'](), processing.contexts['requestCnt']()
                rsp, rspCnt = processing.contexts['response'](), processing.contexts['responseCnt']()
                chain = processing.newChain()

                assert isinstance(chain, Chain), 'Invalid chain %s' % chain
                assert isinstance(req, RequestHTTP), 'Invalid request %s' % req
                assert isinstance(reqCnt, RequestContentHTTP), 'Invalid request content %s' % reqCnt
                assert isinstance(rsp, ResponseHTTP), 'Invalid response %s' % rsp
                assert isinstance(rspCnt, ResponseContentHTTP), 'Invalid response content %s' % rspCnt

                req.scheme, req.uriRoot, req.uri = 'http', uriRoot, path[match.end():]
                break
        else:
            raise cherrypy.HTTPError(404)

        req.method = self.methods.get(request.method, self.methodUnknown)
        req.headers = request.headers
        reqCnt.source = request.rfile

        parameters = []
        for name, value in params.items():
            if isinstance(value, list): parameters.extend([(name, v) for v in value])
            else: parameters.append((name, value))
        req.parameters = parameters

        chain.process(request=req, requestCnt=reqCnt, response=rsp, responseCnt=rspCnt)

        assert isinstance(rsp.code, Code), 'Invalid response code %s' % rsp.code

        response.headers.pop('Content-Type', None)
        response.headers['Server'] = self.serverVersion
        response.headers.update(rsp.headers)
        if ResponseHTTP.text in rsp: response.status = '%s %s' % (rsp.code.code, rsp.text)
        else: response.status = str(rsp.code.code)

        if isinstance(rsp.source, IOutputStream): return readGenerator(rsp.source)
        return rspCnt.source
Exemplo n.º 7
0
def processGet(pathProcessing, headers, url):
    '''
    @see: process
    Process the GET and reads the response stream.
    '''
    _req, _reqCnt, rsp, rspCnt = process(pathProcessing, GET, headers, url, None)
    
    assert isinstance(rsp, ResponseHTTP), 'Invalid response %s' % rsp
    assert isinstance(rspCnt, ResponseContentHTTP), 'Invalid response content %s' % rspCnt
    assert isinstance(rsp.code, Code), 'Invalid response code %s' % rsp.code
    if not rsp.code.isSuccess: raise Exception('Bad response \'%s\' %s' % (rsp.code.code, rsp.text))

    if rspCnt.source is not None:
        if isinstance(rspCnt.source, IInputStream): source = readGenerator(rspCnt.source)
        else: source = rspCnt.source

        for bytes in source: pass  # Just the consume the stream
Exemplo n.º 8
0
     def respond():
         assert isinstance(rsp.code, int), 'Invalid response code %s' % rsp.code
 
         if ResponseHTTP.headers in rsp:
             for name, value in rsp.headers.items(): self.send_header(name, value)
 
         if ResponseHTTP.text in rsp: self.send_response(rsp.code, rsp.text)
         else: self.send_response(rsp.code)
 
         self.end_headers()
 
         if rspCnt.source is not None:
             if isinstance(rspCnt.source, IInputStream): source = readGenerator(rspCnt.source, self.bufferSize)
             else: source = rspCnt.source
 
             self._writeq.append((WRITE_ITER, iter(source)))
         self._writeq.append((WRITE_CLOSE, None))
Exemplo n.º 9
0
    def _process(self, method):
        url = urlparse(self.path)
        path = url.path.lstrip('/')
        for regex, processing in self.server.pathProcessing:
            match = regex.match(path)
            if match:
                uriRoot = path[:match.end()]
                if not uriRoot.endswith('/'): uriRoot += '/'

                assert isinstance(processing, Processing), 'Invalid processing %s' % processing
                req, reqCnt = processing.contexts['request'](), processing.contexts['requestCnt']()
                rsp, rspCnt = processing.contexts['response'](), processing.contexts['responseCnt']()

                assert isinstance(req, RequestHTTP), 'Invalid request %s' % req
                assert isinstance(reqCnt, RequestContentHTTP), 'Invalid request content %s' % reqCnt
                assert isinstance(rsp, ResponseHTTP), 'Invalid response %s' % rsp
                assert isinstance(rspCnt, ResponseContentHTTP), 'Invalid response content %s' % rspCnt

                req.scheme, req.uriRoot, req.uri = 'http', uriRoot, path[match.end():]
                req.parameters = parse_qsl(url.query, True, False)
                break
        else:
            self.send_response(404)
            self.end_headers()
            return

        req.methodName = method
        req.headers = dict(self.headers)
        reqCnt.source = self.rfile

        Chain(processing).process(request=req, requestCnt=reqCnt, response=rsp, responseCnt=rspCnt).doAll()

        assert isinstance(rsp.code, int), 'Invalid response code %s' % rsp.code
        if ResponseHTTP.headers in rsp:
            for name, value in rsp.headers.items(): self.send_header(name, value)

        if ResponseHTTP.text in rsp: self.send_response(rsp.code, rsp.text)
        else: self.send_response(rsp.code)

        self.end_headers()

        if rspCnt.source is not None:
            if isinstance(rspCnt.source, IInputStream): source = readGenerator(rspCnt.source)
            else: source = rspCnt.source

            for bytes in source: self.wfile.write(bytes)
Exemplo n.º 10
0
 def process(self, chain, response:HeadersDefines, responseCnt:ResponseContent, **keyargs):
     '''
     @see: HandlerProcessor.process
     
     Encodes the content length.
     '''
     assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt
     
     if responseCnt.source is None: return  # No content to chunck.
     CONTENT_LENGTH.remove(response)
     # We make sure that no content length is not on the headers since this will create a conflict.
     
     TRANSFER_ENCODING.put(response, TRANSFER_ENCODING_CHUNKED)
     if isinstance(responseCnt.source, IInputStream):
         responseCnt.source = self.chuncks(readGenerator(responseCnt.source, self.maximumChunkSize))
     else:
         assert isinstance(responseCnt.source, Iterable), 'Invalid source %s' % responseCnt.source
         responseCnt.source = self.chuncks(responseCnt.source)
Exemplo n.º 11
0
    def process(self, chain, response:Response, responseCnt:ResponseContent, **keyargs):
        '''
        @see: HandlerProcessor.process
        
        Provides the additional arguments by type to be populated.
        '''
        assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain
        assert isinstance(response, Response), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt

        error = None
        try:
            try:
                chain.process(response=response, responseCnt=responseCnt, **keyargs)
                # We process the chain internally so we might cache any exception.
            except DevelError as e:
                response.code, response.text, response.errorMessage = BAD_CONTENT, 'Development error', str(e)
                chain.process(response=response, responseCnt=responseCnt, **keyargs)
                # We try to process now the chain (where it left of) with the exception set.
        except:
            log.exception('Exception occurred while processing the chain')
            error = StringIO()
            traceback.print_exc(file=error)
        else:
            if __debug__ and isinstance(responseCnt.source, Iterable):
                # If in debug mode and the response content has a source generator then we will try to read that
                # in order to catch any exception before the actual streaming.
                content = BytesIO()
                try:
                    for bytes in responseCnt.source: content.write(bytes)
                except:
                    log.exception('Exception occurred while processing the chain')
                    error = StringIO()
                    traceback.print_exc(file=error)
                else:
                    content.seek(0)
                    responseCnt.source = readGenerator(content)

        if error is not None:
            response.code = INTERNAL_ERROR
            response.text = 'Upps, please consult the server logs'
            response.headers = self.errorHeaders
            responseCnt.source = convertToBytes(self.errorResponse(error), 'utf8', 'backslashreplace')
Exemplo n.º 12
0
    def _process(self, method):
        assert isinstance(method, str), 'Invalid method %s' % method
        proc = self.server.processing
        assert isinstance(proc, Processing), 'Invalid processing %s' % proc
        
        request, requestCnt = proc.ctx.request(), proc.ctx.requestCnt()
        assert isinstance(request, RequestHTTP), 'Invalid request %s' % request
        assert isinstance(requestCnt, RequestContentHTTP), 'Invalid request content %s' % requestCnt

        if RequestHTTP.clientIP in request: request.clientIP = self.client_address[0]
        url = urlparse(self.path)
        request.scheme, request.method = HTTP, method.upper()
        request.headers = dict(self.headers)
        request.uri = url.path.lstrip('/')
        request.parameters = parse_qsl(url.query, True, False)
        
        requestCnt.source = self.rfile

        chain = Chain(proc)
        chain.process(**proc.fillIn(request=request, requestCnt=requestCnt,
                                    response=proc.ctx.response(), responseCnt=proc.ctx.responseCnt())).doAll()

        response, responseCnt = chain.arg.response, chain.arg.responseCnt
        assert isinstance(response, ResponseHTTP), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContentHTTP), 'Invalid response content %s' % responseCnt

        if ResponseHTTP.headers in response and response.headers is not None:
            for name, value in response.headers.items(): self.send_header(name, value)

        assert isinstance(response.status, int), 'Invalid response status code %s' % response.status
        if ResponseHTTP.text in response and response.text: text = response.text
        elif ResponseHTTP.code in response and response.code: text = response.code
        else: text = None
        self.send_response(response.status, text)
        self.end_headers()

        if ResponseContentHTTP.source in responseCnt and responseCnt.source is not None:
            if isinstance(responseCnt.source, IInputStream): source = readGenerator(responseCnt.source)
            else: source = responseCnt.source

            for bytes in source: self.wfile.write(bytes)
Exemplo n.º 13
0
     def respond():
         response, responseCnt = chain.arg.response, chain.arg.responseCnt
         assert isinstance(response, ResponseHTTP), 'Invalid response %s' % response
         assert isinstance(responseCnt, ResponseContentHTTP), 'Invalid response content %s' % responseCnt
 
         if ResponseHTTP.headers in response and response.headers is not None:
             for name, value in response.headers.items(): self.send_header(name, value)
 
         assert isinstance(response.status, int), 'Invalid response status code %s' % response.status
         if ResponseHTTP.text in response and response.text: text = response.text
         elif ResponseHTTP.code in response and response.code: text = response.code
         else: text = None
         self.send_response(response.status, text)
         self.end_headers()
 
         if ResponseContentHTTP.source in responseCnt and responseCnt.source is not None:
             if isinstance(responseCnt.source, IInputStream): source = readGenerator(responseCnt.source, self.bufferSize)
             else: source = responseCnt.source
             self._writeq.append((WRITE_ITER, iter(source)))
             
         self._writeq.append((WRITE_CLOSE, None))
Exemplo n.º 14
0
def processGet(pathProcessing, headers, url):
    '''
    @see: process
    Process the GET and reads the response stream.
    '''
    _req, _reqCnt, rsp, rspCnt = process(pathProcessing, GET, headers, url,
                                         None)

    assert isinstance(rsp, ResponseHTTP), 'Invalid response %s' % rsp
    assert isinstance(
        rspCnt, ResponseContentHTTP), 'Invalid response content %s' % rspCnt
    assert isinstance(rsp.code, Code), 'Invalid response code %s' % rsp.code
    if not rsp.code.isSuccess:
        raise Exception('Bad response \'%s\' %s' % (rsp.code.code, rsp.text))

    if rspCnt.source is not None:
        if isinstance(rspCnt.source, IOutputStream):
            source = readGenerator(rspCnt.source)
        else:
            source = rspCnt.source

        for bytes in source:
            pass  # Just the consume the stream
Exemplo n.º 15
0
    def __call__(self, context, respond):
        """
        Process the WSGI call.
        """
        assert isinstance(context, dict), "Invalid context %s" % context
        assert callable(respond), "Invalid respond callable %s" % respond

        responseHeaders = dict(self.defaultHeaders)
        path, scheme = context["PATH_INFO"], context["wsgi.url_scheme"]
        if path.startswith("/"):
            path = path[1:]

        for regex, processing in self.pathProcessing:
            match = regex.match(path)
            if match:
                uriRoot = path[: match.end()]
                if not uriRoot.endswith("/"):
                    uriRoot += "/"

                assert isinstance(processing, Processing), "Invalid processing %s" % processing
                req, reqCnt = processing.contexts["request"](), processing.contexts["requestCnt"]()
                rsp, rspCnt = processing.contexts["response"](), processing.contexts["responseCnt"]()

                assert isinstance(req, RequestHTTP), "Invalid request %s" % req
                assert isinstance(reqCnt, RequestContentHTTP), "Invalid request content %s" % reqCnt
                assert isinstance(rsp, ResponseHTTP), "Invalid response %s" % rsp
                assert isinstance(rspCnt, ResponseContentHTTP), "Invalid response content %s" % rspCnt

                req.scheme, req.uriRoot, req.uri = scheme, uriRoot, path[match.end() :]
                break
        else:
            respond("404 Not Found", list(responseHeaders.items()))
            return ()

        method = context["REQUEST_METHOD"]
        if method:
            method = method.upper()
            if method not in METHODS:
                method = METHOD_UNKNOWN
        else:
            method = METHOD_UNKNOWN

        req.methodName = method
        req.parameters = parse_qsl(context["QUERY_STRING"], True, False)
        prefix, prefixLen = self.headerPrefix, len(self.headerPrefix)
        req.headers = {
            hname[prefixLen:].replace("_", "-"): hvalue for hname, hvalue in context.items() if hname.startswith(prefix)
        }
        req.headers.update(
            {hname.replace("_", "-"): hvalue for hname, hvalue in context.items() if hname in self.headers}
        )
        reqCnt.source = context.get("wsgi.input")

        Chain(processing).process(request=req, requestCnt=reqCnt, response=rsp, responseCnt=rspCnt).doAll()

        assert isinstance(rsp.code, int), "Invalid response code %s" % rsp.code

        responseHeaders.update(rsp.headers)
        if ResponseHTTP.text in rsp:
            status = "%s %s" % (rsp.code, rsp.text)
        else:
            text = self.responses.get(rsp.code)
            if text is not None:
                status = "%s %s" % (rsp.code, text[0])
            else:
                status = str(rsp.code)

        respond(status, list(responseHeaders.items()))

        if rspCnt.source is not None:
            if isinstance(rspCnt.source, IInputStream):
                return readGenerator(rspCnt.source)
            return rspCnt.source
        return ()
Exemplo n.º 16
0
    def __call__(self, context, respond):
        '''
        Process the WSGI call.
        '''
        assert isinstance(context, dict), 'Invalid context %s' % context
        assert callable(respond), 'Invalid respond callable %s' % respond

        proc = self.processing
        assert isinstance(proc, Processing), 'Invalid processing %s' % proc

        request, requestCnt = proc.ctx.request(), proc.ctx.requestCnt()
        assert isinstance(request, RequestHTTP), 'Invalid request %s' % request
        assert isinstance(
            requestCnt,
            RequestContentHTTP), 'Invalid request content %s' % requestCnt

        if RequestHTTP.clientIP in request:
            request.clientIP = context.get('HTTP_X_FORWARDED_FOR')
            if request.clientIP:
                request.clientIP = request.clientIP.split(',')[-1].strip()
            else:
                request.clientIP = context.get('REMOTE_ADDR')

        request.scheme, request.method = context.get('wsgi.url_scheme',
                                                     '').upper(), context.get(
                                                         'REQUEST_METHOD',
                                                         '').upper()
        request.uri = context.get('PATH_INFO', '').lstrip('/')
        if RequestHTTP.headers in request:
            request.headers = {}
            for hname, hvalue in context.items():
                if hname.startswith(self.headerPrefix):
                    request.headers[hname[self.headerPrefixLen:].replace(
                        '_', '-')] = hvalue
                elif hname in self.headers:
                    request.headers[hname.replace('_', '-')] = hvalue
        if RequestHTTP.parameters in request:
            request.parameters = parse_qsl(context.get('QUERY_STRING', ''),
                                           True, False)

        if RequestContentHTTP.source in requestCnt:
            requestCnt.source = context.get('wsgi.input')

        arg = proc.execute(FILL_ALL, request=request, requestCnt=requestCnt)
        response, responseCnt = arg.response, arg.responseCnt
        assert isinstance(response,
                          ResponseHTTP), 'Invalid response %s' % response
        assert isinstance(
            responseCnt,
            ResponseContentHTTP), 'Invalid response content %s' % responseCnt

        responseHeaders = dict(self.defaultHeaders)
        if ResponseHTTP.headers in response and response.headers is not None:
            responseHeaders.update(response.headers)

        assert isinstance(
            response.status,
            int), 'Invalid response status code %s' % response.status
        if ResponseHTTP.text in response and response.text:
            status = '%s %s' % (response.status, response.text)
        elif ResponseHTTP.code in response and response.code:
            status = '%s %s' % (response.status, response.code)
        else:
            status = str(response.status)
        respond(status, list(responseHeaders.items()))

        if ResponseContentHTTP.source in responseCnt and responseCnt.source is not None:
            if isinstance(responseCnt.source, IInputStream):
                return readGenerator(responseCnt.source)
            return responseCnt.source
        return ()