A robust and efficient URL shortener service built with Java and Spring Boot. This application allows users to convert long URLs into short, manageable links. It provides features like custom aliases, expiration dates, and click tracking. The service is designed with a clean architecture, comprehensive test coverage, and a full CI/CD pipeline for automated testing and deployment.
- URL Shortening: Generate unique, short codes (Base62) for long URLs.
- Custom Aliases: Create personalized and memorable short links.
- Expiration Control: Set an expiration period for temporary links.
- Redirection: Seamlessly redirects users from the short link to the original long URL.
- Analytics: Tracks the number of clicks and the last accessed time for each link.
- REST API: A well-defined API for creating and managing short URLs.
- Rate Limiting: Protects the creation endpoint from abuse with IP-based rate limiting (10 requests/minute).
- Scheduled Cleanup: Automatically removes expired URLs from the database daily.
- Containerized: Includes a
Dockerfilefor easy deployment and scaling. - CORS Support: Configured for integration with web frontends (e.g., from
localhost:3000(for testing) andcemtbi.github.io).
- Backend: Java 17, Spring Boot, Spring Data JPA, Spring Web
- Database: PostgreSQL (Production), H2 (Testing)
- Build: Maven
- Testing: JUnit 5, Mockito, Testcontainers
- API Documentation: Springdoc OpenAPI (Swagger UI)
- Others: Lombok, Bucket4j (Rate Limiting)
- DevOps: Docker, GitHub Actions
The service exposes REST endpoints for managing URLs. The full API documentation is available via Swagger UI at /swagger-ui.html when the application is running.
- Endpoint:
POST /api/urls - Description: Creates a new short URL.
- Request Body:
{ "url": "https://github.com/CemTbi/UrlShortener", "alias": "my-repo", // Optional: 3-32 alphanumeric characters and underscores "expiryDays": 7 // Optional: Number of days until the link expires } - Responses:
201 Created: Successfully created the short URL. The response body contains the details of the created link.400 Bad Request: Invalid request body (e.g., malformed URL, invalid alias).429 Too Many Requests: Triggered if the rate limit is exceeded.
- Endpoint:
GET /api/urls/{code} - Description: Retrieves the details of a specific short URL without redirecting.
- Path Variable:
code: The unique code or alias of the short URL.
- Responses:
200 OK: Returns the short URL details.404 Not Found: The specified code does not exist or has expired.
- Endpoint:
GET /{code} - Description: Redirects the user to the original long URL associated with the code and increments the click count.
- Path Variable:
code: The unique code or alias of the short URL.
- Responses:
302 Found: Redirects to the original URL.404 Not Found: The specified code does not exist or has expired.
- Java 17
- Maven
- Docker (for containerized deployment)
-
Clone the repository:
git clone https://github.com/CemTbi/UrlShortener.git cd UrlShortener -
Run the application using the Maven wrapper:
./mvnw spring-boot:run
The application will start using the
testprofile by default, which connects to an in-memory H2 database.- Application:
http://localhost:10000 - H2 Console:
http://localhost:10000/h2-console - Swagger UI:
http://localhost:10000/swagger-ui.html
- Application:
The repository includes a Dockerfile to build and run the application in a container.
-
Build the Docker image:
docker build -t urlshortener . -
Run the container. For production use, you must provide the database connection details as environment variables and activate the
prodprofile.docker run -p 10000:10000 \ -e SPRING_PROFILES_ACTIVE=prod \ -e DB_HOST=<your_db_host> \ -e DB_NAME=<your_db_name> \ -e DB_USER=<your_db_user> \ -e DB_PASSWORD=<your_db_password> \ urlshortener
The application uses Spring Profiles to manage different configurations:
application-test.properties: (Default) Uses an in-memory H2 database for local development and testing.application-prod.properties: Configured for a PostgreSQL database. It requires the following environment variables:DB_HOST: The hostname of the PostgreSQL server.DB_NAME: The database name.DB_USER: The database user.DB_PASSWORD: The user's password.PORT: (Optional) The port for the application server.
The project is equipped with a comprehensive suite of unit and integration tests.
To run all tests, execute the following command from the root directory:
./mvnw verifyTest coverage reports for both unit and integration tests are generated by JaCoCo in the target/site/ directory.
This repository is configured with GitHub Actions to automate the build, test, and deployment process. The workflows handle:
- Running builds, unit tests, and integration tests on every push and pull request.
- Performing static code analysis with SonarCloud.
- Scanning for vulnerabilities in code and Docker images with Trivy.
- Building and pushing the Docker image to GitHub Container Registry (GHCR) on pushes to the
mainbranch.
This project is licensed under the MIT License. See the LICENSE file for details.