Procházet zdrojové kódy

Add 'Firebase: no' header, closes #42

Philipp Heckel před 4 roky
rodič
revize
f966b2f9d7
3 změnil soubory, kde provedl 88 přidání a 14 odebrání
  1. 10 1
      docs/examples.md
  2. 66 1
      docs/publish.md
  3. 12 12
      server/server.go

+ 10 - 1
docs/examples.md

@@ -64,5 +64,14 @@ It looked something like this:
     curl -d "$(hostname),$count,$time" ntfy.sh/results
     ```
 
+## Ansible, Salt and Puppet
+You can easily integrate ntfy into Ansible, Salt, or Puppet to notify you when runs are done or are highstated.
+One of my co-workers uses the following Ansible task to let him know when things are done:
 
-
+```yml
+- name: Send ntfy.sh update
+  uri:
+    url: "https://ntfy.sh/{{ ntfy_channel }}"
+    method: POST
+    body: "{{ inventory_hostname }} reseeding complete"
+```

+ 66 - 1
docs/publish.md

@@ -332,7 +332,14 @@ them with a comma, e.g. `tag1,tag2,tag3`.
   <figcaption>Detail view of notifications with tags</figcaption>
 </figure>
 
-## Message caching
+## Advanced features
+
+### Message caching
+!!! info
+    If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a 
+    client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily, 
+    **messages might be missed**.
+
 By default, the ntfy server caches messages on disk for 12 hours (see [message caching](config.md#message-cache)), so
 all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary 
 client-side network disruptions, but arguably this feature also may raise privacy concerns.
@@ -385,3 +392,61 @@ are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fe
         ]
     ]));
     ```
+
+### Firebase
+!!! info
+    If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android 
+    app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome 
+    this delay, simply enable instant delivery.
+
+The ntfy server can be configured to use [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging)
+(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint). 
+The ntfy.sh server is configured this way, meaning that all messages published to ntfy.sh are also published to corresponding
+FCM topics.
+
+If you'd like to avoid forwarding messages to Firebase, you can set the `X-Firebase` header (or its alias: `Firebase`)
+to `no`. This will instruct the server not to forward messages to Firebase.
+
+=== "Command line (curl)"
+    ```
+    curl -H "X-Firebase: no" -d "This message won't be forwarded to FCM" ntfy.sh/mytopic
+    curl -H "Firebase: no" -d "This message won't be forwarded to FCM" ntfy.sh/mytopic
+    ```
+
+=== "HTTP"
+    ``` http
+    POST /mytopic HTTP/1.1
+    Host: ntfy.sh
+    Firebase: no
+
+    This message won't be forwarded to FCM
+    ```
+
+=== "JavaScript"
+    ``` javascript
+    fetch('https://ntfy.sh/mytopic', {
+        method: 'POST',
+        body: 'This message won't be forwarded to FCM',
+        headers: { 'Firebase': 'no' }
+    })
+    ```
+
+=== "Go"
+    ``` go
+    req, _ := http.NewRequest("POST", "https://ntfy.sh/mytopic", strings.NewReader("This message won't be forwarded to FCM"))
+    req.Header.Set("Firebase", "no")
+    http.DefaultClient.Do(req)
+    ```
+
+=== "PHP"
+    ``` php-inline
+    file_get_contents('https://ntfy.sh/mytopic', false, stream_context_create([
+        'http' => [
+            'method' => 'POST',
+            'header' =>
+                "Content-Type: text/plain\r\n" .
+                "Firebase: no",
+            'content' => 'This message won't be stored server-side'
+        ]
+    ]));
+    ```

+ 12 - 12
server/server.go

@@ -128,11 +128,6 @@ func New(conf *config.Config) (*Server, error) {
 	if err != nil {
 		return nil, err
 	}
-	for _, t := range topics {
-		if firebaseSubscriber != nil {
-			t.Subscribe(firebaseSubscriber)
-		}
-	}
 	return &Server{
 		config:   conf,
 		cache:    cache,
@@ -284,13 +279,20 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
 	if m.Message == "" {
 		return errHTTPBadRequest
 	}
-	title, priority, tags, cache := parseHeaders(r.Header)
+	title, priority, tags, cache, firebase := parseHeaders(r.Header)
 	m.Title = title
 	m.Priority = priority
 	m.Tags = tags
 	if err := t.Publish(m); err != nil {
 		return err
 	}
+	if s.firebase != nil && firebase {
+		go func() {
+			if err := s.firebase(m); err != nil {
+				log.Printf("Unable to publish to Firebase: %v", err.Error())
+			}
+		}()
+	}
 	if cache {
 		if err := s.cache.AddMessage(m); err != nil {
 			return err
@@ -306,7 +308,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, _ *visito
 	return nil
 }
 
-func parseHeaders(header http.Header) (title string, priority int, tags []string, cache bool) {
+func parseHeaders(header http.Header) (title string, priority int, tags []string, cache bool, firebase bool) {
 	title = readHeader(header, "x-title", "title", "ti", "t")
 	priorityStr := readHeader(header, "x-priority", "priority", "prio", "p")
 	if priorityStr != "" {
@@ -333,7 +335,8 @@ func parseHeaders(header http.Header) (title string, priority int, tags []string
 		}
 	}
 	cache = readHeader(header, "x-cache", "cache") != "no"
-	return title, priority, tags, cache
+	firebase = readHeader(header, "x-firebase", "firebase") != "no"
+	return title, priority, tags, cache, firebase
 }
 
 func readHeader(header http.Header, names ...string) string {
@@ -512,9 +515,6 @@ func (s *Server) topicsFromIDs(ids ...string) ([]*topic, error) {
 				return nil, errHTTPTooManyRequests
 			}
 			s.topics[id] = newTopic(id)
-			if s.firebase != nil {
-				s.topics[id].Subscribe(s.firebase)
-			}
 		}
 		topics = append(topics, s.topics[id])
 	}
@@ -547,7 +547,7 @@ func (s *Server) updateStatsAndExpire() {
 			log.Printf("cannot get stats for topic %s: %s", t.ID, err.Error())
 			continue
 		}
-		if msgs == 0 && (subs == 0 || (s.firebase != nil && subs == 1)) { // Firebase is a subscriber!
+		if msgs == 0 && subs == 0 {
 			delete(s.topics, t.ID)
 			continue
 		}