generated from ttipo/project-base
fix(backend): 관광공사 사진 주소를 https 로 맞춤
관광공사 장소 사진 1,059건 중 279건이 http 였다. 같은 서버(tong.visitkorea.or.kr)가 https 로도 주므로 저장할 때 https 로 바꾼다(장소·행사 모두). 앱은 http 사진도 받지만 웹(https 페이지)에서는 혼합 콘텐츠로 막힌다. 확인하지 않은 다른 서버의 주소는 그대로 둔다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,8 +52,9 @@ describe('festivalItemToEvent', () => {
|
||||
ldongRegnCd: '27',
|
||||
ldongSignguCd: '260',
|
||||
phone: '053-666-4842',
|
||||
imageUrl: 'http://tong.visitkorea.or.kr/f.jpg',
|
||||
imageThumbUrl: 'http://tong.visitkorea.or.kr/f_s.jpg',
|
||||
// 관광공사 사진 서버는 https 로 맞춘다
|
||||
imageUrl: 'https://tong.visitkorea.or.kr/f.jpg',
|
||||
imageThumbUrl: 'https://tong.visitkorea.or.kr/f_s.jpg',
|
||||
imageLicense: 'Type3',
|
||||
sourceModifiedAt: new Date('2026-10-20T01:15:00.000Z'),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { isInKorea } from '@/shared/utils/geo';
|
||||
import { extractUrl, htmlToText } from '@/shared/utils/html-text';
|
||||
import { preferHttps } from '@/shared/utils/image-url';
|
||||
import { parseKstTimestamp } from '@/shared/utils/kst';
|
||||
import { IMAGE_LICENSES } from '../place.constants';
|
||||
import type { EventKind, ImageLicense } from '../place.constants';
|
||||
@@ -88,8 +89,8 @@ export function festivalItemToEvent(
|
||||
ldongRegnCd: str(item, 'lDongRegnCd'),
|
||||
ldongSignguCd: str(item, 'lDongSignguCd'),
|
||||
phone: htmlToText(item.tel),
|
||||
imageUrl: str(item, 'firstimage'),
|
||||
imageThumbUrl: str(item, 'firstimage2'),
|
||||
imageUrl: preferHttps(str(item, 'firstimage')),
|
||||
imageThumbUrl: preferHttps(str(item, 'firstimage2')),
|
||||
imageLicense: (IMAGE_LICENSES as readonly string[]).includes(license ?? '')
|
||||
? (license as ImageLicense)
|
||||
: null,
|
||||
|
||||
@@ -70,8 +70,9 @@ describe('listItemToPlace', () => {
|
||||
ldongRegnCd: '27',
|
||||
ldongSignguCd: '110',
|
||||
phone: '053-661-2194',
|
||||
imageUrl: 'http://tong.visitkorea.or.kr/a.jpg',
|
||||
imageThumbUrl: 'http://tong.visitkorea.or.kr/a_s.jpg',
|
||||
// 관광공사 사진 서버는 https 로 맞춘다(웹에서 혼합 콘텐츠로 막히지 않게)
|
||||
imageUrl: 'https://tong.visitkorea.or.kr/a.jpg',
|
||||
imageThumbUrl: 'https://tong.visitkorea.or.kr/a_s.jpg',
|
||||
imageLicense: 'Type1',
|
||||
sourceModifiedAt: new Date('2026-10-15T00:30:00.000Z'),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { isInKorea, isInSido, sidoCodeFromAddress } from '@/shared/utils/geo';
|
||||
import { extractUrl, htmlToText } from '@/shared/utils/html-text';
|
||||
import { preferHttps } from '@/shared/utils/image-url';
|
||||
import { parseKstTimestamp } from '@/shared/utils/kst';
|
||||
import { parseOpeningHours } from '@/shared/utils/opening-hours';
|
||||
import type { ParsedOpeningHours } from '@/shared/utils/opening-hours';
|
||||
@@ -224,8 +225,8 @@ export function listItemToPlace(
|
||||
ldongRegnCd: str(item, 'lDongRegnCd'),
|
||||
ldongSignguCd: str(item, 'lDongSignguCd'),
|
||||
phone: htmlToText(item.tel),
|
||||
imageUrl: str(item, 'firstimage'),
|
||||
imageThumbUrl: str(item, 'firstimage2'),
|
||||
imageUrl: preferHttps(str(item, 'firstimage')),
|
||||
imageThumbUrl: preferHttps(str(item, 'firstimage2')),
|
||||
imageLicense: (IMAGE_LICENSES as readonly string[]).includes(license ?? '')
|
||||
? (license as ImageLicense)
|
||||
: null,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { preferHttps } from './image-url';
|
||||
|
||||
describe('preferHttps', () => {
|
||||
it('관광공사 사진 서버의 http 주소를 https 로 바꾼다', () => {
|
||||
expect(
|
||||
preferHttps('http://tong.visitkorea.or.kr/cms/resource/a_image2_1.jpg'),
|
||||
).toBe('https://tong.visitkorea.or.kr/cms/resource/a_image2_1.jpg');
|
||||
expect(preferHttps('HTTP://Tong.VisitKorea.or.kr/a.jpg')).toBe(
|
||||
'https://Tong.VisitKorea.or.kr/a.jpg',
|
||||
);
|
||||
});
|
||||
|
||||
it('이미 https 이거나 확인하지 않은 서버·빈 값은 그대로 둔다', () => {
|
||||
expect(preferHttps('https://tong.visitkorea.or.kr/a.jpg')).toBe(
|
||||
'https://tong.visitkorea.or.kr/a.jpg',
|
||||
);
|
||||
expect(preferHttps('http://www.kopis.or.kr/a.jpg')).toBe(
|
||||
'http://www.kopis.or.kr/a.jpg',
|
||||
);
|
||||
expect(preferHttps('http://tong.visitkorea.or.kr.evil.example/a.jpg')).toBe(
|
||||
'http://tong.visitkorea.or.kr.evil.example/a.jpg',
|
||||
);
|
||||
expect(preferHttps(null)).toBeNull();
|
||||
expect(preferHttps('')).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 사진 주소 정리 (순수 함수).
|
||||
*/
|
||||
|
||||
/**
|
||||
* 같은 파일을 https 로도 주는 것을 확인한 사진 서버.
|
||||
* 2026-11-04 대구 관광공사 장소 사진 1,059건 중 780건은 https, 279건은 http 였다(같은 서버).
|
||||
* https 페이지(웹)에서는 http 사진이 혼합 콘텐츠로 막히므로 저장할 때 https 로 맞춘다.
|
||||
*/
|
||||
const HTTPS_IMAGE_HOSTS = new Set(['tong.visitkorea.or.kr']);
|
||||
|
||||
/** 확인한 서버의 http 사진 주소를 https 로 바꾼다. 다른 서버·형식은 그대로 둔다 */
|
||||
export function preferHttps(url: string | null): string | null {
|
||||
if (!url) return url;
|
||||
const m = /^http:\/\/([^/?#:]+)/i.exec(url);
|
||||
if (!m || !HTTPS_IMAGE_HOSTS.has(m[1].toLowerCase())) return url;
|
||||
return `https://${url.slice('http://'.length)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user