mirror of
https://github.com/0xShay/halflink.git
synced 2026-01-11 13:13:25 +00:00
Initialise Spring API with ShortLink endpoints
This commit is contained in:
3
backend/.gitignore
vendored
Normal file
3
backend/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
target/
|
||||||
|
|
||||||
|
.idea/
|
||||||
50
backend/pom.xml
Normal file
50
backend/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>services.shay</groupId>
|
||||||
|
<artifactId>halflink</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>4.0.1</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
<version>3.3.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
21
backend/src/main/java/services/shay/Halflink.java
Normal file
21
backend/src/main/java/services/shay/Halflink.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package services.shay;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Halflink {
|
||||||
|
|
||||||
|
@GetMapping("/")
|
||||||
|
String home() {
|
||||||
|
return "Halflink API says hello!";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Halflink.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package services.shay.shortlink;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class ShortCodeGenerator {
|
||||||
|
|
||||||
|
private static final String BASE_58_CHARS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
|
public static String generate(int length) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
sb.append(BASE_58_CHARS.charAt(RANDOM.nextInt(BASE_58_CHARS.length())));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generate() {
|
||||||
|
return "abc";
|
||||||
|
// return generate(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
58
backend/src/main/java/services/shay/shortlink/ShortLink.java
Normal file
58
backend/src/main/java/services/shay/shortlink/ShortLink.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package services.shay.shortlink;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Null;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "shortlink", uniqueConstraints = { @UniqueConstraint(columnNames = { "code" }) })
|
||||||
|
public class ShortLink {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
private Integer clicks;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
protected ShortLink() {}
|
||||||
|
|
||||||
|
public ShortLink(String url, String title) {
|
||||||
|
this.url = url;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PrePersist
|
||||||
|
protected void onCreate() {
|
||||||
|
createdAt = new Date();
|
||||||
|
clicks = 0;
|
||||||
|
code = ShortCodeGenerator.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId() { return id; }
|
||||||
|
public String getUrl() { return url; }
|
||||||
|
public String getTitle() { return title; }
|
||||||
|
public Date getCreatedAt() { return createdAt; }
|
||||||
|
public Integer getClicks() { return clicks; }
|
||||||
|
public String getCode() { return code; }
|
||||||
|
|
||||||
|
public void setId(UUID id) { this.id = id; }
|
||||||
|
public void setUrl(String url) { this.url = url; }
|
||||||
|
public void setTitle(String title) { this.title = title; }
|
||||||
|
public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
|
||||||
|
public void setClicks(Integer clicks) { this.clicks = clicks; }
|
||||||
|
public void setCode(String code) { this.code = code; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package services.shay.shortlink;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/sl")
|
||||||
|
public class ShortLinkController {
|
||||||
|
|
||||||
|
private final ShortLinkRepository shortLinkRepository;
|
||||||
|
|
||||||
|
public ShortLinkController(ShortLinkRepository shortLinkRepository) {
|
||||||
|
this.shortLinkRepository = shortLinkRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{code}")
|
||||||
|
public ResponseEntity<Void> redirectToUrl(@PathVariable String code) {
|
||||||
|
ShortLink sl = shortLinkRepository.findByCode(code).orElse(null);
|
||||||
|
if (sl != null) {
|
||||||
|
sl.setClicks(sl.getClicks() + 1);
|
||||||
|
shortLinkRepository.save(sl);
|
||||||
|
return ResponseEntity
|
||||||
|
.status(HttpStatus.FOUND)
|
||||||
|
.location(URI.create(sl.getUrl()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ShortLink createShortLink(@Valid @RequestBody ShortLink shortLink) {
|
||||||
|
ShortLink savedShortLink = shortLinkRepository.save(shortLink);
|
||||||
|
System.out.println("savedShortLink = " + savedShortLink);
|
||||||
|
return savedShortLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void deleteShortLink(@PathVariable UUID id) {
|
||||||
|
shortLinkRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package services.shay.shortlink;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ShortLinkRepository extends JpaRepository<ShortLink, UUID> {
|
||||||
|
|
||||||
|
Optional<ShortLink> findByCode(String code);
|
||||||
|
|
||||||
|
}
|
||||||
8
backend/src/main/resources/application.properties
Normal file
8
backend/src/main/resources/application.properties
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Database connection
|
||||||
|
spring.datasource.url=jdbc:postgresql://localhost:5432/halflink
|
||||||
|
spring.datasource.username=springchatuser
|
||||||
|
spring.datasource.password=abcdef
|
||||||
|
|
||||||
|
# JPA/Hibernate settings
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.show-sql=true
|
||||||
11
backend/src/main/resources/sandbox.http
Normal file
11
backend/src/main/resources/sandbox.http
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
POST http://localhost:8080/sl
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"url": "https://docs.spring.io/spring-security/reference/servlet/authentication/index.html",
|
||||||
|
"title": "Spring Security Servlet Authentication"
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
DELETE http://localhost:8080/sl/a0232bf3-245d-4515-8a8b-c10031d21766
|
||||||
Reference in New Issue
Block a user