/pictures und /audio endpoints moved under /poi

This commit is contained in:
Florian Zumpe
2026-06-17 01:14:19 +02:00
parent 833b5ad3a4
commit 5c85a0194b
9 changed files with 225 additions and 267 deletions
+64 -101
View File
@@ -129,13 +129,13 @@ Beispiele verwenden überwiegend Route `1`, POI `7` und Bild `15`.
"lon": 13.407,
"triggerRadiusM": 60,
"sequence": 2,
"audioUrl": "/api/routes/1/audio/7",
"audioUrl": "/api/routes/1/pois/7/audio",
"images": [
{
"id": 15,
"caption": "Blick auf die Baumkrone",
"sequence": 0,
"url": "/api/routes/1/pictures/15"
"url": "/api/routes/1/pois/7/pictures/15"
}
]
}
@@ -151,7 +151,7 @@ Beispiele verwenden überwiegend Route `1`, POI `7` und Bild `15`.
"poiTitle": "Die alte Eiche",
"caption": "Blick auf die Baumkrone",
"sequence": 0,
"url": "/api/routes/1/pictures/15",
"url": "/api/routes/1/pois/7/pictures/15",
"createdAt": "2026-06-16 12:30:00"
}
```
@@ -165,7 +165,7 @@ Pro POI kann höchstens eine Audiodatei existieren. Deshalb wird die Audioressou
"routeId": 1,
"poiId": 7,
"poiTitle": "Die alte Eiche",
"url": "/api/routes/1/audio/7",
"url": "/api/routes/1/pois/7/audio",
"updatedAt": "2026-06-16 12:35:00"
}
```
@@ -187,16 +187,15 @@ Pro POI kann höchstens eine Audiodatei existieren. Deshalb wird die Audioressou
| `GET` | `/api/pois/:id` | einzelnen POI lesen |
| `POST` | `/api/routes/:id/pois` | POI-Metadaten anlegen |
| `PUT` | `/api/pois/:id` | POI-Metadaten aktualisieren |
| `GET` | `/api/routes/:id/pictures` | Bilder einer Route auflisten |
| `GET` | `/api/routes/:id/pictures/:pictureId` | Bilddatei ausliefern; optional Metadaten mit `?metadata=true` |
| `POST` | `/api/routes/:id/pictures` | einzelnes Bild hochladen |
| `PUT` | `/api/routes/:id/pictures/:pictureId` | Bilddatei oder Metadaten aktualisieren |
| `DELETE` | `/api/routes/:id/pictures/:pictureId` | einzelnes Bild löschen |
| `GET` | `/api/routes/:id/audio` | Audiodateien einer Route auflisten |
| `GET` | `/api/routes/:id/audio/:poiId` | Audiodatei ausliefern; optional Metadaten mit `?metadata=true` |
| `POST` | `/api/routes/:id/audio` | Audiodatei für einen POI anlegen |
| `PUT` | `/api/routes/:id/audio/:poiId` | Audiodatei eines POIs ersetzen |
| `DELETE` | `/api/routes/:id/audio/:poiId` | Audiodatei eines POIs löschen |
| `GET` | `/api/routes/:routeId/pois/:poiId/pictures` | Bilder eines POIs auflisten |
| `GET` | `/api/routes/:routeId/pois/:poiId/pictures/:pictureId` | Bilddatei ausliefern; optional Metadaten mit `?metadata=true` |
| `POST` | `/api/routes/:routeId/pois/:poiId/pictures` | einzelnes Bild für den POI hochladen |
| `PUT` | `/api/routes/:routeId/pois/:poiId/pictures/:pictureId` | Bilddatei oder Metadaten aktualisieren |
| `DELETE` | `/api/routes/:routeId/pois/:poiId/pictures/:pictureId` | einzelnes Bild löschen |
| `GET` | `/api/routes/:routeId/pois/:poiId/audio` | Audiodatei ausliefern; optional Metadaten mit `?metadata=true` |
| `POST` | `/api/routes/:routeId/pois/:poiId/audio` | Audiodatei für den POI anlegen |
| `PUT` | `/api/routes/:routeId/pois/:poiId/audio` | Audiodatei des POIs ersetzen |
| `DELETE` | `/api/routes/:routeId/pois/:poiId/audio` | Audiodatei des POIs löschen |
## 4. Systemzustand
@@ -417,29 +416,24 @@ curl -X PUT http://127.0.0.1:47145/api/pois/7 \
}'
```
## 8. Bilder einzeln verwalten
## 8. Bilder eines POIs einzeln verwalten
### `GET /api/routes/:id/pictures`
Die Route und der POI sind Bestandteil jedes Bildpfades. Dadurch ist die Zuordnung eindeutig und beim Upload muss keine zusätzliche `poiId` übergeben werden.
Liefert alle Bilder der Route. Optional kann auf einen POI eingeschränkt werden.
#### Query-Parameter
### Gemeinsame Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---:|---|
| `poiId` | positive Ganzzahl | nein | liefert nur Bilder dieses POIs |
| `routeId` | positive Ganzzahl | ja | ID der aktiven Route |
| `poiId` | positive Ganzzahl | ja | ID eines POIs, der zu dieser Route gehört |
| `pictureId` | positive Ganzzahl | nur bei Einzelressourcen | ID des Bildes, das zu diesem POI gehört |
Alle Bilder der Route:
### `GET /api/routes/:routeId/pois/:poiId/pictures`
Liefert alle Bilder des angegebenen POIs in Diashow-Reihenfolge.
```bash
curl http://127.0.0.1:47145/api/routes/1/pictures
```
Nur Bilder des POIs `7`:
```bash
curl --get http://127.0.0.1:47145/api/routes/1/pictures \
--data-urlencode 'poiId=7'
curl http://127.0.0.1:47145/api/routes/1/pois/7/pictures
```
```json
@@ -452,28 +446,28 @@ curl --get http://127.0.0.1:47145/api/routes/1/pictures \
"poiTitle": "Die alte Eiche",
"caption": "Blick auf die Baumkrone",
"sequence": 0,
"url": "/api/routes/1/pictures/15",
"url": "/api/routes/1/pois/7/pictures/15",
"createdAt": "2026-06-16 12:30:00"
}
]
}
```
### `GET /api/routes/:id/pictures/:pictureId`
### `GET /api/routes/:routeId/pois/:poiId/pictures/:pictureId`
Liefert standardmäßig die Bilddatei direkt aus. Genau dieser Pfad wird im Feld `url` der Bildressource und unter `pois[].images[].url` ausgegeben.
Bild speichern:
```bash
curl http://127.0.0.1:47145/api/routes/1/pictures/15 \
curl http://127.0.0.1:47145/api/routes/1/pois/7/pictures/15 \
--output bild-15.jpg
```
Metadaten statt Dateidaten abrufen:
```bash
curl --get http://127.0.0.1:47145/api/routes/1/pictures/15 \
curl --get http://127.0.0.1:47145/api/routes/1/pois/7/pictures/15 \
--data-urlencode 'metadata=true'
```
@@ -481,57 +475,54 @@ curl --get http://127.0.0.1:47145/api/routes/1/pictures/15 \
|---|---|---:|---:|---|
| `metadata` | Boolean | nein | `false` | bei `true` JSON-Metadaten statt der Bilddatei liefern |
### `POST /api/routes/:id/pictures`
Die API antwortet mit `404`, wenn Route, POI oder Bild nicht zusammengehören.
Lädt genau ein Bild hoch und ordnet es einem POI derselben Route zu.
### `POST /api/routes/:routeId/pois/:poiId/pictures`
Lädt genau ein Bild für den im Pfad angegebenen POI hoch.
Content-Type: `multipart/form-data`
| Feld | Typ | Pflicht | Standard | Beschreibung |
|---|---|---:|---:|---|
| `picture` | Datei | ja | – | JPEG-, PNG- oder WebP-Datei |
| `poiId` | positive Ganzzahl | ja | – | Ziel-POI derselben Route |
| `caption` | Text | nein | leer | sichtbare Bildbeschreibung und Grundlage für den Alternativtext |
| `sequence` | nichtnegative Ganzzahl | nein | nächster freier Wert des POIs | Reihenfolge in der Diashow |
```bash
curl -X POST http://127.0.0.1:47145/api/routes/1/pictures \
-F 'poiId=7' \
curl -X POST http://127.0.0.1:47145/api/routes/1/pois/7/pictures \
-F 'caption=Blick auf die Baumkrone' \
-F 'sequence=0' \
-F 'picture=@eiche.jpg;type=image/jpeg'
```
Erfolg: `201 Created` und `Location: /api/routes/1/pictures/<pictureId>`.
Erfolg: `201 Created` und `Location: /api/routes/1/pois/7/pictures/<pictureId>`.
### `PUT /api/routes/:id/pictures/:pictureId`
### `PUT /api/routes/:routeId/pois/:poiId/pictures/:pictureId`
Aktualisiert Metadaten und kann optional die Datei ersetzen. Nicht übergebene Metadaten bleiben erhalten.
Aktualisiert Metadaten und kann optional die Datei ersetzen. Nicht übergebene Metadaten bleiben erhalten. Ein Bild kann über diesen Endpunkt nicht einem anderen POI zugeordnet werden; dafür muss es beim bisherigen POI gelöscht und beim Ziel-POI neu angelegt werden.
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---:|---|
| `picture` | Datei | nein | ersetzt die bisherige Bilddatei |
| `poiId` | positive Ganzzahl | nein | ordnet das Bild einem anderen POI derselben Route zu |
| `caption` | Text | nein | neue Bildbeschreibung; leerer Text entfernt die Beschreibung |
| `sequence` | nichtnegative Ganzzahl | nein | neue Position in der Diashow |
Nur Metadaten per JSON ändern:
```bash
curl -X PUT http://127.0.0.1:47145/api/routes/1/pictures/15 \
curl -X PUT http://127.0.0.1:47145/api/routes/1/pois/7/pictures/15 \
-H 'Content-Type: application/json' \
-d '{
"poiId": 7,
"caption": "Nahaufnahme der Eichenblätter",
"sequence": 1
}'
```
Datei und alle Metadaten ersetzen:
Datei und Metadaten ersetzen:
```bash
curl -X PUT http://127.0.0.1:47145/api/routes/1/pictures/15 \
-F 'poiId=7' \
curl -X PUT http://127.0.0.1:47145/api/routes/1/pois/7/pictures/15 \
-F 'caption=Neue Aufnahme der Eiche' \
-F 'sequence=2' \
-F 'picture=@eiche-neu.webp;type=image/webp'
@@ -539,12 +530,12 @@ curl -X PUT http://127.0.0.1:47145/api/routes/1/pictures/15 \
Wird eine Datei ersetzt, entfernt der Server die bisherige Datei nach erfolgreicher Datenbankaktualisierung.
### `DELETE /api/routes/:id/pictures/:pictureId`
### `DELETE /api/routes/:routeId/pois/:poiId/pictures/:pictureId`
Entfernt Bilddatensatz und Datei.
```bash
curl -X DELETE http://127.0.0.1:47145/api/routes/1/pictures/15
curl -X DELETE http://127.0.0.1:47145/api/routes/1/pois/7/pictures/15
```
```json
@@ -556,58 +547,32 @@ curl -X DELETE http://127.0.0.1:47145/api/routes/1/pictures/15
}
```
## 9. Audiodateien einzeln verwalten
## 9. Audiodatei eines POIs verwalten
Pro POI ist höchstens eine Audiodatei vorgesehen. Deshalb bildet die `poiId` den Schlüssel der Audioressource.
Pro POI ist höchstens eine Audiodatei vorgesehen. Daher ist `/audio` selbst die Einzelressource; eine zusätzliche Audio-ID ist nicht erforderlich.
### `GET /api/routes/:id/audio`
Liefert alle vorhandenen Audiodateien der Route. POIs ohne Audio werden nicht ausgegeben.
#### Query-Parameter
### Gemeinsame Pfadparameter
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---:|---|
| `poiId` | positive Ganzzahl | nein | schränkt die Liste auf einen POI ein |
| `routeId` | positive Ganzzahl | ja | ID der aktiven Route |
| `poiId` | positive Ganzzahl | ja | ID eines POIs, der zu dieser Route gehört |
```bash
curl http://127.0.0.1:47145/api/routes/1/audio
```
### `GET /api/routes/:routeId/pois/:poiId/audio`
```bash
curl --get http://127.0.0.1:47145/api/routes/1/audio \
--data-urlencode 'poiId=7'
```
```json
{
"audio": [
{
"routeId": 1,
"poiId": 7,
"poiTitle": "Die alte Eiche",
"url": "/api/routes/1/audio/7",
"updatedAt": "2026-06-16 12:35:00"
}
]
}
```
### `GET /api/routes/:id/audio/:poiId`
Liefert standardmäßig die Audiodatei des POIs direkt aus. Genau dieser Pfad wird in `audioUrl` und im Feld `url` einer Audioressource ausgegeben. Der Endpunkt unterstützt HTTP-Range-Anfragen, damit Browser innerhalb einer Audiodatei springen können.
Liefert standardmäßig die Audiodatei des POIs direkt aus. Genau dieser Pfad wird in `audioUrl` und im Feld `url` der Audioressource ausgegeben. Der Endpunkt unterstützt HTTP-Range-Anfragen, damit Browser innerhalb der Audiodatei springen können.
Audiodatei speichern:
```bash
curl http://127.0.0.1:47145/api/routes/1/audio/7 \
curl http://127.0.0.1:47145/api/routes/1/pois/7/audio \
--output ansage-7.mp3
```
Metadaten statt Dateidaten abrufen:
```bash
curl --get http://127.0.0.1:47145/api/routes/1/audio/7 \
curl --get http://127.0.0.1:47145/api/routes/1/pois/7/audio \
--data-urlencode 'metadata=true'
```
@@ -615,30 +580,28 @@ curl --get http://127.0.0.1:47145/api/routes/1/audio/7 \
|---|---|---:|---:|---|
| `metadata` | Boolean | nein | `false` | bei `true` JSON-Metadaten statt der Audiodatei liefern |
Antwortet mit `404`, wenn der POI keine Audiodatei besitzt.
Antwortet mit `404`, wenn Route und POI nicht zusammengehören oder der POI keine Audiodatei besitzt.
### `POST /api/routes/:id/audio`
### `POST /api/routes/:routeId/pois/:poiId/audio`
Legt die Audiodatei eines POIs an.
Legt die Audiodatei des im Pfad angegebenen POIs an.
Content-Type: `multipart/form-data`
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---:|---|
| `audio` | Datei | ja | MP3-, MP4/M4A-, AAC-, Ogg-, WAV- oder WebM-Datei |
| `poiId` | positive Ganzzahl | ja | POI derselben Route |
```bash
curl -X POST http://127.0.0.1:47145/api/routes/1/audio \
-F 'poiId=7' \
curl -X POST http://127.0.0.1:47145/api/routes/1/pois/7/audio \
-F 'audio=@ansage.mp3;type=audio/mpeg'
```
Erfolg: `201 Created` und `Location: /api/routes/1/audio/7`.
Erfolg: `201 Created` und `Location: /api/routes/1/pois/7/audio`.
Existiert bereits eine Audiodatei, antwortet der Server mit `409`. Zum Ersetzen ist `PUT` zu verwenden.
### `PUT /api/routes/:id/audio/:poiId`
### `PUT /api/routes/:routeId/pois/:poiId/audio`
Ersetzt die vorhandene Audiodatei des POIs.
@@ -647,18 +610,18 @@ Ersetzt die vorhandene Audiodatei des POIs.
| `audio` | Datei | ja | neue Audiodatei |
```bash
curl -X PUT http://127.0.0.1:47145/api/routes/1/audio/7 \
curl -X PUT http://127.0.0.1:47145/api/routes/1/pois/7/audio \
-F 'audio=@ansage-neu.ogg;type=audio/ogg'
```
Der Server entfernt die bisherige Datei nach erfolgreicher Aktualisierung. Besitzt der POI noch keine Audiodatei, antwortet der Server mit `404`; zum erstmaligen Anlegen ist `POST` zu verwenden.
### `DELETE /api/routes/:id/audio/:poiId`
### `DELETE /api/routes/:routeId/pois/:poiId/audio`
Entfernt die Audiodatei und setzt `audioUrl` des POIs auf `null`.
```bash
curl -X DELETE http://127.0.0.1:47145/api/routes/1/audio/7
curl -X DELETE http://127.0.0.1:47145/api/routes/1/pois/7/audio
```
```json
@@ -706,8 +669,8 @@ Die API veröffentlicht keine internen Speicherpfade und keine `/media/...`-Adre
```text
GET /api/routes/1/gpx
GET /api/routes/1/pictures/15
GET /api/routes/1/audio/7
GET /api/routes/1/pois/7/pictures/15
GET /api/routes/1/pois/7/audio
```
Die Zuordnung lautet:
@@ -715,9 +678,9 @@ Die Zuordnung lautet:
| JSON-Feld | Datei-Endpunkt |
|---|---|
| `route.gpxUrl` | `/api/routes/:id/gpx` |
| `poi.audioUrl` | `/api/routes/:id/audio/:poiId` |
| `poi.images[].url` | `/api/routes/:id/pictures/:pictureId` |
| `picture.url` | `/api/routes/:id/pictures/:pictureId` |
| `audio.url` | `/api/routes/:id/audio/:poiId` |
| `poi.audioUrl` | `/api/routes/:routeId/pois/:poiId/audio` |
| `poi.images[].url` | `/api/routes/:routeId/pois/:poiId/pictures/:pictureId` |
| `picture.url` | `/api/routes/:routeId/pois/:poiId/pictures/:pictureId` |
| `audio.url` | `/api/routes/:routeId/pois/:poiId/audio` |
Die Dateinamen und relativen Pfade unter `storage/` bleiben ausschließlich interne Implementierungsdetails. Dateien gelöschter Routen liegen im Papierkorb und sind über keinen Datei-Endpunkt erreichbar.