{"id":22306553,"url":"https://github.com/vietdoo/url-shortening-ruby","last_synced_at":"2026-02-17T00:32:52.850Z","repository":{"id":263937386,"uuid":"891654777","full_name":"vietdoo/url-shortening-ruby","owner":"vietdoo","description":"This is a simple URL shortening service that takes a long URL and converts it into a short URL. The short URL can be used to redirect to the original long URL. Using Ruby on Rails","archived":false,"fork":false,"pushed_at":"2025-02-21T06:33:43.000Z","size":187,"stargazers_count":1,"open_issues_count":11,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-14T17:32:24.698Z","etag":null,"topics":["postgresql","rails","ruby","ruby-on-rails","sqlite3","url-shortener","url-shortener-api","urlshortener"],"latest_commit_sha":null,"homepage":"https://shorturl.vietdoo.me/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vietdoo.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-20T18:04:10.000Z","updated_at":"2024-11-28T10:38:37.000Z","dependencies_parsed_at":"2025-10-14T17:31:10.168Z","dependency_job_id":"362b103a-5672-48b9-9478-58ffeb8d27cd","html_url":"https://github.com/vietdoo/url-shortening-ruby","commit_stats":null,"previous_names":["vietdoo/url-shortening-ruby"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vietdoo/url-shortening-ruby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vietdoo%2Furl-shortening-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vietdoo%2Furl-shortening-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vietdoo%2Furl-shortening-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vietdoo%2Furl-shortening-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vietdoo","download_url":"https://codeload.github.com/vietdoo/url-shortening-ruby/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vietdoo%2Furl-shortening-ruby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29526791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T21:45:09.491Z","status":"ssl_error","status_checked_at":"2026-02-16T21:44:58.452Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["postgresql","rails","ruby","ruby-on-rails","sqlite3","url-shortener","url-shortener-api","urlshortener"],"created_at":"2024-12-03T19:27:56.222Z","updated_at":"2026-02-17T00:32:52.821Z","avatar_url":"https://github.com/vietdoo.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"## URL SHORTENING SERVICE\n\n**Live Demo**: [URL Shortening Service](https://shorturl.vietdoo.me/)\n`Note: With render.com's free tier web service, it may take a few seconds upto few minutes to wake up the server`\n\n### Description\nThis is a simple URL shortening service that takes a long URL and converts it into a short URL. The short URL can be used to redirect to the original long URL. Using Ruby on Rails, the service is built with a RESTful API that can be used to create, read short URLs.\n\n\n## Features\n\n- Shorten long URLs into compact, shareable links\n- Custom short code support\n- URL expiration \n- Data stored in a database.\n- User authentication with Devise\n- API endpoints for URL encoding/decoding\n- URL history tracking\n- Security protections against common attacks\n- Rate limiting for API endpoints\n- Continuous integration and deployment pipelines\n\n### Prerequisites\n- Ruby 3.2.2\n- Rails 8.0.0\n- SQLite3 (development)\n- Postgres (optional, for production deployment)\n- Docker (optional, for containerized deployment)\n\n### Installation\n\n1. **Clone the repository:**\n    ```sh\n    git clone https://github.com/your-username/url-shortening-service.git\n    cd url-shortening-service\n    ```\n\n2. **Install dependencies:**\n    ```sh\n    bundle install\n    ```\n\n3. **Set up the database:**\n    ```sh\n    rails db:setup\n    rails db:migrate\n    ```\n\n4. **Run the server:**\n    ```sh\n    rails s\n    ```\n\n5. **Access the web application:**\n    Open your browser and navigate to `http://localhost:3000`.\n\n### Usage\n\n\nThe application provides both a web interface and API endpoints:\n\n# Web Interface Overview\n\n- **Create Short URLs**:  \n  Access the homepage at `/` to create a new short URL. Enter the original URL, custom short code (optional), and expiration date (optional) to generate a short URL.\n\n- **View Shortened URL Results**:  \n  Visit `/shortened-url-result?id={unique-id}` to view the details of a specific short URL. This page is automatically displayed after a new short URL is created.  \n\n- **Redirect to Original URL**:  \n  Visit the short URL path (e.g., `/abc123`) to be redirected to the original long URL.\n\n- **User Authentication**:  \n  - Login: `/users/sign_in`  \n  - Register: `/users/sign_up`  \n\n- **View URL History**:  \n  Access `/users/history` to see a list of all shortened URLs created by the user.\n\n---\n\n### API Endpoints\n\n#### Encode URL\nCreate a shortened version of a given URL.\n\n`POST /api/v1/encode`\n\nPass all parameters in the url object.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| original_url | string | The original URL to shorten |\n| short_code | string | The custom short code (optional) |\n| expiration_days | integer | The number of days until the short URL expires (optional) |\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/encode \\\n  -H \"Content-Type: application/json\" \\\n  -d '\"url\": {\n        \"expiration_days\": 10,\n        \"original_url\": \"https://oivan.com/\",\n        \"short_code\": \"\"\n    }'\n```\n\n#### Response\n```json\n{\n    \"status\": \"ok\",\n    \"data\": {\n        \"original_url\": \"https://oivan.com/\",\n        \"short_code\": \"5CmsQZbd\",\n        \"short_url\": \"http://localhost:3000/5CmsQZbd\",\n        \"time_expired\": \"2024-12-25T13:47:30.558+07:00\",\n        \"result_page\": \"http://127.0.0.1:3000/shortened-url-result?id=f88102ae-20af-4d40-ad3a-6ba2304d2fee\"\n    },\n    \"message\": \"URL shortened successfully!\"\n}\n```\n\n#### Decode URL\n`POST /api/v1/decode`\n\n#### Parameters\nPass all parameters in the url object.\n\n| Parameter | Type | Description |\n| --- | --- | --- |\n| short_code | string | The short code to decode|\n\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/decode \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": {\"short_code\": \"5CmsQZbd\"}}'\n```\n#### Response\n```json\n{\n    \"status\": \"ok\",\n    \"data\": {\n        \"original_url\": \"https://oivan.com/\",\n        \"short_code\": \"5CmsQZbd\",\n        \"short_url\": \"http://127.0.0.1:3000/5CmsQZbd\",\n        \"time_expired\": \"2024-12-25T13:47:30.558+07:00\",\n        \"result_page\": \"http://localhost:3000/shortened-url-result?id=f88102ae-20af-4d40-ad3a-6ba2304d2fee\"\n    },\n    \"message\": \"URL decoded successfully!\"\n}\n```\n\n\n### My Implementation\n\n#### Architecture\n\n1. **Controllers**:\n   - **API Controllers**: Handle API requests and responses.\n     - Located in `app/controllers/api/v1/`\n     - Example: `EncodingController`, `DecodingController`\n   - **Web Controllers**: Handle web requests for the user interface.\n     - Located in `app/controllers/web/`\n     - Example: `ShorteningController`\n\n2. **Models**:\n   - Represent the data and business logic of the application.\n   - Located in `app/models/`\n   - Example: `Url`, `User`\n\n3. **Services**:\n   - Encapsulate complex business logic and operations.\n   - Located in `app/services/`\n   - Example: `UrlEncodingService`, `UrlDecodingService`\n\n4. **Forms**:\n   - Handle form submissions and validations.\n   - Located in `app/forms/`\n   - Example: `UrlEncodeForm`\n\n5. **Serializers**:\n   - Format JSON responses for API endpoints.\n   - Located in `app/serializers/`\n   - Example: `UrlSerializer`, `ErrorSerializer`\n\n6. **Views**:\n   - Contain the HTML templates for rendering the user interface.\n   - Located in `app/views/`\n   - Example: `web/shortening/index.html.erb`\n\n\n#### URL Shortening Algorithm\n\n- **Short Code Generation:**\nShort codes are generated using a combination of characters and numbers: `A-Z`, `a-z`, `0-9` = 26 + 26 + 10 = 62 characters with length random [5..8], which results in a total of 62^5 + 62^6 + 62^7 + 62^8 possible combinations. This total is nearly **221.9 Trillion** possible combinations.\n\n- **Collision Handling:**\nTo handle collisions, the application checks if the generated short code already exists in the database. If a collision is detected, the application generates a new short code until a unique one is found.\n\n- **Expiration:**\nShort URLs can be set to expire after a certain number of days. The application checks the expiration date when redirecting to the original URL and returns an error if the short URL has expired.\n\n#### User Authentication\n\n- **Devise Gem:**\nUser authentication is implemented using the Devise gem. Users can register, log in, and log out of the application.\n\n\n#### API Endpoints\nUsing the Rails API mode, the application provides RESTful API endpoints for encoding and decoding URLs.\n\n#### Database Schema\nThe application uses a SQLite database in development and can be configured to use Postgres in production. The database schema includes tables for users, urls. \n\n#### CI/CD\nThe application can be set up with continuous integration and continuous deployment pipelines using GitHub Actions for automated testing. If the tests pass and the code is on the `main` branch, the workflow triggers a deployment.\n\n\n#### Security \n\n**SQL Injection:**\nUse parameterized queries to prevent SQL injection attacks.\nValidate and sanitize all user inputs.\n\n**Cross-Site Scripting (XSS):**\nUse Rails' built-in helpers to escape HTML.\nValidate and sanitize user inputs.\n\n**Cross-Site Request Forgery (CSRF):**\nEnable CSRF protection in Rails.\nUse authenticity tokens in forms.\n**Rate Limiting:**\nUsing the Rack::Attack gem to implement rate limiting for API endpoints.\n\n**Data Validation:**\nValidate URLs to ensure they are well-formed.\n\n### Future Improvements\n\n**Caching.**\nUsing a caching mechanism like Redis to store frequently accessed URLs and reduce database load.\n\n**Load Balancing:**\nImplement load balancing to distribute traffic across multiple servers.\n\n**Database Sharding:**\nShard the database to distribute data across multiple servers and improve performance.\n\n**Tracking and Analytics:**\nImplement tracking and analytics to monitor user activity and improve the service.\n\n\n**Monitoring:**\nSet up monitoring tools to track application performance and detect issues.\n\n**Logging:**\nImplement logging to track user activity and debug issues.\n\n**More Efficient Collision Handling:**\nDevelop a more efficient collision handling algorithm to reduce the risk of collisions when the number of short URLs increases.\n\n\n### Deployment\n\n1. **Using Docker:**\n    - Build the Docker image:\n        ```sh\n        docker build -t url-shortening-service .\n        ```\n    - Run the Docker container:\n        ```sh\n        docker run -p 3000:3000 url-shortening-service\n        ```\n\n2. **Using a Cloud Service:**\n    - Deploy the application to a cloud service like Heroku.\n    - Set up environment variables and database configurations as needed.\n\n### Testing\n\n- **Run the test suite:**\n    ```sh\n    rails test\n    ```\n\n### Contributing\n\n- Fork the repository.\n- Create a new branch for your feature or bug fix.\n- Write tests for your changes.\n- Submit a pull request.\n\n### License\n\nThis project is licensed under the MIT License. See the LICENSE file for details.\n\n---\n\nThis README provides detailed instructions on how to set up, use, and deploy the URL shortening service. It includes information on features, prerequisites, installation, usage, API endpoints, architecture, security, future improvements, deployment, testing.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvietdoo%2Furl-shortening-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvietdoo%2Furl-shortening-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvietdoo%2Furl-shortening-ruby/lists"}