URL 단축

120 read

축소할 URL을 입력하세요.

로직 설명
  1. URL을 입력 받기.
  2. 검증하기
  3. short-code 생성
  4. 로직 설명
    toolRoute.post('/shortten', async (c) => {
    	const formData = await c.req.formData();
    	const url = formData.get('url');
    
    	// 1-1. 검증
    	if (!url) {
    		return c.json({ success: false, message: 'URL을 입력해주세요.' }, 400);
    	}
    
    	// 1-2. 검증
    	if (!url || !url.match(/^https?:\/\//)) {
    		return c.json({ success: false, message: 'http[s]:// 로 시작하는 올바른 URL을 입력해주세요.', result: null }, 400);
    	}
    
    	// 1-3. 검증
    	if (!url.match(/\./)) {
    		return c.json({ success: false, message: '올바른 도메인을 입력해주세요.', result: null }, 400);
    	}
    
    	const token = formData.get('cf-turnstile-response');
    
    	// 2. Cloudflare turnstile 토큰 자체가 없으면 바로 차단
    	if (!token) {
    		return c.json({ success: false, message: '캡차 인증이 필요합니다.' }, 400);
    	}
    
    	// 3. Cloudflare 캡챠 인증
    	const verifyRes = await fetch(
    		'https://challenges.cloudflare.com/turnstile/v0/siteverify',
    		{
    			method: 'POST',
    			headers: { 'Content-Type': 'application/json' },
    			body: JSON.stringify({
    				secret: c.env.CF_TURNSTILE_SECRET,
    				response: token,
    				remoteip: c.req.header('CF-Connecting-IP'),
    			}),
    		}
    	);
    
    	const urls = new Urls(c);
    
    	// 4. 해당 URL 을 가진 데이터가 있는지 검색
    	const urlData = await urls.selectOne({ url });
    	let result = null;
    
    	// 5-1.있으면 INSERT 건너뛰고 바로 리턴
    	if(urlData) {
    		result = urlData;
    
    	// 5.2 없으면 URL 단축 후 INSERT
    	} else {
    
    		const outcome = await verifyRes.json();
    
    		if (!outcome.success) {
    			console.error('Turnstile 검증 실패:', outcome['error-codes']);
    			return c.json({ success: false, message: `캡차 검증에 실패했습니다.` }, 403);
    		}
    
    		let max = await urls.selectMax('id');
    		if (!max || max === 0) {
    			max = 0;
    		}
    
    		const number = String(max + 1);
    		const shortCode = StringUtil.textToBase62(number);
    
    		result = await urls.insert({ code: shortCode, url: url });
    
    	}
    
    	return c.json({ success: true, result: `https://${c.env.HOST}/s/${result.code}` });
    });