Introduction
URL shortening services have been around for quite some time now, with services like TinyURL and Bitly helping users convert long, cumbersome URLs into shorter, easy-to-share links. In this blog, I'll walk you through the process of creating your own TinyURL-like service using Spring Boot on the backend and React and TypeScript for the frontend. By the end, you'll have a functional URL shortening service to call your own!
Technologies
Backend: Java, Spring Boot, Maven
Frontend: React, TypeScript, Axios
Backend: Java and Spring Boot
To get started with our backend, we'll use Spring Boot, a popular Java framework for building web applications. Spring Boot allows us to create a RESTful API with minimal boilerplate code.
Setting up the project
- Create a new Spring Boot project using the Spring Initializer: https://start.spring.io/
- Select Java 17, Maven, and add the following dependencies: Spring Web, Lombok.
- Download the project and unzip it into your desired directory.
Implementing the backend logic
Our backend will have the following structure:
- Url: A Java class representing the URL entity.
- UrlRepository: A Java interface to manage the persistence of our URL entities.
- UrlService: A Java class responsible for handling the business logic.
- UrlController: A Java class responsible for handling incoming HTTP requests.
Url.java
@Entity
public class Url {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String originalUrl;
private String shortUrl;
// Add constructors, getters, and setters
}
UrlRepository.java
public interface UrlRepository extends JpaRepository<Url, Long> {
Url findByShortUrl(String shortUrl);
Url findByOriginalUrl(String originalUrl);
}
UrlService.java
@Service
public class UrlService {
private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int SHORT_URL_LENGTH = 8;
@Autowired
private UrlRepository urlRepository;
private String generateRandomShortUrl() {
StringBuilder shortUrlBuilder = new StringBuilder(SHORT_URL_LENGTH);
Random random = new Random();
for (int i = 0; i < SHORT_URL_LENGTH; i++) {
int index = random.nextInt(ALPHABET.length());
shortUrlBuilder.append(ALPHABET.charAt(index));
}
return shortUrlBuilder.toString();
}
public Url createUrl(String originalUrl){
String shortUrl;
Url url;
do {
shortUrl = generateRandomShortUrl();
url = urlRepository.findByShortUrl(shortUrl);
}while (url != null);
url = new Url();
url.setOriginalUrl(originalUrl);
url.setShortUrl(shortUrl);
return urlRepository.save(url);
}
public Url getUrlByShortUrl(String shortUrl){
return urlRepository.findByShortUrl(shortUrl);
}
}
UrlController.java
@RestController
@RequestMapping("/api")
public class UrlController {
@Autowired
private UrlService urlService;
@PostMapping("/createUrl")
public ResponseEntity<Url> createUrl(@RequestParam("url") String originalUrl) {
try {
new URL(originalUrl);
} catch (MalformedURLException e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
Url newUrl = urlService.createUrl(originalUrl);
if (newUrl != null) {
return new ResponseEntity<>(newUrl, HttpStatus.CREATED);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
@GetMapping("/{shortUrl}")
public void redirectToOriginalUrl(@PathVariable String shortUrl, HttpServletResponse response) {
Url url = urlService.getUrlByShortUrl(shortUrl);
if (url != null) {
response.setHeader("Location", url.getOriginalUrl());
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
}
}
Frontend: React and TypeScript
For our frontend, we'll use React, a popular JavaScript library for building user interfaces, and TypeScript, a statically typed superset of JavaScript that adds types to the language.
Setting up the project
Create a new React project with TypeScript in your terminal:
npx create-react-app tinyurl-frontend --template typescript
Navigate to the tinyurl-frontend directory and install Axios, a library to make HTTP requests:
npm install axios
Implementing the frontend logic
Our frontend application will have a simple form for users to enter a long URL and receive a short URL in return. We'll use Axios to make requests to our backend API.
- Create a new file CreateUrlForm.tsx and define a functional component to render the form.
import React, { useState } from "react";
import axios from "axios";
const CreateUrlForm: React.FC = () => {
const [originalUrl, setOriginalUrl] = useState("");
const [shortUrl, setShortUrl] = useState("");
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const apiUrl = "http://localhost:8080";
const response = await axios.post(`${apiUrl}/api/createUrl`, null, {
params: {
url: originalUrl,
},
});
setShortUrl(response.data.shortUrl);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Original URL:
<input
type="text"
value={originalUrl}
onChange={(event) => setOriginalUrl(event.target.value)}
/>
</label>
<button type="submit">Shorten</button>
</form>
{shortUrl && <p>Short URL: {shortUrl}</p>}
</div>
);
};
export default CreateUrlForm;
- Update src/App.tsx to include the CreateUrlForm component:
import React from "react";
import CreateUrlForm from "./CreateUrlForm";
import "./App.css";
function App() {
return (
<div className="App">
<header className="App-header">
<h1>TinyURL Clone</h1>
</header>
<main>
<CreateUrlForm />
</main>
</div>
);
}
export default App;
Now, we have a simple frontend that allows users to shorten URLs.
Conclusion
In this blog post, we've covered how to create a simple URL shortening service using Java/Spring Boot and React/TypeScript. This application is just the beginning, and you can expand it with additional features such as custom short URLs, URL analytics, and more. With the basic foundation in place, you can continue to build and refine your application to meet your needs.
I hope you found this tutorial helpful in getting started with building your own TinyURL-like service. Good luck, and happy coding!
Top comments (0)