support clear|read via GET

This commit is contained in:
Hunter Kehoe
2026-06-06 10:38:09 -06:00
parent 88fff8264b
commit 26bc28ae24
3 changed files with 44 additions and 2 deletions
+16 -1
View File
@@ -4104,26 +4104,41 @@ field the response. A sequence of updates may look like this (first example from
### Clearing notifications ### Clearing notifications
Clearing a notification means **marking it as read and dismissing it from the notification drawer**. Clearing a notification means **marking it as read and dismissing it from the notification drawer**.
To do this, send a PUT request to the `/<topic>/<sequence_id>/clear` endpoint (or `/<topic>/<sequence_id>/read` as an alias). To do this, send a `PUT` request to the `/<topic>/<sequence_id>/clear` endpoint (or `/<topic>/<sequence_id>/read` as an alias).
This will then emit a `message_clear` event that is used by the clients (web app and Android app) to update the read status This will then emit a `message_clear` event that is used by the clients (web app and Android app) to update the read status
and dismiss the notification. and dismiss the notification.
Alternatively, if your client has limited HTTP support, you can send a `GET` request to the same endpoints:
`GET /<topic>/<sequence_id>/clear` or `GET /<topic>/<sequence_id>/read`.
=== "Command line (curl)" === "Command line (curl)"
```bash ```bash
# Via PUT method
curl -X PUT ntfy.sh/mytopic/my-download-123/clear curl -X PUT ntfy.sh/mytopic/my-download-123/clear
# Via GET method
curl ntfy.sh/mytopic/my-download-123/clear
``` ```
=== "HTTP" === "HTTP"
``` http ``` http
PUT /mytopic/my-download-123/clear HTTP/1.1 PUT /mytopic/my-download-123/clear HTTP/1.1
Host: ntfy.sh Host: ntfy.sh
# Or using GET
GET /mytopic/my-download-123/clear HTTP/1.1
Host: ntfy.sh
``` ```
=== "JavaScript" === "JavaScript"
``` javascript ``` javascript
// Via PUT method
await fetch('https://ntfy.sh/mytopic/my-download-123/clear', { await fetch('https://ntfy.sh/mytopic/my-download-123/clear', {
method: 'PUT' method: 'PUT'
}); });
// Via GET method
await fetch('https://ntfy.sh/mytopic/my-download-123/clear');
``` ```
=== "Go" === "Go"
+1 -1
View File
@@ -648,7 +648,7 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit
return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleDelete))(w, r, v) return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleDelete))(w, r, v)
} else if r.Method == http.MethodGet && deletePathRegex.MatchString(r.URL.Path) { } else if r.Method == http.MethodGet && deletePathRegex.MatchString(r.URL.Path) {
return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleDelete))(w, r, v) return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleDelete))(w, r, v)
} else if r.Method == http.MethodPut && clearPathRegex.MatchString(r.URL.Path) { } else if (r.Method == http.MethodGet || r.Method == http.MethodPut) && clearPathRegex.MatchString(r.URL.Path) {
return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleClear))(w, r, v) return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handleClear))(w, r, v)
} else if r.Method == http.MethodGet && publishPathRegex.MatchString(r.URL.Path) { } else if r.Method == http.MethodGet && publishPathRegex.MatchString(r.URL.Path) {
return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handlePublish))(w, r, v) return s.limitRequestsWithTopic(s.authorizeTopicWrite(s.handlePublish))(w, r, v)
+27
View File
@@ -4113,6 +4113,33 @@ func TestServer_ClearMessage_ReadEndpoint(t *testing.T) {
}) })
} }
func TestServer_ClearMessage_GET(t *testing.T) {
forEachBackend(t, func(t *testing.T, databaseURL string) {
t.Parallel()
s := newTestServer(t, newTestConfig(t, databaseURL))
// 1. Test GET /topic/seq-id/clear
response := request(t, s, "PUT", "/mytopic/seq456", "original message 1", nil)
require.Equal(t, 200, response.Code)
response = request(t, s, "GET", "/mytopic/seq456/clear", "", nil)
require.Equal(t, 200, response.Code)
clearMsg1 := toMessage(t, response.Body.String())
require.Equal(t, "seq456", clearMsg1.SequenceID)
require.Equal(t, "message_clear", clearMsg1.Event)
// 2. Test GET /topic/seq-id/read
response = request(t, s, "PUT", "/mytopic/seq789", "original message 2", nil)
require.Equal(t, 200, response.Code)
response = request(t, s, "GET", "/mytopic/seq789/read", "", nil)
require.Equal(t, 200, response.Code)
clearMsg2 := toMessage(t, response.Body.String())
require.Equal(t, "seq789", clearMsg2.SequenceID)
require.Equal(t, "message_clear", clearMsg2.Event)
})
}
func TestServer_UpdateMessage(t *testing.T) { func TestServer_UpdateMessage(t *testing.T) {
forEachBackend(t, func(t *testing.T, databaseURL string) { forEachBackend(t, func(t *testing.T, databaseURL string) {
t.Parallel() t.Parallel()