change GET to POST, removed /health
This commit is contained in:
52
README.md
52
README.md
@@ -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:
|
||||||
|
|||||||
25
server.js
25
server.js
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user