예제 #1
0
    def extract_cors(self, cors_prop):
        """
        Extract Cors property from AWS::Serverless::Api resource by reading and parsing Swagger documents. The result
        is added to the Api.

        Parameters
        ----------
        cors_prop : dict
            Resource properties for Cors
        """
        cors = None
        if cors_prop and isinstance(cors_prop, dict):
            allow_methods = cors_prop.get("AllowMethods", ','.join(sorted(Route.ANY_HTTP_METHODS)))
            allow_methods = self.normalize_cors_allow_methods(allow_methods)
            cors = Cors(
                allow_origin=cors_prop.get("AllowOrigin"),
                allow_methods=allow_methods,
                allow_headers=cors_prop.get("AllowHeaders"),
                max_age=cors_prop.get("MaxAge")
            )
        elif cors_prop and isinstance(cors_prop, string_types):
            cors = Cors(
                allow_origin=cors_prop,
                allow_methods=','.join(sorted(Route.ANY_HTTP_METHODS)),
                allow_headers=None,
                max_age=None
            )
        return cors
예제 #2
0
    def test_empty_elements(self):
        cors = Cors(allow_origin="www.domain.com", allow_methods=",".join(["GET", "POST", "OPTIONS"]))
        headers = Cors.cors_to_headers(cors)

        self.assertEqual(
            headers,
            {"Access-Control-Allow-Origin": "www.domain.com", "Access-Control-Allow-Methods": "GET,POST,OPTIONS"},
        )
    def test_empty_elements(self):
        cors = Cors(allow_origin="www.domain.com",
                    allow_methods=','.join(["GET", "POST", "OPTIONS"]))
        headers = Cors.cors_to_headers(cors)

        self.assertEquals(
            headers, {
                'Access-Control-Allow-Origin': 'www.domain.com',
                'Access-Control-Allow-Methods': 'GET,POST,OPTIONS'
            })
    def test_basic_conversion(self):
        cors = Cors(allow_origin="*",
                    allow_methods=','.join(["POST", "OPTIONS"]),
                    allow_headers="UPGRADE-HEADER",
                    max_age=6)
        headers = Cors.cors_to_headers(cors)

        self.assertEquals(
            headers, {
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Methods': 'POST,OPTIONS',
                'Access-Control-Allow-Headers': 'UPGRADE-HEADER',
                'Access-Control-Max-Age': 6
            })
예제 #5
0
    def test_basic_conversion(self):
        cors = Cors(
            allow_origin="*", allow_methods=",".join(["POST", "OPTIONS"]), allow_headers="UPGRADE-HEADER", max_age=6
        )
        headers = Cors.cors_to_headers(cors)

        self.assertEqual(
            headers,
            {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "POST,OPTIONS",
                "Access-Control-Allow-Headers": "UPGRADE-HEADER",
                "Access-Control-Max-Age": 6,
            },
        )
예제 #6
0
    def extract_cors(self, cors_prop):
        """
        Extract Cors property from AWS::Serverless::Api resource by reading and parsing Swagger documents. The result
        is added to the Api.

        Parameters
        ----------
        cors_prop : dict
            Resource properties for Cors
        """
        cors = None
        if cors_prop and isinstance(cors_prop, dict):
            allow_methods = self._get_cors_prop(cors_prop, "AllowMethods")
            if allow_methods:
                allow_methods = self.normalize_cors_allow_methods(allow_methods)
            else:
                allow_methods = ",".join(sorted(Route.ANY_HTTP_METHODS))

            allow_origin = self._get_cors_prop(cors_prop, "AllowOrigin")
            allow_headers = self._get_cors_prop(cors_prop, "AllowHeaders")
            max_age = self._get_cors_prop(cors_prop, "MaxAge")

            cors = Cors(
                allow_origin=allow_origin, allow_methods=allow_methods, allow_headers=allow_headers, max_age=max_age
            )
        elif cors_prop and isinstance(cors_prop, string_types):
            allow_origin = cors_prop
            if not (allow_origin.startswith("'") and allow_origin.endswith("'")):
                raise InvalidSamDocumentException(
                    "Cors Properties must be a quoted string " '(i.e. "\'*\'" is correct, but "*" is not).'
                )
            allow_origin = allow_origin.strip("'")

            cors = Cors(
                allow_origin=allow_origin,
                allow_methods=",".join(sorted(Route.ANY_HTTP_METHODS)),
                allow_headers=None,
                max_age=None,
            )
        return cors
예제 #7
0
    def _request_handler(self, **kwargs):
        """
        We handle all requests to the host:port. The general flow of handling a request is as follows

        * Fetch request from the Flask Global state. This is where Flask places the request and is per thread so
          multiple requests are still handled correctly
        * Find the Lambda function to invoke by doing a look up based on the request.endpoint and method
        * If we don't find the function, we will throw a 502 (just like the 404 and 405 responses we get
          from Flask.
        * Since we found a Lambda function to invoke, we construct the Lambda Event from the request
        * Then Invoke the Lambda function (docker container)
        * We then transform the response or errors we get from the Invoke and return the data back to
          the caller

        Parameters
        ----------
        kwargs dict
            Keyword Args that are passed to the function from Flask. This happens when we have path parameters

        Returns
        -------
        Response object
        """

        route = self._get_current_route(request)
        cors_headers = Cors.cors_to_headers(self.api.cors)

        method, _ = self.get_request_methods_endpoints(request)
        if method == "OPTIONS":
            headers = Headers(cors_headers)
            return self.service_response("", headers, 200)

        try:
            event = self._construct_event(request, self.port,
                                          self.api.binary_media_types,
                                          self.api.stage_name,
                                          self.api.stage_variables)
        except UnicodeDecodeError:
            return ServiceErrorResponses.lambda_failure_response()

        stdout_stream = io.BytesIO()
        stdout_stream_writer = StreamWriter(stdout_stream, self.is_debugging)

        try:
            self.lambda_runner.invoke(route.function_name,
                                      event,
                                      stdout=stdout_stream_writer,
                                      stderr=self.stderr)
        except FunctionNotFound:
            return ServiceErrorResponses.lambda_not_found_response()

        lambda_response, lambda_logs, _ = LambdaOutputParser.get_lambda_output(
            stdout_stream)

        if self.stderr and lambda_logs:
            # Write the logs to stderr if available.
            self.stderr.write(lambda_logs)

        try:
            (status_code, headers,
             body) = self._parse_lambda_output(lambda_response,
                                               self.api.binary_media_types,
                                               request)
        except (KeyError, TypeError, ValueError):
            LOG.error(
                "Function returned an invalid response (must include one of: body, headers, multiValueHeaders or "
                "statusCode in the response object). Response received: %s",
                lambda_response,
            )
            return ServiceErrorResponses.lambda_failure_response()

        return self.service_response(body, headers, status_code)