API Gateway CORS

손준수·2024년 5월 20일
0

Spring project를 jar로 빌드하여 AWS lambda에 업로드 한 후
test 진행 중 AWS 설정을 못읽어와서 DynamoDB 조회가 안되는 이슈가 있었음

application.properties에 aws 키값을 입력하지 않고 환경 변수로 설정

package com.example.springboot.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DynamoDBconfig {
    @Value("${MY_AWS_ACCESS_KEY_ID}")
    private String amazonAwsAccessKey;

    @Value("${MY_AWS_SECRET_ACCESS_KEY}")
    private String amazonAwsSecretKey;

    @Value("${AWS_DYNAMODB_REGION}")
    private String region;

    @Bean
    public AmazonDynamoDB amazonDynamoDB() {
        return AmazonDynamoDBClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(amazonAwsAccessKey, amazonAwsSecretKey)))
                .withRegion(Regions.fromName(region))
                .build();
    }

    @Bean
    public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
        return new DynamoDBMapper(amazonDynamoDB, DynamoDBMapperConfig.DEFAULT);
    }
}

config 구성

Lambda에도 환경변수를 설정해주었더니 DynamoDB 조회문제는 해결 되었다.

하지만 새로운 변수가 발생했다..
Api Gateway에서 api를 /{proxy+}, ANY 로 만들어서 lambda에 트리거로 추가 해주었는데

CORS 에러가 나타났다
일단 react의 package.json에 "proxy": "https://xxxxxxxxxxx.execute-api.ap-northeast-2.amazonaws.com" 설정도 해주고

https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html

aws 공식문서 보고

cors 설정도 해주었는데 해결이 되지않는다 ...
혹시나 싶어 spring에도

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("Content-Type", "X-Amz-Date", "Authorization", "X-Api-Key", "X-Amz-Security-Token")
                .allowCredentials(true)
                .maxAge(3600);
    }


}

현재 상태 ( 요청측 , 응답측 각각에만 세팅 해둔상태 spring에 있는건 지움)

const sendDataToServer = async (selections) => {
    try {
      const response = await axios.post(
        "https://<rest_api_id>-<vpc_endpoint_id>.execute-api.<aws_region>.amazonaws.com"

        {
          selections,
        },
        {
          headers: {
            "Content-Type": "application/json",
            "spring.cloud.function.definition": "getChoice",
            "Access-Control-Allow-Origin": "http://localhost:3000", // 필요한 도메인으로 변경
            "Access-Control-Allow-Methods": "OPTIONS,POST",
            "Access-Control-Allow-Headers":
              "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
            "Access-Control-Allow-Credentials": "true",
          },
        }
      );

      console.log("서버로부터의 응답:", response.data);
      console.log(response.data.music, response.data.places);

      navigate("/Result", {
        state: {
          music: response.data.music,
          place: response.data.places,
        },
      });
    } catch (error) {
      console.error("데이터 요청 중 오류 발생:", error);
    }
  };
 // package.json
// https://<rest_api_id>-<vpc_endpoint_id>.execute-api.<aws_region>.amazonaws.com"

※ 해결책을 찾았다
Api Gateway의 /{proxy+} , ANY 설정을 지우고

새롭게 / 해당하는 요청 + OPTIONS를 만들어주고

요청에 사진처럼 요청에 매개변수 매핑을 편집해주고

람다에 요청전 핸들러 함수를 만들어서 연결해주어야 한다

G선생님께 물어본 preflight의 역할

AWS Lambda에서 "preflight" 요청은 일반적으로 CORS(Cross-Origin Resource Sharing) 문제와 관련이 있습니다.
특히, HTTP API를 만들 때 클라이언트가 서버에 요청을 보내기 전에 특정 조건을 확인하는 데 사용됩니다.
여기서 "preflight" 요청은 브라우저가 특정 요청을 실제로 보내기 전에 보내는 사전 요청을 의미합니다.

CORS와 Preflight 요청
CORS는 다른 도메인에서 호스트된 리소스에 접근할 수 있도록 하는 보안 기능입니다.
웹 브라우저는 보안상의 이유로, 다른 도메인에서 리소스를 요청할 때 CORS 정책을 따릅니다.
특히, HTTP 요청이 GET, POST, HEAD 이외의 메서드(예: PUT, DELETE 등)를 사용하거나, 
Content-Type 이외의 헤더를 포함하는 경우, 브라우저는 실제 요청을 보내기 전에 "preflight" 요청을 보냅니다.

Preflight 요청의 역할
Preflight 요청의 역할은 서버가 실제 요청을 수락할 수 있는지 확인하는 것입니다. 
브라우저는 OPTIONS 메서드를 사용하여 서버에 사전 요청을 보내며,
서버는 이 요청에 대한 응답으로 CORS 헤더를 포함하여 클라이언트가 실제 요청을 보내도 되는지 여부를 알려줍니다.

AWS Lambda에서 Preflight 요청 처리
AWS Lambda를 API Gateway와 함께 사용할 때, 
preflight 요청을 처리하기 위해 OPTIONS 메서드를 처리하는 람다 함수나 API Gateway 설정이 필요합니다. 
이를 통해 서버는 브라우저가 보내는 사전 요청에 적절히 응답할 수 있습니다.

참고)
https://stackoverflow.com/questions/76182956/cors-preflight-response-error-with-aws-api-gateway-and-lambda-function

0개의 댓글