570 lines
13 KiB
Markdown
570 lines
13 KiB
Markdown
# PersoNotes REST API Documentation
|
|
|
|
Version: **v1**
|
|
Base URL: `http://localhost:8080/api/v1`
|
|
|
|
## Table des matières
|
|
|
|
- [Vue d'ensemble](#vue-densemble)
|
|
- [Authentification](#authentification)
|
|
- [Formats de données](#formats-de-données)
|
|
- [Endpoints](#endpoints)
|
|
- [Lister les notes](#lister-les-notes)
|
|
- [Récupérer une note](#récupérer-une-note)
|
|
- [Créer/Mettre à jour une note](#créermettre-à-jour-une-note)
|
|
- [Supprimer une note](#supprimer-une-note)
|
|
- [Codes de statut HTTP](#codes-de-statut-http)
|
|
- [Exemples d'utilisation](#exemples-dutilisation)
|
|
|
|
---
|
|
|
|
## Vue d'ensemble
|
|
|
|
L'API REST de PersoNotes permet de gérer vos notes Markdown via HTTP. Elle supporte :
|
|
|
|
- **Listage** : Récupérer la liste de toutes les notes avec métadonnées
|
|
- **Lecture** : Télécharger une note en JSON ou Markdown brut
|
|
- **Écriture** : Créer ou mettre à jour une note
|
|
- **Suppression** : Supprimer une note définitivement
|
|
|
|
### Caractéristiques
|
|
|
|
- ✅ **Versionnée** : `/api/v1` pour assurer la compatibilité future
|
|
- ✅ **Content Negotiation** : Support JSON et Markdown selon le header `Accept`
|
|
- ✅ **Idempotence** : PUT crée ou met à jour (idempotent)
|
|
- ✅ **Automatisation** : Front matter géré automatiquement
|
|
- ✅ **Ré-indexation** : Recherche mise à jour automatiquement après chaque modification
|
|
- ✅ **Support sous-dossiers** : Organisation hiérarchique native
|
|
|
|
---
|
|
|
|
## Authentification
|
|
|
|
**Version actuelle : Aucune authentification requise**
|
|
|
|
⚠️ **IMPORTANT** : L'API n'a pas d'authentification. Si vous exposez le serveur publiquement :
|
|
1. Utilisez un reverse proxy (nginx, Caddy) avec authentification
|
|
2. Implémentez Basic Auth ou API Key
|
|
3. Utilisez un VPN ou tunnel SSH
|
|
|
|
---
|
|
|
|
## Formats de données
|
|
|
|
### Note complète (NoteResponse)
|
|
|
|
```json
|
|
{
|
|
"path": "projet/backend.md",
|
|
"title": "Backend API",
|
|
"content": "---\ntitle: Backend API\n...\n---\n\n# Content",
|
|
"body": "\n# Content",
|
|
"frontMatter": {
|
|
"title": "Backend API",
|
|
"date": "10-11-2025",
|
|
"last_modified": "10-11-2025:14:30",
|
|
"tags": ["projet", "backend"]
|
|
},
|
|
"lastModified": "10-11-2025:14:30",
|
|
"size": 1024
|
|
}
|
|
```
|
|
|
|
### Métadonnées de note (NoteMetadata)
|
|
|
|
```json
|
|
{
|
|
"path": "projet/backend.md",
|
|
"title": "Backend API",
|
|
"tags": ["projet", "backend"],
|
|
"lastModified": "10-11-2025:14:30",
|
|
"date": "10-11-2025",
|
|
"size": 1024
|
|
}
|
|
```
|
|
|
|
### Requête de création/modification (NoteRequest)
|
|
|
|
Deux options :
|
|
|
|
**Option 1 : Content complet** (recommandé pour migration)
|
|
```json
|
|
{
|
|
"content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
|
|
}
|
|
```
|
|
|
|
**Option 2 : Body + FrontMatter séparés** (recommandé pour création)
|
|
```json
|
|
{
|
|
"body": "\n# Mon contenu\n\nTexte ici...",
|
|
"frontMatter": {
|
|
"title": "Ma note",
|
|
"tags": ["test", "exemple"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Erreur (ErrorResponse)
|
|
|
|
```json
|
|
{
|
|
"error": "Bad Request",
|
|
"message": "Invalid path",
|
|
"code": 400
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints
|
|
|
|
### Lister les notes
|
|
|
|
Récupère la liste de toutes les notes avec leurs métadonnées.
|
|
|
|
**Endpoint** : `GET /api/v1/notes`
|
|
|
|
**Paramètres** : Aucun
|
|
|
|
**Réponse** : `200 OK`
|
|
|
|
```json
|
|
{
|
|
"notes": [
|
|
{
|
|
"path": "projet/backend.md",
|
|
"title": "Backend API",
|
|
"tags": ["projet", "backend"],
|
|
"lastModified": "10-11-2025:14:30",
|
|
"date": "10-11-2025",
|
|
"size": 1024
|
|
},
|
|
{
|
|
"path": "daily/2025-11-10.md",
|
|
"title": "Notes du 10 novembre",
|
|
"tags": ["daily"],
|
|
"lastModified": "10-11-2025:09:15",
|
|
"date": "10-11-2025",
|
|
"size": 2048
|
|
}
|
|
],
|
|
"total": 2
|
|
}
|
|
```
|
|
|
|
**Exemple curl** :
|
|
|
|
```bash
|
|
curl http://localhost:8080/api/v1/notes
|
|
```
|
|
|
|
---
|
|
|
|
### Récupérer une note
|
|
|
|
Télécharge une note spécifique. Le format dépend du header `Accept`.
|
|
|
|
**Endpoint** : `GET /api/v1/notes/{path}`
|
|
|
|
**Paramètres** :
|
|
- `{path}` : Chemin relatif de la note (ex: `projet/backend.md`)
|
|
|
|
**Headers** :
|
|
- `Accept: application/json` (défaut) : Retourne JSON avec métadonnées
|
|
- `Accept: text/markdown` : Retourne Markdown brut
|
|
- `Accept: text/plain` : Retourne Markdown brut
|
|
|
|
**Réponse JSON** : `200 OK`
|
|
|
|
```json
|
|
{
|
|
"path": "projet/backend.md",
|
|
"title": "Backend API",
|
|
"content": "---\ntitle: Backend API\ndate: 10-11-2025\nlast_modified: 10-11-2025:14:30\ntags:\n - projet\n - backend\n---\n\n# Backend API\n\nContenu de la note...",
|
|
"body": "\n# Backend API\n\nContenu de la note...",
|
|
"frontMatter": {
|
|
"title": "Backend API",
|
|
"date": "10-11-2025",
|
|
"last_modified": "10-11-2025:14:30",
|
|
"tags": ["projet", "backend"]
|
|
},
|
|
"lastModified": "10-11-2025:14:30",
|
|
"size": 1024
|
|
}
|
|
```
|
|
|
|
**Réponse Markdown** : `200 OK`
|
|
|
|
```markdown
|
|
---
|
|
title: Backend API
|
|
date: 10-11-2025
|
|
last_modified: 10-11-2025:14:30
|
|
tags:
|
|
- projet
|
|
- backend
|
|
---
|
|
|
|
# Backend API
|
|
|
|
Contenu de la note...
|
|
```
|
|
|
|
**Erreurs** :
|
|
- `404 Not Found` : Note inexistante
|
|
|
|
**Exemples curl** :
|
|
|
|
```bash
|
|
# Récupérer en JSON
|
|
curl http://localhost:8080/api/v1/notes/projet/backend.md \
|
|
-H "Accept: application/json"
|
|
|
|
# Récupérer en Markdown brut
|
|
curl http://localhost:8080/api/v1/notes/projet/backend.md \
|
|
-H "Accept: text/markdown"
|
|
|
|
# Sauvegarder dans un fichier
|
|
curl http://localhost:8080/api/v1/notes/projet/backend.md \
|
|
-H "Accept: text/markdown" \
|
|
-o backend.md
|
|
```
|
|
|
|
---
|
|
|
|
### Créer/Mettre à jour une note
|
|
|
|
Crée une nouvelle note ou met à jour une note existante (idempotent).
|
|
|
|
**Endpoint** : `PUT /api/v1/notes/{path}`
|
|
|
|
**Paramètres** :
|
|
- `{path}` : Chemin relatif de la note (ex: `projet/nouvelle-note.md`)
|
|
|
|
**Headers** :
|
|
- `Content-Type: application/json` : Envoyer du JSON
|
|
- `Content-Type: text/markdown` : Envoyer du Markdown brut
|
|
|
|
**Body JSON** :
|
|
|
|
```json
|
|
{
|
|
"body": "\n# Ma nouvelle note\n\nContenu ici...",
|
|
"frontMatter": {
|
|
"title": "Ma nouvelle note",
|
|
"tags": ["test", "exemple"]
|
|
}
|
|
}
|
|
```
|
|
|
|
Ou avec `content` complet :
|
|
|
|
```json
|
|
{
|
|
"content": "---\ntitle: Ma note\ntags: [test]\n---\n\n# Contenu"
|
|
}
|
|
```
|
|
|
|
**Body Markdown brut** :
|
|
|
|
```markdown
|
|
# Ma nouvelle note
|
|
|
|
Contenu ici...
|
|
```
|
|
|
|
**Réponse** : `201 Created` (nouvelle note) ou `200 OK` (mise à jour)
|
|
|
|
```json
|
|
{
|
|
"path": "projet/nouvelle-note.md",
|
|
"title": "Ma nouvelle note",
|
|
"content": "---\ntitle: Ma nouvelle note\n...",
|
|
"body": "\n# Ma nouvelle note\n\nContenu ici...",
|
|
"frontMatter": {
|
|
"title": "Ma nouvelle note",
|
|
"date": "10-11-2025",
|
|
"last_modified": "10-11-2025:14:35",
|
|
"tags": ["test", "exemple"]
|
|
},
|
|
"lastModified": "10-11-2025:14:35",
|
|
"size": 256
|
|
}
|
|
```
|
|
|
|
**Comportement** :
|
|
- ✅ Crée automatiquement les dossiers parents
|
|
- ✅ Génère le front matter si absent
|
|
- ✅ Met à jour `last_modified` automatiquement
|
|
- ✅ Préserve `date` pour notes existantes
|
|
- ✅ Ré-indexe automatiquement pour la recherche
|
|
|
|
**Erreurs** :
|
|
- `400 Bad Request` : Chemin invalide ou JSON malformé
|
|
- `415 Unsupported Media Type` : Content-Type non supporté
|
|
- `500 Internal Server Error` : Erreur d'écriture
|
|
|
|
**Exemples curl** :
|
|
|
|
```bash
|
|
# Créer avec JSON
|
|
curl -X PUT http://localhost:8080/api/v1/notes/projet/test.md \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"body": "\n# Test\n\nCeci est un test.",
|
|
"frontMatter": {
|
|
"title": "Note de test",
|
|
"tags": ["test"]
|
|
}
|
|
}'
|
|
|
|
# Créer avec Markdown brut
|
|
curl -X PUT http://localhost:8080/api/v1/notes/projet/simple.md \
|
|
-H "Content-Type: text/markdown" \
|
|
-d "# Simple note
|
|
|
|
Contenu simple sans front matter."
|
|
|
|
# Upload depuis un fichier
|
|
curl -X PUT http://localhost:8080/api/v1/notes/projet/from-file.md \
|
|
-H "Content-Type: text/markdown" \
|
|
--data-binary @local-file.md
|
|
```
|
|
|
|
---
|
|
|
|
### Supprimer une note
|
|
|
|
Supprime définitivement une note.
|
|
|
|
**Endpoint** : `DELETE /api/v1/notes/{path}`
|
|
|
|
**Paramètres** :
|
|
- `{path}` : Chemin relatif de la note (ex: `projet/old-note.md`)
|
|
|
|
**Réponse** : `200 OK`
|
|
|
|
```json
|
|
{
|
|
"message": "Note deleted successfully",
|
|
"path": "projet/old-note.md"
|
|
}
|
|
```
|
|
|
|
**Erreurs** :
|
|
- `404 Not Found` : Note inexistante
|
|
- `500 Internal Server Error` : Erreur de suppression
|
|
|
|
**Exemple curl** :
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:8080/api/v1/notes/projet/old-note.md
|
|
```
|
|
|
|
---
|
|
|
|
## Codes de statut HTTP
|
|
|
|
| Code | Signification | Description |
|
|
|------|---------------|-------------|
|
|
| `200` | OK | Requête réussie |
|
|
| `201` | Created | Note créée avec succès |
|
|
| `400` | Bad Request | Requête invalide (chemin, JSON, etc.) |
|
|
| `404` | Not Found | Note inexistante |
|
|
| `405` | Method Not Allowed | Méthode HTTP non supportée |
|
|
| `415` | Unsupported Media Type | Content-Type non supporté |
|
|
| `500` | Internal Server Error | Erreur serveur |
|
|
|
|
---
|
|
|
|
## Exemples d'utilisation
|
|
|
|
### Synchronisation de notes
|
|
|
|
**Télécharger toutes les notes** :
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Télécharger toutes les notes localement
|
|
|
|
mkdir -p notes-backup
|
|
|
|
# Récupérer la liste
|
|
curl -s http://localhost:8080/api/v1/notes | jq -r '.notes[].path' | while read path; do
|
|
# Créer les dossiers parents
|
|
mkdir -p "notes-backup/$(dirname "$path")"
|
|
|
|
# Télécharger la note
|
|
curl -s http://localhost:8080/api/v1/notes/"$path" \
|
|
-H "Accept: text/markdown" \
|
|
-o "notes-backup/$path"
|
|
|
|
echo "✓ Downloaded: $path"
|
|
done
|
|
|
|
echo "Backup terminé!"
|
|
```
|
|
|
|
**Uploader un dossier de notes** :
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Uploader toutes les notes .md d'un dossier
|
|
|
|
find ./my-notes -name "*.md" | while read file; do
|
|
# Calculer le chemin relatif
|
|
relpath="${file#./my-notes/}"
|
|
|
|
# Upload
|
|
curl -X PUT http://localhost:8080/api/v1/notes/"$relpath" \
|
|
-H "Content-Type: text/markdown" \
|
|
--data-binary @"$file"
|
|
|
|
echo "✓ Uploaded: $relpath"
|
|
done
|
|
|
|
echo "Upload terminé!"
|
|
```
|
|
|
|
### Recherche et filtrage
|
|
|
|
**Lister toutes les notes avec un tag spécifique** :
|
|
|
|
```bash
|
|
curl -s http://localhost:8080/api/v1/notes | \
|
|
jq '.notes[] | select(.tags | contains(["projet"])) | .path'
|
|
```
|
|
|
|
**Compter les notes par dossier** :
|
|
|
|
```bash
|
|
curl -s http://localhost:8080/api/v1/notes | \
|
|
jq -r '.notes[].path' | \
|
|
xargs -n1 dirname | \
|
|
sort | uniq -c
|
|
```
|
|
|
|
### Création automatique de notes
|
|
|
|
**Note quotidienne** :
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Créer une note quotidienne
|
|
|
|
TODAY=$(date +%Y-%m-%d)
|
|
TITLE="Notes du $(date +%d/%m/%Y)"
|
|
|
|
curl -X PUT http://localhost:8080/api/v1/notes/daily/${TODAY}.md \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"body\": \"\\n# ${TITLE}\\n\\n## Tasks\\n- [ ] TODO\\n\\n## Notes\\n\",
|
|
\"frontMatter\": {
|
|
\"title\": \"${TITLE}\",
|
|
\"tags\": [\"daily\"]
|
|
}
|
|
}"
|
|
|
|
echo "Note quotidienne créée: daily/${TODAY}.md"
|
|
```
|
|
|
|
### Intégration avec d'autres outils
|
|
|
|
**Exporter en HTML avec Pandoc** :
|
|
|
|
```bash
|
|
curl -s http://localhost:8080/api/v1/notes/projet/doc.md \
|
|
-H "Accept: text/markdown" | \
|
|
pandoc -f markdown -t html -o doc.html
|
|
|
|
echo "Exporté en HTML: doc.html"
|
|
```
|
|
|
|
**Recherche full-text avec jq** :
|
|
|
|
```bash
|
|
# Chercher "API" dans tous les titres
|
|
curl -s http://localhost:8080/api/v1/notes | \
|
|
jq '.notes[] | select(.title | contains("API"))'
|
|
```
|
|
|
|
### Script de maintenance
|
|
|
|
**Vérifier les notes sans tags** :
|
|
|
|
```bash
|
|
curl -s http://localhost:8080/api/v1/notes | \
|
|
jq -r '.notes[] | select(.tags | length == 0) | .path'
|
|
```
|
|
|
|
**Statistiques** :
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Afficher des statistiques sur les notes
|
|
|
|
STATS=$(curl -s http://localhost:8080/api/v1/notes)
|
|
|
|
TOTAL=$(echo "$STATS" | jq '.total')
|
|
TOTAL_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add')
|
|
AVG_SIZE=$(echo "$STATS" | jq '[.notes[].size] | add / length | floor')
|
|
|
|
echo "📊 Statistiques des notes"
|
|
echo "========================"
|
|
echo "Total de notes: $TOTAL"
|
|
echo "Taille totale: $(numfmt --to=iec-i --suffix=B $TOTAL_SIZE)"
|
|
echo "Taille moyenne: $(numfmt --to=iec-i --suffix=B $AVG_SIZE)"
|
|
echo ""
|
|
echo "Top 5 tags:"
|
|
echo "$STATS" | jq -r '.notes[].tags[]' | sort | uniq -c | sort -rn | head -5
|
|
```
|
|
|
|
---
|
|
|
|
## Bonnes pratiques
|
|
|
|
### Sécurité
|
|
|
|
1. **Ne pas exposer publiquement sans authentification**
|
|
2. **Utiliser HTTPS en production**
|
|
3. **Valider les chemins côté client** (éviter `../` malveillants)
|
|
4. **Limiter la taille des uploads** (si nécessaire, ajouter un middleware)
|
|
|
|
### Performance
|
|
|
|
1. **Pagination** : L'API liste ne pagine pas actuellement (toutes les notes en une requête). Pour beaucoup de notes (>1000), envisager d'ajouter `?limit=` et `?offset=`
|
|
2. **Cache** : Utiliser un proxy cache (Varnish, nginx) pour GET
|
|
3. **Compression** : Activer gzip sur le reverse proxy
|
|
|
|
### Workflow recommandé
|
|
|
|
1. **Backup régulier** : Script cron qui télécharge toutes les notes
|
|
2. **Versioning Git** : Synchroniser le dossier de notes avec Git
|
|
3. **CI/CD** : Valider le format Markdown avec des linters
|
|
4. **Monitoring** : Logger les accès API pour audit
|
|
|
|
---
|
|
|
|
## Support et contribution
|
|
|
|
- **Issues** : Rapporter les bugs sur GitHub
|
|
- **Documentation** : Ce fichier (`API.md`)
|
|
- **Code source** : `internal/api/rest_handler.go`
|
|
|
|
---
|
|
|
|
## Changelog
|
|
|
|
### v1 (2025-11-10)
|
|
- ✨ Première version de l'API REST
|
|
- ✅ Endpoints: LIST, GET, PUT, DELETE
|
|
- ✅ Content negotiation JSON/Markdown
|
|
- ✅ Support sous-dossiers
|
|
- ✅ Gestion automatique du front matter
|
|
- ✅ Ré-indexation automatique
|
|
|
|
---
|
|
|
|
**Note** : Cette API coexiste avec l'interface web HTML. Les deux peuvent être utilisées simultanément sans conflit.
|