-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feat/#76 shorten url
- Loading branch information
Showing
15 changed files
with
235 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
Server/src/main/java/JGS/CasperEvent/domain/url/controller/UrlController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,44 @@ | ||
package JGS.CasperEvent.domain.url.controller; | ||
|
||
import JGS.CasperEvent.domain.url.dto.ShortenUrlResponseDto; | ||
import JGS.CasperEvent.domain.url.service.UrlService; | ||
import JGS.CasperEvent.global.entity.BaseUser; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import javax.crypto.BadPaddingException; | ||
import javax.crypto.IllegalBlockSizeException; | ||
import javax.crypto.NoSuchPaddingException; | ||
import java.security.InvalidKeyException; | ||
import java.security.NoSuchAlgorithmException; | ||
|
||
@RestController | ||
@RequestMapping("link") | ||
public class UrlController { | ||
|
||
private final UrlService urlService; | ||
|
||
@Autowired | ||
public UrlController(UrlService urlService) { | ||
this.urlService = urlService; | ||
} | ||
|
||
@PostMapping | ||
public ResponseEntity<ShortenUrlResponseDto> generateShortUrl(HttpServletRequest request) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { | ||
BaseUser user = (BaseUser) request.getAttribute("user"); | ||
return ResponseEntity | ||
.status(HttpStatus.CREATED) | ||
.body(urlService.generateShortUrl(user)); | ||
} | ||
|
||
@GetMapping("/{encodedId}") | ||
public ResponseEntity<Void> redirectOriginalUrl(@PathVariable String encodedId){ | ||
return ResponseEntity | ||
.status(HttpStatus.FOUND) | ||
.header("Location", urlService.getOriginalUrl(encodedId)) | ||
.build(); | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
Server/src/main/java/JGS/CasperEvent/domain/url/dto/ShortenUrlResponseDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package JGS.CasperEvent.domain.url.dto; | ||
|
||
public record ShortenUrlResponseDto(String shortenUrl, String shortenLocalUrl) { | ||
} |
14 changes: 0 additions & 14 deletions
14
Server/src/main/java/JGS/CasperEvent/domain/url/entity/OriginalUrl.java
This file was deleted.
Oops, something went wrong.
26 changes: 26 additions & 0 deletions
26
Server/src/main/java/JGS/CasperEvent/domain/url/entity/Url.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package JGS.CasperEvent.domain.url.entity; | ||
|
||
import JGS.CasperEvent.global.entity.BaseEntity; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import lombok.Getter; | ||
|
||
@Entity | ||
@Getter | ||
public class Url extends BaseEntity { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private String originalUrl; | ||
|
||
public Url(String originalUrl){ | ||
this.originalUrl = originalUrl; | ||
} | ||
|
||
public Url() { | ||
|
||
} | ||
} |
10 changes: 9 additions & 1 deletion
10
Server/src/main/java/JGS/CasperEvent/domain/url/repository/UrlRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,12 @@ | ||
package JGS.CasperEvent.domain.url.repository; | ||
|
||
public interface UrlRepository { | ||
import JGS.CasperEvent.domain.url.entity.Url; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface UrlRepository extends JpaRepository<Url, Long> { | ||
Optional<Url> findByOriginalUrl(String originalUrl); | ||
} |
67 changes: 67 additions & 0 deletions
67
Server/src/main/java/JGS/CasperEvent/domain/url/service/UrlService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,71 @@ | ||
package JGS.CasperEvent.domain.url.service; | ||
|
||
import JGS.CasperEvent.domain.url.dto.ShortenUrlResponseDto; | ||
import JGS.CasperEvent.domain.url.entity.Url; | ||
import JGS.CasperEvent.domain.url.repository.UrlRepository; | ||
import JGS.CasperEvent.global.entity.BaseUser; | ||
import JGS.CasperEvent.global.util.AESUtils; | ||
import JGS.CasperEvent.global.util.Base62Utils; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
import javax.crypto.BadPaddingException; | ||
import javax.crypto.IllegalBlockSizeException; | ||
import javax.crypto.NoSuchPaddingException; | ||
import javax.crypto.SecretKey; | ||
import java.security.InvalidKeyException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.NoSuchElementException; | ||
|
||
@Service | ||
public class UrlService { | ||
|
||
@Value("${client.url}") | ||
private String clientUrl; | ||
@Value("${client.localUrl}") | ||
private String localClientUrl; | ||
|
||
@Value("${shortenUrlService.url}") | ||
private String shortenBaseUrl; | ||
|
||
|
||
private final UrlRepository urlRepository; | ||
private final SecretKey secretKey; | ||
|
||
@Autowired | ||
public UrlService(UrlRepository urlRepository, SecretKey secretKey) { | ||
this.urlRepository = urlRepository; | ||
this.secretKey = secretKey; | ||
} | ||
|
||
//todo: 테스트 끝나면 수정필요 | ||
public ShortenUrlResponseDto generateShortUrl(BaseUser user) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { | ||
String encryptedUserId = AESUtils.encrypt(user.getId(), secretKey); | ||
|
||
String originalUrl = clientUrl + "?" + "referralId=" + encryptedUserId; | ||
String originalLocalUrl = localClientUrl + "?" + "referralId=" + encryptedUserId; | ||
|
||
Url url = urlRepository.findByOriginalUrl(originalUrl).orElseGet( | ||
() -> urlRepository.save(new Url(originalUrl)) | ||
); | ||
Url localUrl = urlRepository.findByOriginalUrl(originalLocalUrl).orElseGet( | ||
() -> urlRepository.save(new Url(originalLocalUrl)) | ||
); | ||
|
||
Long urlId = url.getId(); | ||
Long localUrlId = localUrl.getId(); | ||
|
||
String shortenUrl = shortenBaseUrl + "/link/" + Base62Utils.encode(urlId); | ||
String shortenLocalUrl = shortenBaseUrl + "/link/" + Base62Utils.encode(localUrlId); | ||
|
||
return new ShortenUrlResponseDto(shortenUrl, shortenLocalUrl); | ||
} | ||
|
||
public String getOriginalUrl(String encodedId){ | ||
Long urlId = Base62Utils.decode(encodedId); | ||
Url url = urlRepository.findById(urlId).orElseThrow(NoSuchElementException::new); | ||
return url.getOriginalUrl(); | ||
} | ||
|
||
} |
20 changes: 20 additions & 0 deletions
20
Server/src/main/java/JGS/CasperEvent/global/config/SecurityConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package JGS.CasperEvent.global.config; | ||
|
||
import JGS.CasperEvent.global.util.AESUtils; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import javax.crypto.SecretKey; | ||
|
||
@Configuration | ||
public class SecurityConfig { | ||
|
||
@Value("${spring.encryption.key}") | ||
private String encryptionKey; | ||
|
||
@Bean | ||
public SecretKey secretKey() { | ||
return AESUtils.stringToKey(encryptionKey); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
Server/src/main/java/JGS/CasperEvent/global/util/AESUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package JGS.CasperEvent.global.util; | ||
|
||
import javax.crypto.*; | ||
import javax.crypto.spec.SecretKeySpec; | ||
import java.security.InvalidKeyException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.Base64; | ||
|
||
public class AESUtils { | ||
|
||
public static SecretKey stringToKey(String keyString) { | ||
byte[] decodedKey = keyString.getBytes(); | ||
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); | ||
} | ||
|
||
public static String encrypt(String plainText, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { | ||
Cipher cipher = Cipher.getInstance("AES"); | ||
cipher.init(Cipher.ENCRYPT_MODE, key); | ||
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes()); | ||
return Base64.getEncoder().encodeToString(encryptedBytes); | ||
} | ||
|
||
public static String decrypt(String encryptedText, SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { | ||
Cipher cipher = Cipher.getInstance("AES"); | ||
cipher.init(Cipher.DECRYPT_MODE, key); | ||
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText)); | ||
return new String(decryptedBytes); | ||
} | ||
|
||
|
||
} |
25 changes: 25 additions & 0 deletions
25
Server/src/main/java/JGS/CasperEvent/global/util/Base62Utils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package JGS.CasperEvent.global.util; | ||
|
||
public class Base62Utils { | ||
private static final String BASE62_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
|
||
public static String encode(long number) { | ||
if (number == 0) return Character.toString(BASE62_CHARS.charAt(0)); | ||
|
||
StringBuilder sb = new StringBuilder(); | ||
while (number > 0) { | ||
int reminder = (int) (number % 62); | ||
sb.append(BASE62_CHARS.charAt(reminder)); | ||
number /= 62; | ||
} | ||
return sb.reverse().toString(); | ||
} | ||
|
||
public static long decode(String str){ | ||
long result = 0; | ||
for (int i = 0; i < str.length(); i++) { | ||
result = result * 62 + BASE62_CHARS.indexOf(str.charAt(i)); | ||
} | ||
return result; | ||
} | ||
} |
80 changes: 0 additions & 80 deletions
80
Server/src/main/java/JGS/CasperEvent/global/util/GsonUtil.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.