Files
tingz/API.md

365 lines
7.8 KiB
Markdown

# API with cURL
Complete guide to tingz API with cURL.
## Assumptions
- Running deployer service on http://localhost:8080
- Admin token (set in `.env.development` as `ADMIN_TOKEN`) set to `devadmintoken`
- API version is `v1`
- **Note:** The deployer service only handles API requests (`/api/v1/*`). For serving deployed static sites, you need a separate web server (Caddy, nginx, etc.) configured to serve files from `/var/www/docs`
## Step 1: Create a User (Admin Only)
First, an admin needs to create a user account to get a deployment token.
```bash
curl -X POST "http://localhost:8080/api/v1/auth" \
-H "Authorization: Bearer devadmintoken" \
-H "Content-Type: application/json" \
-d '{"username":"alice"}'
```
**Success Response:**
```json
{
"status": "ok",
"token": "82lz0BVOWtV4uVj9DBZBuKMeyVDwidL2"
}
```
**Important:** Save this token! You'll need it for all deployments for that user.
### Username Requirements
- Lowercase letters, numbers, hyphens, underscores only
- 1-64 characters
- Must start and end with alphanumeric character
- Pattern: `^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$`
## Step 2: Prepare Your Static Site
Package your static site as a `.tar.gz` file with files at the root level.
### Correct Way (Files at Root)
```bash
cd /path/to/your/site
tar -czf ../site.tar.gz .
```
This creates a tarball where `index.html` is at the root, not nested in a directory.
### What NOT to Do
```bash
# DON'T: This creates site/index.html (nested)
tar -czf site.tar.gz site/
# DON'T: This creates /path/to/your/site/index.html (nested)
tar -czf site.tar.gz /path/to/your/site
```
### Verify Your Tarball
```bash
tar -tzf site.tar.gz | head -5
```
Expected output:
```
index.html
css/
css/style.css
js/
js/app.js
```
NOT:
```
site/index.html ← Wrong! Nested directory
site/css/style.css
```
## Step 3: Deploy Your Site
Use your user token to deploy the site.
```bash
curl -X POST "http://localhost:8080/api/v1/deploy" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-F "project=myproject" \
-F "file=@site.tar.gz"
```
**Success Response:**
```json
{
"status": "ok",
"project": "myproject",
"username": "alice",
"url": "https://docs.yigid.dev/alice/myproject/",
"release": "20251014T180806"
}
```
### Project Name Requirements
- Same rules as username
- Lowercase, alphanumeric, hyphens, underscores
- 1-64 characters
- Pattern: `^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$`
### Important Notes
- The `@` prefix is required for file uploads: `-F "file=@site.tar.gz"`
- Max upload size: 100MB (default, configurable)
- Files are deployed to: `/var/www/docs/{username}/{project}/`
- Each deployment creates a new release in `/var/www/deploys/{username}/{project}/{release_id}/`
- The deploy directory is an atomic symlink to the latest release
- Old releases are kept (5 by default) for rollback
## Step 4: Verify Deployment
### Check the Symlink
```bash
ls -la docs/alice/myproject
```
Output:
```
lrwxr-xr-x 1 deployer deployer 47 Oct 14 21:08 myproject -> /var/www/deploys/alice/myproject/20251014T180806
```
### Check the Files
```bash
ls -la deploys/alice/myproject/20251014T180806/
```
### Access Your Site
**Note:** The deployer service only handles API requests. Deployed sites are served by a separate web server (like Caddy or nginx) that reads from `/var/www/docs`.
```bash
# If you have a web server configured to serve from /var/www/docs:
curl https://docs.yigid.dev/alice/myproject/
```
**For local development:** You'll need to set up a web server to serve files from the `docs/` directory, or use a simple HTTP server:
```bash
# Example: serve files from docs directory
cd docs && python3 -m http.server 3000
# Then access: http://localhost:3000/alice/myproject/
```
## Complete Workflow Example
```bash
# 1. Set your admin token
export ADMIN_TOKEN="devadmintoken"
# 2. Create user and capture token
USER_TOKEN=$(curl -s -X POST "http://localhost:8080/api/v1/auth" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"alice"}' | jq -r '.token')
echo "User token: ${USER_TOKEN}"
# 3. Create test site
mkdir -p my-site
cat > my-site/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>My Site</title></head>
<body><h1>Hello, World!</h1></body>
</html>
EOF
# 4. Package site
tar -czf site.tar.gz -C my-site .
# 5. Deploy
curl -s -X POST "http://localhost:8080/api/v1/deploy" \
-H "Authorization: Bearer ${USER_TOKEN}" \
-F "project=mysite" \
-F "file=@site.tar.gz" | jq
# 6. Verify (requires web server setup)
# If you have a web server serving from docs/ directory:
curl http://localhost:3000/alice/mysite/
```
## Health Check
Test if the service is running:
```bash
curl http://localhost:8080/api/v1/status
```
Expected response:
```json
{
"status": "ok"
}
```
## Error Responses
### Invalid Token
```json
{
"status": "error",
"error": "unauthorized"
}
```
### Invalid Project Name
```json
{
"status": "error",
"error": "invalid project name format"
}
```
### Missing File
```json
{
"status": "error",
"error": "missing or invalid file"
}
```
### Upload Too Large
```json
{
"status": "error",
"error": "request body too large"
}
```
### Path Traversal in Tarball
```json
{
"status": "error",
"error": "failed to extract tarball: path contains '..' component which is not allowed: ../../etc/passwd"
}
```
## User Management (Admin Only)
### Reroll User Token
Create a new token for an existing user (invalidates old token):
```bash
curl -X POST "http://localhost:8080/api/v1/auth" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"alice"}'
```
### Delete User (Keep Files)
```bash
curl -X DELETE "http://localhost:8080/api/v1/auth" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"alice","files":"persist"}'
```
### Delete User and All Files
```bash
curl -X DELETE "http://localhost:8080/api/v1/auth" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"alice","files":"delete"}'
```
## CI/CD Integration
### GitHub Actions
```yaml
name: Deploy Documentation
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build site
run: |
# Your build steps here
npm run build
- name: Package and deploy
env:
DEPLOYER_TOKEN: ${{ secrets.DEPLOYER_TOKEN }}
run: |
tar -czf site.tar.gz -C dist .
curl -f -X POST "https://deployer.example.com/api/v1/deploy" \
-H "Authorization: Bearer ${DEPLOYER_TOKEN}" \
-F "project=docs" \
-F "file=@site.tar.gz"
```
### GitLab CI
```yaml
deploy:
stage: deploy
only:
- main
script:
- tar -czf site.tar.gz -C public .
- |
curl -f -X POST "https://deployer.example.com/api/v1/deploy" \
-H "Authorization: Bearer ${DEPLOYER_TOKEN}" \
-F "project=docs" \
-F "file=@site.tar.gz"
variables:
DEPLOYER_TOKEN: $DEPLOYER_TOKEN
```
## Tips & Best Practices
1. **Always use `@` for file uploads**: `-F "file=@your-file.tar.gz"`
2. **Verify tarball contents** before deploying:
```bash
tar -tzf site.tar.gz | head -20
```
3. **Use `-f` flag in CI/CD** to fail on HTTP errors:
```bash
curl -f -X POST ...
```
4. **Pretty-print JSON responses** with `jq`:
```bash
curl ... | jq
```
5. **Avoid macOS resource forks** in tarballs:
```bash
COPYFILE_DISABLE=1 tar -czf site.tar.gz -C dist .
```
6. **Check release history**:
```bash
ls -lt deploys/alice/myproject/
```
7. **Atomic deployments**: The symlink swap is atomic, so no downtime during deployment
8. **Release retention**: Old releases are kept (5 by default) for manual rollback if needed