Similar to Pastebin, this web application allows users to share plain text and code snippets without requiring a user account. It's useful in the following situations:
- Save frequently used code
- Share code snippets with others
- Refer to code shared by others
URL: text-snippet.taesokkwon.com
snippets-step1.mov
The paste is no longer available after the expiration time.
snippets-expired.mov
| Category | Technology |
|---|---|
| VM | Amazon EC2 |
| Web server | Nginx |
| Frontend | HTML, JavaScript, Bootstrap CSS |
| Backend | PHP 8.3 |
| Database | Amazon RDS (MySQL 8.0) |
| Middleware | Custom-built migration tool |
| CI/CD | GitHub Actions |
| QA/Testing | - PHP CS Fixer (code formatting) - PHPStan (linter) - PHPUnit (unit testing) |
| Tools | Monaco Editor |
| Container | Docker (for local development) |
The application checks content size before submission. If the content size exceeds the limit, the application will return an error message. This feature prevents users from submitting excessively large content.
// php ini configuration
post_max_size = 8M
memory_limit = 128M
max_input_time = 60
max_execution_time = 30For testing, post_max_size was intentionally set to a low limit (2KB) to verify the validation functionality. In production, the limit is set to 8MB to accommodate larger code snippets while still protecting against potential abuse.
- Special characters (
\n,\t,\',\",\) are properly escaped/unescaped using PHP'sjson_encode()andjson_decode()methods. - All database inputs are parameterized using
mysqliprepared statements to prevent SQL injection. - HTML special characters are escaped using
htmlspecialchars()when displaying titles and metadata.
The application limits requests based on the client's IP address.
// Nginx configuration
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m;
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php index.html index.htm;
...
location = /api/paste {
limit_req zone=one;
try_files $uri $uri/ /index.php?$query_string;
}
...
}
For testing, the rate limit was intentionally set to a low value (2 requests per minute + no burst) to verify the rate-limiting functionality. In production, the limit is set to 10 requests per minute (+ burst=5 nodelay) to accommodate normal API usage while protecting against potential abuse.
snippets-503error.mov
Each paste's URL (https://{domain}/{hash_id}) is generated using a cryptographically secure random ID via PHP's random_bytes() function.
This implementation follows Latacora's Cryptographic Right Answers and utilizes /dev/urandom.
The implementation uses:
- A character set of 64 characters for URL-safe encoding
- 8 characters length for the final hash
- Total possible combinations: 64βΈ = 281,474,976,710,656
This project uses GitHub Actions for two separate workflows:
Located in .github/workflows/ci.yml, the CI workflow runs on pushes to the main branch (and other specified triggers). It:
- Installs and caches dependencies via Composer
- Performs PHP CS Fixer checks for code style
- Performs PHPStan static analysis for code quality
- Runs PHPUnit unit tests to verify functionality
Located in .github/workflows/cd.yml, the CD workflow is triggered automatically only if the CI workflow succeeds. It:
- Uses GitHub Actions OpenID Connect to assume a short-lived AWS role
- Runs commands remotely via AWS Systems Manager (SSM) to pull and deploy changes on the EC2 instance (no direct SSH access or security group changes)
- Updates Composer dependencies on the server and restarts services (PHP-FPM, Nginx)
This project uses Docker for local development, making it easy for anyone to run and test the application on their local machine.
- Clone this repository
git clone https://github.com/tkwonn/text-snippet.git
cd text-snippet- Setup the environment variables
# Copy the example environment file
cp .env.example .env
# Example of .env file content
DATABASE_HOST=mysql
DATABASE_NAME=pastes
DATABASE_USER=user
DATABASE_USER_PASSWORD=password
DATABASE_ROOT_PASSWORD=root_password- Build and run the containers
make build
make up
# Initialize the database
make migrate
make seedThe application will be available at http://localhost:8080

