Skip to content

Commit 976d55e

Browse files
authored
Merge pull request #270 from Link-MIND/feature/#269
fix/#269: redirect 302๋ฅผ ๋„์šฐ๋Š” url์ธ ๊ฒฝ์šฐ ๋๊นŒ์ง€ ๋“ค์–ด๊ฐ€์„œ ํ—ค๋”ํŒŒ์‹ฑ
2 parents 9f6b39c + 49deb78 commit 976d55e

File tree

5 files changed

+117
-49
lines changed

5 files changed

+117
-49
lines changed

โ€Žlinkmind/src/main/java/com/app/toaster/parse/service/ParsingService.javaโ€Ž

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,57 @@ public ParsingService(@Value("${static-image.url}") final String basicThumbnail)
3131
this.BASIC_THUMBNAIL = basicThumbnail;
3232
}
3333

34-
public OgResponse getOg(String linkUrl) throws IOException {
35-
try {
36-
String title = getTitle(linkUrl);
37-
log.info(title);
38-
String image = getImage(linkUrl);
39-
log.info(image);
40-
return OgResponse.of(
41-
title == null || title.isBlank() ? "๊ธฐ๋ณธ ํ† ์ŠคํŠธ ์ œ๋ชฉ" : title,
42-
image == null || image.isBlank() ? BASIC_THUMBNAIL : image
43-
);
44-
}catch (HttpStatusException | SSLHandshakeException e){
45-
return OgResponse.of("15์ž ๋‚ด๋กœ ์ œ๋ชฉ์„ ์ง€์–ด์ฃผ์„ธ์š”.", BASIC_THUMBNAIL);
46-
}catch (ConnectException e){
47-
throw new BadRequestException(Error.BAD_REQUEST_URL, Error.BAD_REQUEST_URL.getMessage());
48-
}
34+
public OgResponse getOg(String linkUrl) {
35+
String title = getTitle(linkUrl);
36+
log.info(title);
37+
String image = getImage(linkUrl);
38+
log.info(image);
39+
return OgResponse.of(
40+
title == null || title.isBlank() ? "๊ธฐ๋ณธ ํ† ์ŠคํŠธ ์ œ๋ชฉ" : title,
41+
image == null || image.isBlank() ? BASIC_THUMBNAIL : image
42+
);
4943
}
5044
// public String getOg(String linkUrl) throws IOException {
5145
// String image = getImage(linkUrl);
5246
// return image == null || image.isBlank() ? BASIC_THUMBNAIL : image;
5347
// }
5448

55-
private String getTitle(String linkUrl) throws IOException {
49+
private String getTitle(String linkUrl) {
5650
try {
57-
Document doc = Jsoup.connect(linkUrl).get();
51+
Document doc = Jsoup.connect(linkUrl)
52+
.followRedirects(true) // ๋ฆฌ๋‹ค์ด๋ ‰์…˜ ์ž๋™ ๋”ฐ๋ผ๊ฐ€๊ธฐ
53+
.maxBodySize(1024*1024) // ํŽ˜์ด์ง€ ํฌ๊ธฐ ์ œํ•œ ์—†์Œ
54+
.timeout(10000)
55+
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
56+
.get();
5857
Elements ogTitleElements = doc.select("meta[property=og:title]");
5958
Elements titleElements = doc.select("head").select("title");
6059
if (ogTitleElements.isEmpty() && titleElements.isEmpty()) {
61-
return null;
60+
log.info("[NOT FOUND] og ๋ฐ์ดํ„ฐ, html header ๋œฏ์—ˆ๋Š”๋ฐ ๊ฒฐ๊ณผ ์—†์Œ.");
61+
return "15์ž ๋‚ด๋กœ ์ œ๋ชฉ์„ ์ง€์–ด์ฃผ์„ธ์š”.";
6262
}
6363
return ogTitleElements.isEmpty()?titleElements.get(0).text(): ogTitleElements.get(0).attr("content");
6464
}catch (org.jsoup.HttpStatusException e){
65-
return null;
65+
log.info("[ERROR] title ํŒŒ์‹ฑ ์ค‘ http status ์—๋Ÿฌ ๋ฐœ์ƒ");
66+
return "15์ž ๋‚ด๋กœ ์ œ๋ชฉ์„ ์ง€์–ด์ฃผ์„ธ์š”.";
67+
} catch (SSLHandshakeException e){
68+
log.info("[ERROR] ๋„ˆ๋ฌด ์˜ค๋ž˜๋œ ์‚ฌ์ดํŠธ๋ผ handshake ๊ทœ์น™์ด ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
69+
return "15์ž ๋‚ด๋กœ ์ œ๋ชฉ์„ ์ง€์–ด์ฃผ์„ธ์š”.";
70+
} catch (IOException e){
71+
log.info("[ERROR] title ํŒŒ์‹ฑ ์ค‘ ์—๋Ÿฌ ๋ฐœ์ƒ");
72+
return "15์ž ๋‚ด๋กœ ์ œ๋ชฉ์„ ์ง€์–ด์ฃผ์„ธ์š”.";
6673
}
67-
6874
}
6975

7076
private String getImage(String linkUrl){
7177
try {
72-
Document doc = Jsoup.connect(linkUrl).get();
78+
Document doc = Jsoup.connect(linkUrl)
79+
.followRedirects(true) // ๋ฆฌ๋‹ค์ด๋ ‰์…˜ ์ž๋™ ๋”ฐ๋ผ๊ฐ€๊ธฐ
80+
.maxBodySize(1024*1024) // ํŽ˜์ด์ง€ ํฌ๊ธฐ ์ œํ•œ ์—†์Œ
81+
.timeout(10000)
82+
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
83+
.get();
84+
7385
Elements iframes = doc.select("iframe");
7486
Elements ogBlogImage = new Elements();
7587
if (!iframes.isEmpty()){
@@ -82,7 +94,10 @@ private String getImage(String linkUrl){
8294
return findImageAnywhere(ogImageElements, ogImage, ogBlogImage);
8395
}catch (MalformedURLException e){
8496
throw new CustomException(Error.MALFORMED_URL_EXEPTION,Error.MALFORMED_URL_EXEPTION.getMessage());
85-
}catch (org.jsoup.HttpStatusException e){
97+
}catch (org.jsoup.HttpStatusException e) {
98+
return null;
99+
}catch (SSLHandshakeException e){
100+
log.info("[ERROR] ๋„ˆ๋ฌด ์˜ค๋ž˜๋œ ์‚ฌ์ดํŠธ๋ผ handshake ๊ทœ์น™์ด ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
86101
return null;
87102
}catch (IOException e){
88103
throw new CustomException(Error.NOT_FOUND_IMAGE_EXCEPTION, Error.NOT_FOUND_IMAGE_EXCEPTION.getMessage());

โ€Žlinkmind/src/main/java/com/app/toaster/toast/controller/ToastController.javaโ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class ToastController {
4242
@Deprecated
4343
public ApiResponse getOgAdvanced(
4444
@RequestBody OgRequestDto ogRequestDto
45-
) throws IOException {
45+
) {
4646
return ApiResponse.success(Success.PARSING_OG_SUCCESS, parsingService.getOg(ogRequestDto.linkUrl()));
4747
}
4848

@@ -72,7 +72,7 @@ public ApiResponse<IsReadResponse> updateIsRead(
7272
public ApiResponse deleteToast( //๋‚˜์ค‘์— softDelete๋กœ ๋ณ€๊ฒฝ
7373
@UserId Long userId,
7474
@RequestParam Long toastId
75-
) throws IOException {
75+
) {
7676
toastService.deleteToast(userId, toastId);
7777
return ApiResponse.success(Success.DELETE_TOAST_SUCCESS);
7878
}

โ€Žlinkmind/src/main/java/com/app/toaster/toast/service/ToastService.javaโ€Ž

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,21 @@ public void createToast(Long userId, SaveToastDto saveToastDto){
5555
throw new CustomException(Error.BAD_REQUEST_EMPTY_URL, Error.BAD_REQUEST_EMPTY_URL.getMessage());
5656
}
5757
//ํ† ์ŠคํŠธ ์ƒ์„ฑ
58-
try {
59-
OgResponse res = parsingService.getOg(saveToastDto.linkUrl());
60-
//byte ๋ฐฐ์—ด๋กœ ์ฝ์–ด๋“ค์ž„.
61-
log.info(res.titleAdvanced());
62-
log.info(res.imageAdvanced());
63-
String imageString = checkIsBasicImage(res.imageAdvanced());
64-
// // ImagePresignedUrlResponse realRes = getUploadPreSignedUrl(res.imageAdvanced());
65-
// log.info(realRes.fileName());
66-
// log.info(realRes.preSignedUrl());
67-
68-
69-
//presigned url
70-
Toast toast = Toast.builder()
71-
.user(presentUser)
72-
.linkUrl(saveToastDto.linkUrl())
73-
.title(res.titleAdvanced())
74-
.thumbnailUrl(imageString)
75-
.build();
76-
// ๋งŒ์•ฝ ์œ ์ €์—๊ฒŒ ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•˜๊ณ 
77-
checkCategoryIsEmpty(toast, saveToastDto.categoryId());
78-
toastRepository.save(toast);
79-
} catch (IOException e ) { //์—ฌ๊ธฐ์„œ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์™ธ๋ถ€ s3 ๋ฌธ์ œ์ผ ์ˆ˜ ๋„ ์žˆ์œผ๋ฏ€๋กœ 500์œผ๋กœ ์—๋Ÿฌ ์˜ˆ์ƒ ๋ฒ”์œ„ ์•Œ๋ฆผ.
80-
throw new CustomException(Error.CREATE_TOAST_PROCCESS_EXCEPTION, Error.CREATE_TOAST_PROCCESS_EXCEPTION.getMessage());
81-
}
58+
OgResponse res = parsingService.getOg(saveToastDto.linkUrl());
59+
//byte ๋ฐฐ์—ด๋กœ ์ฝ์–ด๋“ค์ž„.
60+
log.info(res.titleAdvanced());
61+
log.info(res.imageAdvanced());
62+
String imageString = checkIsBasicImage(res.imageAdvanced());
63+
64+
Toast toast = Toast.builder()
65+
.user(presentUser)
66+
.linkUrl(saveToastDto.linkUrl())
67+
.title(res.titleAdvanced())
68+
.thumbnailUrl(imageString)
69+
.build();
70+
// ๋งŒ์•ฝ ์œ ์ €์—๊ฒŒ ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•˜๊ณ 
71+
checkCategoryIsEmpty(toast, saveToastDto.categoryId());
72+
toastRepository.save(toast);
8273

8374
}
8475
@Transactional
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.app.toaster.parse.service;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import com.app.toaster.parse.controller.response.OgResponse;
6+
import com.app.toaster.toast.controller.request.SaveToastDto;
7+
import java.io.IOException;
8+
import org.jsoup.Jsoup;
9+
import org.jsoup.nodes.Document;
10+
import org.jsoup.select.Elements;
11+
import org.junit.jupiter.api.DisplayName;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.ExtendWith;
14+
import org.mockito.InjectMocks;
15+
import org.mockito.junit.jupiter.MockitoExtension;
16+
17+
@ExtendWith(MockitoExtension.class)
18+
class ParsingServiceTest {
19+
20+
@InjectMocks
21+
private ParsingService parsingService;
22+
23+
@Test
24+
@DisplayName("๋ฆฌ๋‹ค์ด๋ ‰์…˜ Url์— ๋Œ€ํ•ด์„œ๋„ open graph ํŒŒ์‹ฑ์ด ์ž˜๋œ๋‹ค.")
25+
void getOgWhenRedirect302Url() throws IOException {
26+
// given
27+
String redirectUrl = createRedirect302CaseFixture().linkUrl();
28+
29+
// when - ์ง์ ‘ Jsoup์œผ๋กœ ํ…Œ์ŠคํŠธ
30+
Document doc = Jsoup.connect(redirectUrl)
31+
.followRedirects(true)
32+
.maxBodySize(1024 * 1024)
33+
.timeout(10000)
34+
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
35+
.get();
36+
37+
Elements ogTitleElements = doc.select("meta[property=og:title]");
38+
Elements ogImageElements = doc.select("meta[property=og:image]");
39+
Elements titleElements = doc.select("title");
40+
41+
// then - Jsoup ๋ ˆ๋ฒจ์—์„œ ๋จผ์ € ๊ฒ€์ฆ
42+
System.out.println("OG Title: " + (ogTitleElements.isEmpty() ? "์—†์Œ" : ogTitleElements.attr("content")));
43+
System.out.println("OG Image: " + (ogImageElements.isEmpty() ? "์—†์Œ" : ogImageElements.attr("content")));
44+
System.out.println("Title: " + (titleElements.isEmpty() ? "์—†์Œ" : titleElements.text()));
45+
46+
// when - ์„œ๋น„์Šค ๋ ˆ๋ฒจ ํ…Œ์ŠคํŠธ
47+
OgResponse result = parsingService.getOg(redirectUrl);
48+
49+
// then
50+
assertThat(result).isNotNull();
51+
assertThat(result.titleAdvanced()).isNotBlank();
52+
assertThat(result.imageAdvanced()).isNotBlank();
53+
54+
// ์ถ”๊ฐ€ ๊ฒ€์ฆ
55+
assertThat(result.titleAdvanced()).isNotEqualTo("๊ธฐ๋ณธ ํ† ์ŠคํŠธ ์ œ๋ชฉ");
56+
assertThat(result.imageAdvanced()).isNotEqualTo("BASIC_THUMBNAIL_URL");
57+
}
58+
59+
private SaveToastDto createRedirect302CaseFixture(){
60+
return new SaveToastDto("https://digital.mk.co.kr/news_link.php?year=2025&no=469576", 1L);
61+
}
62+
}

โ€Žlinkmind/src/test/java/com/app/toaster/toast/service/ToastServiceTest.javaโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void setUp() {
7171

7272
@Test
7373
@DisplayName("Toast ์ƒ์„ฑ ์„ฑ๊ณต ํ…Œ์ŠคํŠธ")
74-
void createToast_Success() throws IOException {
74+
void createToast_Success() {
7575
// given
7676
Long userId = 1L;
7777

0 commit comments

Comments
ย (0)