change GET to POST, removed /health

This commit is contained in:
cpu
2025-03-28 02:12:52 +01:00
parent 228f4984d8
commit 4f46c1be99
2 changed files with 19 additions and 58 deletions

View File

@@ -6,9 +6,9 @@ It's designed to be run as a Docker container and integrated with Traefik v3 for
## Features ## Features
* Receives POST requests on `/flic-webhook`. * Receives GET requests on `/flic-webhook`.
* Uses HTTP headers `Button-Name` and `Timestamp` from the Flic request. * Uses HTTP headers `Button-Name` and `Timestamp` from the Flic request.
* Parses `click_type` from the Flic request body. * Gets `click_type` from query parameter.
* Looks up the target PWA push subscription based on the `Button-Name` header in a JSON file. * Looks up the target PWA push subscription based on the `Button-Name` header in a JSON file.
* Sends a Web Push notification containing the click details (action, button, timestamp) to the corresponding PWA subscription. * Sends a Web Push notification containing the click details (action, button, timestamp) to the corresponding PWA subscription.
* Integrates with Traefik v3 via Docker labels. * Integrates with Traefik v3 via Docker labels.
@@ -87,7 +87,7 @@ It's designed to be run as a Docker container and integrated with Traefik v3 for
* Add entries mapping your Flic button's serial number (as a lowercase string key) to the PWA `PushSubscription` object. * Add entries mapping your Flic button's serial number (as a lowercase string key) to the PWA `PushSubscription` object.
```json ```json
{ {
"80:e4:da:70:xx:xx:xx:xx": { // <-- Replace with your actual Flic Button Serial (lowercase recommended) "game": { // <-- Replace with your actual Flic Button name (lowercase recommended)
"endpoint": "https://your_pwa_push_endpoint...", "endpoint": "https://your_pwa_push_endpoint...",
"expirationTime": null, "expirationTime": null,
"keys": { "keys": {
@@ -119,11 +119,6 @@ It's designed to be run as a Docker container and integrated with Traefik v3 for
--mount type=bind,src=./subscriptions.json,dst=/app/subscriptions.json \ --mount type=bind,src=./subscriptions.json,dst=/app/subscriptions.json \
flic-webhook-webpush:latest flic-webhook-webpush:latest
``` ```
* `--network traefik`: Connects to the Traefik network.
* `--env-file .env`: Loads configuration from your `.env` file.
* `--label-file labels`: Applies the Traefik routing rules from your edited `labels` file.
* `--mount ...`: Makes your local `subscriptions.json` available inside the container at `/app/subscriptions.json`. `readonly` is recommended as the app only reads it.
* `flic-webhook-webpush:latest`: The image built in the previous step.
3. **Check Logs:** 3. **Check Logs:**
Monitor the container logs to ensure it started correctly and to see incoming webhook requests or errors. Monitor the container logs to ensure it started correctly and to see incoming webhook requests or errors.
@@ -141,18 +136,11 @@ In your Flic app or Flic Hub SDK interface:
1. Select your Flic button. 1. Select your Flic button.
2. Add an "Internet Request" action. 2. Add an "Internet Request" action.
3. Fill in the following details: 3. Fill in the following details:
* Set `POST` method. * Set `GET` method.
* Set URL: `https://webpush.virtonline.eu/flic-webhook` * Set URL with query parameter: `https://webpush.virtonline.eu/flic-webhook?click_type=SingleClick`
* Add headers: * Add headers:
* Key: `Authorization` * Key: `Authorization`
* Value: `Bearer <FLIC_SECRET>` (Replace `<FLIC_SECRET>` with the actual secret from your `.env` file). * Value: `Bearer <FLIC_SECRET>` (Replace `<FLIC_SECRET>` with the actual secret from your `.env` file).
* **Body:** Configure the JSON body to include the click type.
```json
{
"click_type": "SingleClick"
}
```
* Set Content-Type: `application/json`.
* It should look like this: * It should look like this:
<!-- <img src="images/flic-button-request.png" width="300" alt="Flic Button Request Configuration"> // TODO: Update image --> <!-- <img src="images/flic-button-request.png" width="300" alt="Flic Button Request Configuration"> // TODO: Update image -->
@@ -162,33 +150,19 @@ In your Flic app or Flic Hub SDK interface:
## API Endpoint ## API Endpoint
* **`POST /flic-webhook`** * **`GET /flic-webhook`**
* **Description:** Receives Flic button events. * **Description:** Receives Flic button events.
* **Authentication:** Optional Bearer token via `Authorization` header if `FLIC_SECRET` is configured. * **Authentication:** Optional Bearer token via `Authorization` header if `FLIC_SECRET` is configured.
* **Request Body (JSON):** * **Query Parameters:**
```json * `click_type`: The type of button press (SingleClick, DoubleClick, or Hold)
{
"click_type": "SingleClick | DoubleClick | Hold"
}
```
* **Responses:** * **Responses:**
* `200 OK`: Webhook received, push notification sent successfully. * `200 OK`: Webhook received, push notification sent successfully.
* `400 Bad Request`: Missing `Button-Name` header or `click_type` in the request body. * `400 Bad Request`: Missing `Button-Name` header or `click_type` query parameter.
* `401 Unauthorized`: Missing or invalid Bearer token (if `FLIC_SECRET` is enabled). * `401 Unauthorized`: Missing or invalid Bearer token (if `FLIC_SECRET` is enabled).
* `404 Not Found`: No subscription found in `subscriptions.json` for the given `Button-Name`. * `404 Not Found`: No subscription found in `subscriptions.json` for the given `Button-Name`.
* `410 Gone`: The push subscription associated with the button was rejected by the push service (likely expired or revoked). * `410 Gone`: The push subscription associated with the button was rejected by the push service (likely expired or revoked).
* `500 Internal Server Error`: Failed to send the push notification for other reasons. * `500 Internal Server Error`: Failed to send the push notification for other reasons.
* **`GET /health`** (Optional)
* **Description:** Simple health check endpoint.
* **Response:**
```json
{
"status": "UP",
"timestamp": "ISO_8601_TIMESTAMP_STRING"
}
```
## Testing the Webhook ## Testing the Webhook
Once your service is up and running, you can test the webhook endpoint using curl or any API testing tool: Once your service is up and running, you can test the webhook endpoint using curl or any API testing tool:
@@ -196,14 +170,10 @@ Once your service is up and running, you can test the webhook endpoint using cur
**Note:** In the command below, replace `a74181969a613c545d66c1e436e75c1e4a6` with your actual FLIC_SECRET value from your .env file. **Note:** In the command below, replace `a74181969a613c545d66c1e436e75c1e4a6` with your actual FLIC_SECRET value from your .env file.
```bash ```bash
curl -X POST https://webpush.virtonline.eu/flic-webhook \ curl -X GET "https://webpush.virtonline.eu/flic-webhook?click_type=SingleClick" \
-H "Authorization: Bearer a74181969a613c545d66c1e436e75c1e4a6" \ -H "Authorization: Bearer a74181969a613c545d66c1e436e75c1e4a6" \
-H "Content-Type: application/json" \
-H "Button-Name: Game" \ -H "Button-Name: Game" \
-H "Timestamp: 2025-03-26T01:10:20Z" \ -H "Timestamp: 2025-03-26T01:10:20Z"
-d '{
"click_type": "SingleClick"
}'
``` ```
The expected response should be: The expected response should be:

View File

@@ -213,21 +213,21 @@ app.post('/subscribe', async (req, res) => {
} }
}); });
// --- Flic Webhook Endpoint --- // --- Flic Webhook Endpoint (GET only) ---
// Apply Flic-specific authentication ONLY to this route // Apply Flic-specific authentication to this route
app.post('/flic-webhook', authenticateFlicRequest, async (req, res) => { app.get('/flic-webhook', authenticateFlicRequest, async (req, res) => {
// Get buttonName from Header 'Button-Name' and timestamp from Header 'Timestamp' // Get buttonName from Header 'Button-Name' and timestamp from Header 'Timestamp'
const buttonName = req.headers['button-name']; const buttonName = req.headers['button-name'];
const timestamp = req.headers['timestamp']; const timestamp = req.headers['timestamp'];
// Still get click_type from the request body // Get click_type from query parameter instead of request body
const { click_type } = req.body; const click_type = req.query.click_type;
console.log(`Received webhook: Button=${buttonName}, Type=${click_type}, Timestamp=${timestamp || 'N/A'}`); console.log(`Received GET webhook: Button=${buttonName}, Type=${click_type}, Timestamp=${timestamp || 'N/A'}`);
// Basic validation // Basic validation
if (!buttonName || !click_type) { if (!buttonName || !click_type) {
console.warn(`Webhook Error: Missing Button-Name header or click_type in body`); console.warn(`Webhook Error: Missing Button-Name header or click_type query parameter`);
return res.status(400).json({ message: 'Bad Request: Missing Button-Name header or click_type in request body' }); return res.status(400).json({ message: 'Bad Request: Missing Button-Name header or click_type query parameter' });
} }
const normalizedButtonName = buttonName.toLowerCase(); // Use lowercase for lookup consistency const normalizedButtonName = buttonName.toLowerCase(); // Use lowercase for lookup consistency
@@ -272,15 +272,6 @@ app.post('/flic-webhook', authenticateFlicRequest, async (req, res) => {
} }
}); });
// --- Health Check Endpoint ---
app.get('/health', (req, res) => {
res.status(200).json({
status: 'UP',
timestamp: new Date().toISOString(),
subscription_count: Object.keys(subscriptions).length
});
});
// --- Start Server --- // --- Start Server ---
// Use http.createServer to allow graceful shutdown // Use http.createServer to allow graceful shutdown
const server = http.createServer(app); const server = http.createServer(app);