@dytsou/shorten-url 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +359 -0
- package/config/config.example.js +118 -0
- package/config/config.js +101 -0
- package/docs/api/index.html +34 -0
- package/docs/api/openapi.yaml +150 -0
- package/docs/index.html +728 -0
- package/package.json +52 -0
- package/src/worker.example.js +376 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dytsou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# URL Shortener
|
|
2
|
+
|
|
3
|
+
A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface. This project allows anyone to create short URLs with optional custom slugs, featuring a clean UI and robust backend with comprehensive API documentation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **URL Shortening**: Convert long URLs into short, shareable links
|
|
8
|
+
- **Custom Slugs**: Create personalized short URLs (optional)
|
|
9
|
+
- **Protected Shortening**: Short URL creation is protected behind Cloudflare Access / WARP for safer usage
|
|
10
|
+
- **Responsive Design**: Works seamlessly on desktop and mobile devices
|
|
11
|
+
- **Fast Performance**: Built on Cloudflare Workers for global edge deployment
|
|
12
|
+
- **Security Features**: URL validation, rate limiting, and optional Safe Browsing integration
|
|
13
|
+
- **Modern Copy Function**: One-click copying with fallbacks for all browsers
|
|
14
|
+
- **Custom Error Pages**: Beautiful 404, security warning, and redirect pages (fully customizable via your GitHub Pages)
|
|
15
|
+
- **API Documentation**: Interactive Swagger UI with OpenAPI 3.1.0 specification
|
|
16
|
+
- **Analytics Ready**: Optional click tracking and analytics integration
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
- A Cloudflare account with Workers enabled
|
|
23
|
+
- GitHub account for hosting the frontend (or any static hosting)
|
|
24
|
+
- Basic knowledge of Git and command line
|
|
25
|
+
|
|
26
|
+
### 1. Clone the Repository
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/dytsou/shorten-url.git
|
|
30
|
+
cd shorten-url
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Setup Configuration
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Copy the example configuration
|
|
37
|
+
cp config/config.example.js config/config.js
|
|
38
|
+
|
|
39
|
+
# Edit the configuration file
|
|
40
|
+
vim config/config.js
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Update the `config/config.js` file with your settings:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const config = {
|
|
47
|
+
frontend: {
|
|
48
|
+
// IMPORTANT: Update this to your GitHub Pages URL or custom domain
|
|
49
|
+
url: "https://yourusername.github.io/shorten-url/",
|
|
50
|
+
},
|
|
51
|
+
// ... other settings
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Deploy Frontend
|
|
56
|
+
|
|
57
|
+
#### Option A: GitHub Pages (Recommended)
|
|
58
|
+
|
|
59
|
+
1. Push your code to GitHub
|
|
60
|
+
2. Go to your repository settings
|
|
61
|
+
3. Enable GitHub Pages for the main branch
|
|
62
|
+
4. Your frontend will be available at `https://yourusername.github.io/shorten-url/`
|
|
63
|
+
|
|
64
|
+
#### Option B: Custom Domain
|
|
65
|
+
|
|
66
|
+
1. Upload the `docs/` directory to your web hosting
|
|
67
|
+
2. Update the `frontend.url` in `config/config.js` to match your domain
|
|
68
|
+
|
|
69
|
+
### 4. Setup Cloudflare Workers
|
|
70
|
+
|
|
71
|
+
#### Install Wrangler CLI
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install -g wrangler
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Configure Wrangler
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Login to Cloudflare
|
|
81
|
+
wrangler auth login
|
|
82
|
+
|
|
83
|
+
# Create a new KV namespace for storing URLs
|
|
84
|
+
wrangler kv:namespace create "LINKS"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Create wrangler.toml
|
|
88
|
+
|
|
89
|
+
Create a `wrangler.toml` file in your project root:
|
|
90
|
+
|
|
91
|
+
```toml
|
|
92
|
+
name = "url-shortener"
|
|
93
|
+
main = "src/worker.js"
|
|
94
|
+
compatibility_date = "2024-01-01"
|
|
95
|
+
|
|
96
|
+
[[kv_namespaces]]
|
|
97
|
+
binding = "LINKS"
|
|
98
|
+
id = "your-kv-namespace-id-here"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Replace `your-kv-namespace-id-here` with the ID from the KV namespace creation command.
|
|
102
|
+
|
|
103
|
+
#### Deploy the Worker
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
wrangler deploy
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 5. Update Configuration
|
|
110
|
+
|
|
111
|
+
After deploying, update your `config/config.js` with the worker URL:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
const config = {
|
|
115
|
+
frontend: {
|
|
116
|
+
url: "https://yourusername.github.io/shorten-url/",
|
|
117
|
+
},
|
|
118
|
+
// ... other settings
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## ⚙️ Configuration Options
|
|
123
|
+
|
|
124
|
+
### Frontend Configuration
|
|
125
|
+
|
|
126
|
+
| Option | Description | Default |
|
|
127
|
+
| ------------------------ | --------------------------------------- | -------- |
|
|
128
|
+
| `frontend.url` | URL where your frontend is hosted | Required |
|
|
129
|
+
| `frontend.displayDomain` | Domain shown in UI (null = auto-detect) | `null` |
|
|
130
|
+
| `frontend.theme` | UI theme selection | `""` |
|
|
131
|
+
|
|
132
|
+
### Worker Configuration
|
|
133
|
+
|
|
134
|
+
| Option | Description | Default |
|
|
135
|
+
| ------------------------------- | --------------------------------- | ---------- |
|
|
136
|
+
| `worker.no_ref` | Hide HTTP referrer header | `"off"` |
|
|
137
|
+
| `worker.cors` | Enable CORS for API requests | `"on"` |
|
|
138
|
+
| `worker.unique_link` | Same URL = same short link | `true` |
|
|
139
|
+
| `worker.custom_link` | Allow custom slugs | `true` |
|
|
140
|
+
| `worker.safe_browsing_api_key` | Google Safe Browsing API key | `""` |
|
|
141
|
+
| `worker.min_random_key_length` | Minimum length for generated keys | `6` |
|
|
142
|
+
| `worker.max_custom_slug_length` | Maximum length for custom slugs | `50` |
|
|
143
|
+
| `worker.reserved_slugs` | List of reserved slugs | See config |
|
|
144
|
+
|
|
145
|
+
### Security Configuration
|
|
146
|
+
|
|
147
|
+
| Option | Description | Default |
|
|
148
|
+
| -------------------------- | -------------------------- | ------- |
|
|
149
|
+
| `security.rate_limit` | Requests per minute per IP | `10` |
|
|
150
|
+
| `security.validate_urls` | Enable URL validation | `true` |
|
|
151
|
+
| `security.blocked_domains` | List of blocked domains | `[]` |
|
|
152
|
+
|
|
153
|
+
### Storage Configuration
|
|
154
|
+
|
|
155
|
+
| Option | Description | Default |
|
|
156
|
+
| ---------------------- | ------------------------- | --------- |
|
|
157
|
+
| `storage.binding_name` | KV namespace binding name | `"LINKS"` |
|
|
158
|
+
|
|
159
|
+
## 🔧 Advanced Setup
|
|
160
|
+
|
|
161
|
+
### Custom Domain
|
|
162
|
+
|
|
163
|
+
1. Add a custom domain in Cloudflare Workers dashboard
|
|
164
|
+
2. Update your DNS records to point to Cloudflare
|
|
165
|
+
3. Update the worker URL in your configuration
|
|
166
|
+
|
|
167
|
+
### Google Safe Browsing
|
|
168
|
+
|
|
169
|
+
1. Get an API key from [Google Cloud Console](https://developers.google.com/safe-browsing/v4/get-started)
|
|
170
|
+
2. Add the key to your `config.js`:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
worker: {
|
|
174
|
+
safe_browsing_api_key: "your-api-key-here",
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Analytics Integration
|
|
179
|
+
|
|
180
|
+
Configure analytics in your `config.js`:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
analytics: {
|
|
184
|
+
enable_tracking: true,
|
|
185
|
+
ga_tracking_id: "G-XXXXXXXXXX", // Google Analytics 4
|
|
186
|
+
analytics_endpoint: "https://your-analytics-endpoint.com"
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Custom Error Pages
|
|
191
|
+
|
|
192
|
+
The system fetches error and redirect pages from your GitHub Pages repository, so you can fully customize their content and design:
|
|
193
|
+
|
|
194
|
+
- **404 Page**: <code>https://dytsou.github.io/404.html</code>
|
|
195
|
+
- **Security Warning**: <code>https://dytsou.github.io/safe-browsing-warning.html</code>
|
|
196
|
+
- **No-Referrer Redirect**: <code>https://dytsou.github.io/no-ref-page.html</code>
|
|
197
|
+
|
|
198
|
+
You can edit these HTML files in your GitHub Pages repo to change the look, text, or behavior at any time. The worker will always serve the latest version from your site.
|
|
199
|
+
|
|
200
|
+
All pages feature responsive design with glassmorphism effects matching your main interface.
|
|
201
|
+
|
|
202
|
+
## 📖 API Documentation
|
|
203
|
+
|
|
204
|
+
The project includes comprehensive API documentation available at `/api` endpoint with interactive Swagger UI.
|
|
205
|
+
|
|
206
|
+
### OpenAPI Specification
|
|
207
|
+
|
|
208
|
+
- **Format**: OpenAPI 3.1.0
|
|
209
|
+
- **Location**: [docs/api/openapi.yaml](docs/api/openapi.yaml)
|
|
210
|
+
- **Interactive UI**: Available at `/api` endpoint on your deployed worker
|
|
211
|
+
- **Offline Access**: [docs/api/index.html](docs/api/index.html) for local viewing
|
|
212
|
+
|
|
213
|
+
### Shorten URL
|
|
214
|
+
|
|
215
|
+
**POST** `/shorten`
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"url": "https://example.com/very-long-url",
|
|
220
|
+
"custom_slug": "my-link" // optional
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Response:**
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"short_url": "https://url.tsou.me/abc123"
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Error Response:**
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"status": 400,
|
|
237
|
+
"message": "Invalid URL format"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Access Short URL
|
|
242
|
+
|
|
243
|
+
**GET** `/{key}`
|
|
244
|
+
|
|
245
|
+
Redirects to the original URL or shows appropriate error page.
|
|
246
|
+
|
|
247
|
+
### Additional Endpoints
|
|
248
|
+
|
|
249
|
+
- **GET** `/api` - Interactive API documentation (Swagger UI)
|
|
250
|
+
|
|
251
|
+
## 🛠️ Development
|
|
252
|
+
|
|
253
|
+
### Local Development
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Start local development server (see wrangler.toml for port / host)
|
|
257
|
+
wrangler dev
|
|
258
|
+
|
|
259
|
+
# Test with curl (example; in production, requests must pass through Cloudflare Access/WARP)
|
|
260
|
+
curl -X POST http://localhost:8787/shorten \
|
|
261
|
+
-H "Content-Type: application/json" \
|
|
262
|
+
-d '{"url": "https://example.com"}'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### File Structure
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
shorten-url/
|
|
269
|
+
├── src/
|
|
270
|
+
│ ├── worker.js # Production Cloudflare Worker
|
|
271
|
+
│ ├── worker.dev.js # Development Cloudflare Worker
|
|
272
|
+
│ └── worker.example.js # Worker template
|
|
273
|
+
├── docs/
|
|
274
|
+
│ ├── index.html # Homepage interface
|
|
275
|
+
│ └── api/
|
|
276
|
+
│ ├── index.html # Swagger UI for API docs
|
|
277
|
+
│ └── openapi.yaml # OpenAPI 3.1.0 specification
|
|
278
|
+
├── config/
|
|
279
|
+
│ ├── config.js # Configuration (not in git)
|
|
280
|
+
│ └── config.example.js # Configuration template
|
|
281
|
+
├── .cursor/ # Cursor IDE rules and workflow
|
|
282
|
+
├── .github/ # GitHub workflows and templates
|
|
283
|
+
├── .gitignore # Git ignore rules
|
|
284
|
+
├── README.md # This file
|
|
285
|
+
└── wrangler.toml # Wrangler configuration
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Security Considerations
|
|
289
|
+
|
|
290
|
+
- Keep your `config.js` file private (it's in `.gitignore`)
|
|
291
|
+
- Use environment variables for sensitive data in production
|
|
292
|
+
- Enable rate limiting to prevent abuse
|
|
293
|
+
- Consider enabling Google Safe Browsing for malicious URL detection
|
|
294
|
+
- Regularly monitor your KV storage usage
|
|
295
|
+
- Configure Cloudflare Access / WARP correctly, as URL shortening is intended to be available only to authenticated/requesters you control
|
|
296
|
+
|
|
297
|
+
## Troubleshooting
|
|
298
|
+
|
|
299
|
+
### Common Issues
|
|
300
|
+
|
|
301
|
+
**"Failed to copy" error:**
|
|
302
|
+
|
|
303
|
+
- The app uses modern clipboard API with fallbacks
|
|
304
|
+
- Ensure you're using HTTPS (required for clipboard access)
|
|
305
|
+
|
|
306
|
+
**Worker deployment fails:**
|
|
307
|
+
|
|
308
|
+
- Check your `wrangler.toml` configuration
|
|
309
|
+
- Ensure KV namespace ID is correct
|
|
310
|
+
- Verify you're logged into the correct Cloudflare account
|
|
311
|
+
|
|
312
|
+
**Custom slugs not working:**
|
|
313
|
+
|
|
314
|
+
- Check that `custom_link` is enabled in config
|
|
315
|
+
- Verify slug meets validation requirements (alphanumeric, hyphens, underscores only)
|
|
316
|
+
- Ensure slug is not in the reserved slugs list
|
|
317
|
+
|
|
318
|
+
**Frontend not loading:**
|
|
319
|
+
|
|
320
|
+
- Update `frontend.url` in your config to match your hosting URL
|
|
321
|
+
- Ensure CORS is enabled in worker configuration
|
|
322
|
+
|
|
323
|
+
**Rate limiting issues:**
|
|
324
|
+
|
|
325
|
+
- Adjust `security.rate_limit` in your configuration
|
|
326
|
+
- Consider implementing IP allowlisting for trusted sources
|
|
327
|
+
|
|
328
|
+
## License
|
|
329
|
+
|
|
330
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
331
|
+
|
|
332
|
+
## Contributing
|
|
333
|
+
|
|
334
|
+
1. Fork the repository
|
|
335
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
336
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
337
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
338
|
+
5. Open a Pull Request
|
|
339
|
+
|
|
340
|
+
## Support
|
|
341
|
+
|
|
342
|
+
If you encounter any issues or have questions:
|
|
343
|
+
|
|
344
|
+
1. Check the [troubleshooting section](#-troubleshooting)
|
|
345
|
+
2. Search existing issues on GitHub
|
|
346
|
+
3. Create a new issue with detailed information
|
|
347
|
+
|
|
348
|
+
## Deployment Checklist
|
|
349
|
+
|
|
350
|
+
- [ ] Updated `config.js` with your settings
|
|
351
|
+
- [ ] Deployed frontend to GitHub Pages or custom hosting
|
|
352
|
+
- [ ] Created Cloudflare KV namespace
|
|
353
|
+
- [ ] Configured `wrangler.toml` with correct KV namespace ID
|
|
354
|
+
- [ ] Deployed worker using `wrangler deploy`
|
|
355
|
+
- [ ] Tested URL shortening functionality
|
|
356
|
+
- [ ] Verified copy-to-clipboard feature works
|
|
357
|
+
- [ ] Tested custom error pages (404, security warnings)
|
|
358
|
+
- [ ] (Optional) Configured custom domain
|
|
359
|
+
- [ ] (Optional) Added Google Safe Browsing API key
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL Shortener Configuration Example
|
|
3
|
+
*
|
|
4
|
+
* Copy this file to config.js and modify the values according to your setup.
|
|
5
|
+
* This file should be committed to your repository as a template.
|
|
6
|
+
* The actual config.js file should be added to .gitignore to keep your secrets safe.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const config = {
|
|
10
|
+
// Frontend Configuration
|
|
11
|
+
frontend: {
|
|
12
|
+
// URL where your frontend is hosted (used by worker to serve the main page)
|
|
13
|
+
// REQUIRED: Change this to your GitHub Pages URL or custom domain
|
|
14
|
+
url: "https://yourusername.github.io/your-repo-name/",
|
|
15
|
+
|
|
16
|
+
// Domain displayed in the custom slug input prefix
|
|
17
|
+
// If null, will use the current domain automatically
|
|
18
|
+
// Example: "short.ly" or "yourdomain.com"
|
|
19
|
+
displayDomain: null,
|
|
20
|
+
|
|
21
|
+
// Default theme for the frontend
|
|
22
|
+
theme: "", // Use empty string for default theme, or "theme/urlcool" for urlcool theme
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Worker Configuration
|
|
26
|
+
worker: {
|
|
27
|
+
// Control the HTTP referrer header
|
|
28
|
+
// Set to "on" to create anonymous links that hide the HTTP Referer header
|
|
29
|
+
no_ref: "off",
|
|
30
|
+
|
|
31
|
+
// Allow Cross-origin resource sharing for API requests
|
|
32
|
+
cors: "on",
|
|
33
|
+
|
|
34
|
+
// If true, the same long URL will be shortened into the same short URL
|
|
35
|
+
unique_link: true,
|
|
36
|
+
|
|
37
|
+
// Allow users to customize the short URL
|
|
38
|
+
custom_link: true,
|
|
39
|
+
|
|
40
|
+
// Google Safe Browsing API Key for URL safety check before redirect
|
|
41
|
+
// Get your API key from: https://developers.google.com/safe-browsing/v4/get-started
|
|
42
|
+
// Leave empty to disable safety checking
|
|
43
|
+
safe_browsing_api_key: "",
|
|
44
|
+
|
|
45
|
+
// Maximum length for custom slugs
|
|
46
|
+
max_custom_slug_length: 50,
|
|
47
|
+
|
|
48
|
+
// Minimum length for generated random keys
|
|
49
|
+
min_random_key_length: 6,
|
|
50
|
+
|
|
51
|
+
// Characters used for random key generation (removed confusing characters)
|
|
52
|
+
random_chars: "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",
|
|
53
|
+
|
|
54
|
+
// Reserved slugs that cannot be used as custom URLs
|
|
55
|
+
reserved_slugs: [
|
|
56
|
+
"api",
|
|
57
|
+
"admin",
|
|
58
|
+
"www",
|
|
59
|
+
"mail",
|
|
60
|
+
"ftp",
|
|
61
|
+
"localhost",
|
|
62
|
+
"password",
|
|
63
|
+
"help",
|
|
64
|
+
"support",
|
|
65
|
+
"contact",
|
|
66
|
+
"about",
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// KV Storage Configuration (Cloudflare Workers)
|
|
71
|
+
storage: {
|
|
72
|
+
// KV namespace binding name (must match wrangler.toml)
|
|
73
|
+
binding_name: "LINKS",
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Security Configuration
|
|
77
|
+
security: {
|
|
78
|
+
// Rate limiting (requests per minute per IP)
|
|
79
|
+
rate_limit: 10,
|
|
80
|
+
|
|
81
|
+
// Enable URL validation
|
|
82
|
+
validate_urls: true,
|
|
83
|
+
|
|
84
|
+
// Block suspicious domains
|
|
85
|
+
block_suspicious_domains: true,
|
|
86
|
+
|
|
87
|
+
// List of blocked domains (exact matches)
|
|
88
|
+
// Add domains you want to block from being shortened
|
|
89
|
+
blocked_domains: [
|
|
90
|
+
// "bit.ly",
|
|
91
|
+
// "tinyurl.com",
|
|
92
|
+
// "t.co"
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
// Analytics Configuration (optional)
|
|
97
|
+
analytics: {
|
|
98
|
+
// Enable click tracking
|
|
99
|
+
enable_tracking: false,
|
|
100
|
+
|
|
101
|
+
// Google Analytics tracking ID (GA4)
|
|
102
|
+
// Example: "G-XXXXXXXXXX"
|
|
103
|
+
ga_tracking_id: "",
|
|
104
|
+
|
|
105
|
+
// Custom analytics endpoint for tracking clicks
|
|
106
|
+
analytics_endpoint: "",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Export for use in other files
|
|
111
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
112
|
+
module.exports = config;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Make available globally for browser usage
|
|
116
|
+
if (typeof window !== "undefined") {
|
|
117
|
+
window.APP_CONFIG = config;
|
|
118
|
+
}
|
package/config/config.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL Shortener Configuration
|
|
3
|
+
*
|
|
4
|
+
* This file contains all configurable settings for the URL shortener.
|
|
5
|
+
* Copy this file from config.example.js and modify the values as needed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const config = {
|
|
9
|
+
// Frontend Configuration
|
|
10
|
+
frontend: {
|
|
11
|
+
// URL where your frontend is hosted (used by worker to serve the main page)
|
|
12
|
+
url: "https://dytsou.github.io/shorten-url/",
|
|
13
|
+
|
|
14
|
+
// Domain displayed in the custom slug input prefix
|
|
15
|
+
// If null, will use the current domain automatically
|
|
16
|
+
displayDomain: null,
|
|
17
|
+
|
|
18
|
+
// Default theme for the frontend
|
|
19
|
+
theme: "", // Use empty string for default theme, or "theme/urlcool" for urlcool theme
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Worker Configuration
|
|
23
|
+
worker: {
|
|
24
|
+
// Control the HTTP referrer header
|
|
25
|
+
// Set to "on" to create anonymous links that hide the HTTP Referer header
|
|
26
|
+
no_ref: "off",
|
|
27
|
+
|
|
28
|
+
// Allow Cross-origin resource sharing for API requests
|
|
29
|
+
cors: "on",
|
|
30
|
+
|
|
31
|
+
// If true, the same long URL will be shortened into the same short URL
|
|
32
|
+
unique_link: true,
|
|
33
|
+
|
|
34
|
+
// Allow users to customize the short URL
|
|
35
|
+
custom_link: true,
|
|
36
|
+
|
|
37
|
+
// Google Safe Browsing API Key for URL safety check before redirect
|
|
38
|
+
// Leave empty to disable safety checking
|
|
39
|
+
safe_browsing_api_key: "",
|
|
40
|
+
|
|
41
|
+
// Maximum length for custom slugs
|
|
42
|
+
max_custom_slug_length: 50,
|
|
43
|
+
|
|
44
|
+
// Minimum length for generated random keys
|
|
45
|
+
min_random_key_length: 6,
|
|
46
|
+
|
|
47
|
+
// Characters used for random key generation (removed confusing characters)
|
|
48
|
+
random_chars: 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
|
|
49
|
+
|
|
50
|
+
// Reserved slugs that cannot be used as custom URLs
|
|
51
|
+
reserved_slugs: ['api', 'admin', 'www', 'mail', 'ftp', 'localhost', 'password', 'help', 'support', 'contact', 'about']
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// KV Storage Configuration (Cloudflare Workers)
|
|
55
|
+
storage: {
|
|
56
|
+
// KV namespace binding name (must match wrangler.toml)
|
|
57
|
+
binding_name: "LINKS"
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// Security Configuration
|
|
61
|
+
security: {
|
|
62
|
+
// Rate limiting (requests per minute per IP)
|
|
63
|
+
rate_limit: 10,
|
|
64
|
+
|
|
65
|
+
// Enable URL validation
|
|
66
|
+
validate_urls: true,
|
|
67
|
+
|
|
68
|
+
// Block suspicious domains
|
|
69
|
+
block_suspicious_domains: true,
|
|
70
|
+
|
|
71
|
+
// List of blocked domains (exact matches)
|
|
72
|
+
blocked_domains: [
|
|
73
|
+
"bit.ly",
|
|
74
|
+
"tinyurl.com",
|
|
75
|
+
"t.co",
|
|
76
|
+
"reurl.cc"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
// Analytics Configuration (optional)
|
|
81
|
+
analytics: {
|
|
82
|
+
// Enable click tracking
|
|
83
|
+
enable_tracking: false,
|
|
84
|
+
|
|
85
|
+
// Google Analytics tracking ID
|
|
86
|
+
ga_tracking_id: "",
|
|
87
|
+
|
|
88
|
+
// Custom analytics endpoint
|
|
89
|
+
analytics_endpoint: ""
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Export for use in other files
|
|
94
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
95
|
+
module.exports = config;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Make available globally for browser usage
|
|
99
|
+
if (typeof window !== 'undefined') {
|
|
100
|
+
window.APP_CONFIG = config;
|
|
101
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>Shorten URL API</title>
|
|
6
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" />
|
|
7
|
+
<style>
|
|
8
|
+
html,
|
|
9
|
+
body {
|
|
10
|
+
height: 100%;
|
|
11
|
+
margin: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#swagger-ui {
|
|
15
|
+
height: 100vh;
|
|
16
|
+
}
|
|
17
|
+
</style>
|
|
18
|
+
</head>
|
|
19
|
+
|
|
20
|
+
<body>
|
|
21
|
+
<div id="swagger-ui"></div>
|
|
22
|
+
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>
|
|
23
|
+
<script>
|
|
24
|
+
window.onload = () => {
|
|
25
|
+
SwaggerUIBundle({
|
|
26
|
+
url: "openapi.yaml",
|
|
27
|
+
dom_id: "#swagger-ui",
|
|
28
|
+
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
29
|
+
layout: "BaseLayout",
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|