Skip to content

Commit

Permalink
[BE] feat: S3 pre-singed-url 반환 기능 구현 (#591)
Browse files Browse the repository at this point in the history
* feat: S3 pre-singed-url 반환 기능 구현

* refactor: swagger 명세 수정

* fix: test 실패 수정

* fix: test 실패 expiration time -> 숫자로 수정

* refactor: 리뷰 반영

* refactor: swagger 명세 수정
  • Loading branch information
wugawuga authored Sep 11, 2023
1 parent 8028b4c commit 677f1b3
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 1 deletion.
2 changes: 2 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ dependencies {

implementation 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'

implementation 'com.amazonaws:aws-java-sdk-s3:1.12.547'
}

tasks.named('test') {
Expand Down
5 changes: 5 additions & 0 deletions backend/src/main/java/com/funeat/common/OpenApiConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
@Tag(name = "01.Product", description = "상품 기능"),
@Tag(name = "02.Category", description = "카테고리 기능"),
@Tag(name = "03.Review", description = "리뷰 기능"),
@Tag(name = "04.Tag", description = "태그 기능"),
@Tag(name = "05.Member", description = "사용자 기능"),
@Tag(name = "06.Login", description = "로그인 기능"),
@Tag(name = "07.Recipe", description = "꿀조합 기능"),
@Tag(name = "08.S3", description = "S3 기능"),
}
)
@Configuration
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.funeat.common.controller;

import com.funeat.common.dto.S3UrlRequest;
import com.funeat.common.dto.S3UrlResponse;
import com.funeat.common.s3.S3UploadUrlGenerator;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PreSingedApiController implements PreSingedController {

private final S3UploadUrlGenerator s3UploadUrlGenerator;

public PreSingedApiController(final S3UploadUrlGenerator s3UploadUrlGenerator) {
this.s3UploadUrlGenerator = s3UploadUrlGenerator;
}

@PostMapping("/api/s3/presigned")
public ResponseEntity<S3UrlResponse> getPreSingedUrl(@RequestBody final S3UrlRequest request) {
final S3UrlResponse preSignedUrl = s3UploadUrlGenerator.getPreSignedUrl(request.getFileName());

return ResponseEntity.status(HttpStatus.CREATED)
.body(preSignedUrl);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.funeat.common.controller;

import com.funeat.common.dto.S3UrlRequest;
import com.funeat.common.dto.S3UrlResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

public interface PreSingedController {

@Operation(summary = "S3 업로드 URL 요청", description = "S3 업로드 URL 요청한다.")
@ApiResponse(
responseCode = "201",
description = "업로드 URL 요청 성공."
)
@PostMapping
ResponseEntity<S3UrlResponse> getPreSingedUrl(@RequestBody final S3UrlRequest request);
}
20 changes: 20 additions & 0 deletions backend/src/main/java/com/funeat/common/dto/S3UrlRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.funeat.common.dto;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotBlank;

public class S3UrlRequest {

@NotBlank(message = "파일명을 확인해주세요")
private final String fileName;

@JsonCreator
public S3UrlRequest(@JsonProperty("fileName") final String fileName) {
this.fileName = fileName;
}

public String getFileName() {
return fileName;
}
}
14 changes: 14 additions & 0 deletions backend/src/main/java/com/funeat/common/dto/S3UrlResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.funeat.common.dto;

public class S3UrlResponse {

private final String preSingedUrl;

public S3UrlResponse(final String preSingedUrl) {
this.preSingedUrl = preSingedUrl;
}

public String getPreSingedUrl() {
return preSingedUrl;
}
}
28 changes: 28 additions & 0 deletions backend/src/main/java/com/funeat/common/s3/AwsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.funeat.common.s3;

import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AwsConfig {

@Value("${cloud.aws.region.static}")
private String region;

@Bean
public InstanceProfileCredentialsProvider awsCredentialsProvider() {
return InstanceProfileCredentialsProvider.getInstance();
}

@Bean
public AmazonS3 amazonS3Client() {
return AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(awsCredentialsProvider())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.funeat.common.s3;

import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.Headers;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.funeat.common.dto.S3UrlResponse;
import java.util.Date;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class S3UploadUrlGenerator {

@Value("${cloud.aws.s3.bucket}")
private String bucket;

@Value("${cloud.aws.s3.folder}")
private String folder;

@Value("${cloud.aws.s3.expiration.time}")
private long expirationTime;

private final AmazonS3 amazonS3;

public S3UploadUrlGenerator(final AmazonS3 amazonS3) {
this.amazonS3 = amazonS3;
}

public S3UrlResponse getPreSignedUrl(final String fileName) {
final GeneratePresignedUrlRequest generatePresignedUrlRequest = getPreSignedUrlRequest(bucket, fileName);

return new S3UrlResponse(amazonS3.generatePresignedUrl(generatePresignedUrlRequest).toString());
}

private GeneratePresignedUrlRequest getPreSignedUrlRequest(final String bucket, final String fileName) {
final Date madeExpirationTime = getExpirationTime();
final GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucket,
folder + fileName)
.withMethod(HttpMethod.PUT)
.withExpiration(madeExpirationTime);

urlRequest.addRequestParameter(Headers.S3_CANNED_ACL, CannedAccessControlList.PublicRead.toString());

return urlRequest;
}

private Date getExpirationTime() {
final Date madeExpirationTime = new Date();
madeExpirationTime.setTime(expirationTime);
return madeExpirationTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

@Tag(name = "07. Recipe", description = "꿀조합 관련 API 입니다.")
@Tag(name = "07.Recipe", description = "꿀조합 관련 API 입니다.")
public interface RecipeController {

@Operation(summary = "꿀조합 추가", description = "꿀조합을 작성한다.")
Expand Down
10 changes: 10 additions & 0 deletions backend/src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ management:
enabled: true
server:
port: { SERVER_PORT }

cloud:
aws:
region:
static: { S3_REGION }
s3:
bucket: { S3_BUCKET }
folder: { S3_DEV_FOLDER }
expiration:
time: { S3_EXPIRATION }
9 changes: 9 additions & 0 deletions backend/src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ management:
server:
port: { SERVER_PORT }

cloud:
aws:
region:
static: { S3_REGION }
s3:
bucket: { S3_BUCKET }
folder: { S3_PROD_FOLDER }
expiration:
time: { S3_EXPIRATION }
10 changes: 10 additions & 0 deletions backend/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,13 @@ server:
session:
cookie:
name: FUNEAT

cloud:
aws:
region:
static: testRegion
s3:
bucket: testBucket
folder: testFolder
expiration:
time: 1111

0 comments on commit 677f1b3

Please sign in to comment.