Пример #1
0
 def test_parse_chunked_data(self):
     # See: https://en.wikipedia.org/wiki/Chunked_transfer_encoding
     chunked = '4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n'
     expected = 'Wikipedia in\r\n\r\nchunks.'
     parsed = parse_chunked_data(chunked)
     self.assertEqual(parsed.strip(), expected.strip())
Пример #2
0
def invoke_function(function):
    """ Invoke an existing function
        ---
        operationId: 'invokeFunction'
        parameters:
            - name: 'request'
              in: body
    """
    # function here can either be an arn or a function name
    arn = func_arn(function)

    # arn can also contain a qualifier, extract it from there if so
    m = re.match('(arn:aws:lambda:.*:.*:function:[a-zA-Z0-9-_]+)(:.*)?', arn)
    if m and m.group(2):
        qualifier = m.group(2)[1:]
        arn = m.group(1)
    else:
        qualifier = request.args.get('Qualifier')

    if arn not in arn_to_lambda:
        return error_response('Function does not exist: %s' % arn, 404, error_type='ResourceNotFoundException')
    if qualifier and not arn_to_lambda.get(arn).qualifier_exists(qualifier):
        return error_response('Function does not exist: {0}:{1}'.format(arn, qualifier), 404,
                              error_type='ResourceNotFoundException')
    data = request.get_data()
    if data:
        data = to_str(data)
        try:
            data = json.loads(data)
        except Exception:
            try:
                # try to read chunked content
                data = json.loads(parse_chunked_data(data))
            except Exception:
                return error_response('The payload is not JSON: %s' % data, 415,
                                      error_type='UnsupportedMediaTypeException')

    # Default invocation type is RequestResponse
    invocation_type = request.environ.get('HTTP_X_AMZ_INVOCATION_TYPE', 'RequestResponse')

    def _create_response(result, status_code=200):
        """ Create the final response for the given invocation result """
        if isinstance(result, Response):
            return result
        details = {
            'StatusCode': status_code,
            'Payload': result,
            'Headers': {}
        }
        if isinstance(result, dict):
            for key in ('StatusCode', 'Payload', 'FunctionError'):
                if result.get(key):
                    details[key] = result[key]
        # Try to parse parse payload as JSON
        payload = details['Payload']
        if payload and isinstance(payload, (str, bytes)) and payload[0] in ('[', '{'):
            try:
                details['Payload'] = json.loads(details['Payload'])
            except Exception:
                pass
        # Set error headers
        if details.get('FunctionError'):
            details['Headers']['X-Amz-Function-Error'] = str(details['FunctionError'])
        # Construct response object
        response_obj = details['Payload']
        if isinstance(response_obj, (dict, list, bool)) or is_number(response_obj):
            # Assume this is a JSON response
            response_obj = jsonify(response_obj)
        else:
            response_obj = str(response_obj)
            details['Headers']['Content-Type'] = 'text/plain'
        return response_obj, details['StatusCode'], details['Headers']

    if invocation_type == 'RequestResponse':
        result = run_lambda(asynchronous=False, func_arn=arn, event=data, context={}, version=qualifier)
        return _create_response(result)
    elif invocation_type == 'Event':
        run_lambda(asynchronous=True, func_arn=arn, event=data, context={}, version=qualifier)
        return _create_response('', status_code=202)
    elif invocation_type == 'DryRun':
        # Assume the dry run always passes.
        return _create_response('', status_code=204)
    return error_response('Invocation type not one of: RequestResponse, Event or DryRun',
                          code=400, error_type='InvalidParameterValueException')
Пример #3
0
def invoke_function(function):
    """ Invoke an existing function
        ---
        operationId: 'invokeFunction'
        parameters:
            - name: 'request'
              in: body
    """
    # function here can either be an arn or a function name
    arn = func_arn(function)

    # arn can also contain a qualifier, extract it from there if so
    m = re.match('(arn:aws:lambda:.*:.*:function:[a-zA-Z0-9-_]+)(:.*)?', arn)
    if m and m.group(2):
        qualifier = m.group(2)[1:]
        arn = m.group(1)
    else:
        qualifier = request.args.get('Qualifier')

    if arn not in arn_to_lambda:
        return error_response('Function does not exist: %s' % arn,
                              404,
                              error_type='ResourceNotFoundException')
    if qualifier and not arn_to_lambda.get(arn).qualifier_exists(qualifier):
        return error_response('Function does not exist: {0}:{1}'.format(
            arn, qualifier),
                              404,
                              error_type='ResourceNotFoundException')
    data = request.get_data()
    if data:
        data = to_str(data)
        try:
            data = json.loads(data)
        except Exception:
            try:
                # try to read chunked content
                data = json.loads(parse_chunked_data(data))
            except Exception:
                return error_response(
                    'The payload is not JSON: %s' % data,
                    415,
                    error_type='UnsupportedMediaTypeException')

    # Default invocation type is RequestResponse
    invocation_type = request.environ.get('HTTP_X_AMZ_INVOCATION_TYPE',
                                          'RequestResponse')

    if invocation_type == 'RequestResponse':
        result = run_lambda(asynchronous=False,
                            func_arn=arn,
                            event=data,
                            context={},
                            version=qualifier)
        if isinstance(result, dict):
            return jsonify(result)
        if result:
            return result
        return make_response('', 200)
    elif invocation_type == 'Event':
        run_lambda(asynchronous=True,
                   func_arn=arn,
                   event=data,
                   context={},
                   version=qualifier)
        return make_response('', 202)
    elif invocation_type == 'DryRun':
        # Assume the dry run always passes.
        return make_response('', 204)
    else:
        return error_response(
            'Invocation type not one of: RequestResponse, Event or DryRun',
            code=400,
            error_type='InvalidParameterValueException')