An open API service indexing awesome lists of open source software.

https://github.com/sv443/whdl

Self-hosted, webhook-based, token-authenticated file downloader and RPC service.
https://github.com/sv443/whdl

downloader express file-download file-downloader http-server https-server rpc rpc-api rpc-server rpc-service server service webhook webhook-server webhooks

Last synced: 3 months ago
JSON representation

Self-hosted, webhook-based, token-authenticated file downloader and RPC service.

Awesome Lists containing this project

README

          

# WHDL
Self-hosted, webhook-based, token-authenticated file downloader and RPC service.

Supports downloading and deleting files as well as calling bash or batch scripts.
Uses the middlewares [helmet](https://www.npmjs.com/package/helmet) for security and [cors](https://www.npmjs.com/package/cors) to allow cross-origin web requests.



## Setup
1. Clone the repository or download and extract the ZIP (green button at the top).
2. Install [Node.js](https://nodejs.org/) (LTS version recommended) and [npm.](https://npmjs.com/)
3. Call the command `npm i` in a terminal inside the downloaded folder to install the dependencies.
4. Copy `.env.example` to `.env` and fill out the contained environment variables as needed.
5. Call the command `npm start` to start the service.
Use something like [pm2](https://pm2.keymetrics.io/), [systemd](https://wiki.archlinux.org/title/systemd) or [Windows Task Scheduler](https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-start-page) to start it automatically at system startup.

- To use HTTPS, specify the paths to your `.crt` and `.key` files in `.env` and adjust the `PORT` variable if needed.
Use something like [Let's Encrypt](https://letsencrypt.org/) or [Cloudflare](https://www.cloudflare.com/) to get a free, trusted TLS certificate.

### Generating tokens:
- You can generate cryptographically strong tokens using the command `npm run gen-token`.
Specify the amount and length with the optional arguments, e.g. `npm run gen-token 3 64` to generate 3 tokens with a length of 64 characters each. The default amount is 1 and the default length is 48.
- Tokens need to be URL-safe, so I recommend only using alphanumeric characters and `-` or `_`. [Any characters **not** listed here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#description) will need to be [percent-encoded](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) if you want to use them.
- ⚠️ Should one of the tokens be exfiltrated, an attacker could download and execute any script with the privileges of the user that started the service (if the RPC functionality was turned on).
You should limit access as much as possible in `.env` and always exercise caution with that file.



## Usage
### Download files:
Send a `POST` request to `http://:/download?token=` with a JSON body like this:
```json
{
"url": "https://example.com/file.zip",
"path": "/absolute/path/to/save/file.zip"
}
```
```json
{
"url": "https://example.com/",
"path": "C:\\Users\\user\\Downloads\\example.com.html"
}
```

- The specified `path` must be a subdirectory of one of the allowed directories specified in the semicolon-separated `ALLOWED_DIRS` environment variable (in `.env`).
- Use [GLOB patterns](https://www.malikbrowne.com/blog/a-beginners-guide-glob-patterns/) in `ALLOWED_FILE_PATTERNS` (in `.env`) to restrict which files can be modified.
- Tokens are specified in the semicolon-separated `TOKENS` environment variable (in `.env`).
- If the directory does not exist, it will be created automatically.
- Should the download take longer than 25 seconds, the request will succeed preemptively, while the download still continues in the background.
- Relative paths will be resolved based on the process working directory.



### Delete files:
Send a `DELETE` request to `http://:/delete?token=` with a JSON body like this:
```json
{
"path": "/absolute/path/to/delete/file.zip"
}
```
```json
{
"path": "C:\\Users\\user\\Documents\\file.zip"
}
```
Using a glob pattern:
```json
{
"path": "C:\\Users\\user\\Documents\\",
"pattern": "*.{zip,rar,tar,tar.gz}"
}
```

- If no matching file is found, the request will still succeed.
- The specified `path` must be a subdirectory of one of the allowed directories specified in the semicolon-separated `ALLOWED_DIRS` environment variable (in `.env`).
- Tokens are specified in the semicolon-separated `TOKENS` environment variable (in `.env`).
- Relative paths will be resolved based on the process working directory.



### Execute scripts (RPC):
Send a `POST` request to `http://:/run?token=` with a JSON body like this:
```json
{
"path": "/absolute/path/to/script.sh"
}
```
```json
{
"path": "C:\\Users\\user\\Documents\\unzip_file.bat"
}
```

- This feature is disabled by default, because script file extensions are not included in `.env.template`'s `ALLOWED_FILE_PATTERNS`.
- Only files ending in `.bat`, `.cmd` and `.sh` will be callable, even if other extensions are added to `ALLOWED_FILE_PATTERNS`.
- The specified `path` must be a subdirectory of one of the allowed directories specified in the semicolon-separated `ALLOWED_DIRS` environment variable (in `.env`).
- Tokens are specified in the semicolon-separated `TOKENS` environment variable (in `.env`).
- Relative paths will be resolved based on the process working directory.



Copyright © 2025 Sv443 - Licensed under the [MIT License](./LICENSE.txt)
If you like my projects, please consider [supporting the development ❤️](https://github.com/sponsors/Sv443)