A containerized web service that converts Markdown content to EPUB format using Pandoc, exposing a simple REST API for easy integration.
- Convert Markdown to EPUB format
- Simple REST API
- Containerized with Docker
- Configurable via environment variables
- Optional authentication for API access
- Web UI for easy conversion
- Docker and Docker Compose installed on your system
-
Clone this repository:
git clone <repository-url> cd markdown-epub-converter
-
Build and start the service:
docker-compose up -d
-
The API will be available at
http://localhost:8080/convert
POST /convert
Content-Type: application/json
GET /status
GET /auth-status
{
"markdown": "# Chapter 1\n\nThis is the content...",
"title": "My Book Title",
"author": "Author Name"
}When authentication is enabled, include one of the following headers with your request:
Authorization: Bearer your_token_here
or
X-Auth-Token: your_token_here
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
markdown |
string | Yes | - | The markdown content to convert |
title |
string | No | "Untitled" | The book title for metadata |
author |
string | No | "Unknown Author" | The author name for metadata |
Success (200 OK)
Content-Type: application/epub+zip
Content-Disposition: attachment; filename="book.epub"
[Binary EPUB file data]
Error (400 Bad Request)
{
"error": "Missing required field: markdown"
}Error (500 Internal Server Error)
{
"error": "Conversion failed: [error details]"
}Error (401 Unauthorized)
{
"error": "Authentication required"
}curl -X POST http://localhost:8088/convert \
-H "Content-Type: application/json" \
-d '{
"markdown": "# My Book\n\nThis is chapter one...",
"title": "My First Book",
"author": "John Doe"
}' \
--output book.epubcurl -X POST http://localhost:8088/convert \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_token_here" \
-d '{
"markdown": "# My Book\n\nThis is chapter one...",
"title": "My First Book",
"author": "John Doe"
}' \
--output book.epubimport requests
response = requests.post('http://localhost:8088/convert', json={
'markdown': '# Hello World\n\nThis is my book content.',
'title': 'Hello World Book',
'author': 'Jane Smith'
})
if response.status_code == 200:
with open('book.epub', 'wb') as f:
f.write(response.content)import requests
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_token_here'
}
response = requests.post('http://localhost:8088/convert',
headers=headers,
json={
'markdown': '# Hello World\n\nThis is my book content.',
'title': 'Hello World Book',
'author': 'Jane Smith'
})
if response.status_code == 200:
with open('book.epub', 'wb') as f:
f.write(response.content)The service can be configured using environment variables in the docker-compose.yml file:
PORT: API server port (default: 5000)HOST: API server host (default: 0.0.0.0)DEBUG: Enable debug mode (default: False)AUTH_TOKEN: Set this to enable authentication with the specified token
To enable authentication:
-
Edit the
docker-compose.ymlfile and uncomment the AUTH_TOKEN line:# Authentication (uncomment and set a secure token to enable authentication) - AUTH_TOKEN=your_secure_token_here
-
Replace
your_secure_token_herewith a strong, unique token -
Rebuild and restart the container:
docker-compose down && docker-compose build && docker-compose up -d
-
To disable authentication, either comment out the AUTH_TOKEN line or set it to an empty string, then rebuild and restart the container
The service includes a web interface accessible at the root URL (e.g., http://localhost:8088/). The web interface:
- Automatically detects if authentication is required
- Shows a warning when authentication is not enabled
- Provides a simple form for converting Markdown to EPUB
- Maximum markdown input size: 10MB (configurable)
- Synchronous processing (blocking requests)
- Single-threaded Flask application
- Temporary files stored in container filesystem
- No persistent storage or caching
- Input validation for markdown content
- File system isolation within container
- Temporary file cleanup
- Resource limits to prevent DoS
- No shell injection vulnerabilities in pandoc execution
- Optional authentication for API access
- Warning displayed when authentication is not enabled
The project includes a test script that can be used to verify the API functionality:
# Test without authentication
python test_api.py --url http://localhost:8088
# Test with authentication
python test_api.py --url http://localhost:8088 --token your_token_hereDaniel Koller
- Twitter: @dakoller
- Bluesky: daniel.dakoller.net