Truncate FCM messages if they are too long; This was trickier than expected; relates to #84
This commit is contained in:
		
							parent
							
								
									b4f71ce01a
								
							
						
					
					
						commit
						807d2b0d9d
					
				
					 2 changed files with 51 additions and 2 deletions
				
			
		|  | @ -138,6 +138,7 @@ var ( | |||
| const ( | ||||
| 	firebaseControlTopic = "~control" // See Android if changed | ||||
| 	emptyMessageBody     = "triggered" | ||||
| 	fcmMessageLimitReal  = 4100 // see maybeTruncateFCMMessage for details | ||||
| ) | ||||
| 
 | ||||
| // New instantiates a new Server. It creates the cache and adds a Firebase | ||||
|  | @ -219,15 +220,33 @@ func createFirebaseSubscriber(conf *Config) (subscriber, error) { | |||
| 				Priority: "high", | ||||
| 			} | ||||
| 		} | ||||
| 		_, err := msg.Send(context.Background(), &messaging.Message{ | ||||
| 		_, err := msg.Send(context.Background(), maybeTruncateFCMMessage(&messaging.Message{ | ||||
| 			Topic:   m.Topic, | ||||
| 			Data:    data, | ||||
| 			Android: androidConfig, | ||||
| 		}) | ||||
| 		})) | ||||
| 		return err | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // maybeTruncateFCMMessage performs best-effort truncation of FCM messages. | ||||
| // The docs says the limit is 4000 characters, but the real FCM message limit is 4100 of the | ||||
| // serialized payload; I tested this diligently. | ||||
| func maybeTruncateFCMMessage(m *messaging.Message) *messaging.Message { | ||||
| 	s, err := json.Marshal(m) | ||||
| 	if err != nil { | ||||
| 		return m | ||||
| 	} | ||||
| 	if len(s) > fcmMessageLimitReal { | ||||
| 		over := len(s) - fcmMessageLimitReal | ||||
| 		message, ok := m.Data["message"] | ||||
| 		if ok && len(message) > over { | ||||
| 			m.Data["message"] = message[:len(message)-over] | ||||
| 		} | ||||
| 	} | ||||
| 	return m | ||||
| } | ||||
| 
 | ||||
| // Run executes the main server. It listens on HTTP (+ HTTPS, if configured), and starts | ||||
| // a manager go routine to print stats and prune messages. | ||||
| func (s *Server) Run() error { | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import ( | |||
| 	"bufio" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"firebase.google.com/go/messaging" | ||||
| 	"fmt" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"net/http" | ||||
|  | @ -591,6 +592,35 @@ func TestServer_UnifiedPushDiscovery(t *testing.T) { | |||
| 	require.Equal(t, `{"unifiedpush":{"version":1}}`+"\n", response.Body.String()) | ||||
| } | ||||
| 
 | ||||
| func TestServer_MaybeTruncateFCMMessage(t *testing.T) { | ||||
| 	origMessage := strings.Repeat("this is a long string", 300) | ||||
| 	origFCMMessage := &messaging.Message{ | ||||
| 		Topic: "mytopic", | ||||
| 		Data: map[string]string{ | ||||
| 			"id":       "abcdefg", | ||||
| 			"time":     "1641324761", | ||||
| 			"event":    "message", | ||||
| 			"topic":    "mytopic", | ||||
| 			"priority": "0", | ||||
| 			"tags":     "", | ||||
| 			"title":    "", | ||||
| 			"message":  origMessage, | ||||
| 		}, | ||||
| 		Android: &messaging.AndroidConfig{ | ||||
| 			Priority: "high", | ||||
| 		}, | ||||
| 	} | ||||
| 	origMessageLength := len(origFCMMessage.Data["message"]) | ||||
| 	serializedOrigFCMMessage, _ := json.Marshal(origFCMMessage) | ||||
| 	require.Greater(t, len(serializedOrigFCMMessage), fcmMessageLimitReal) // Pre-condition | ||||
| 
 | ||||
| 	truncatedFCMMessage := maybeTruncateFCMMessage(origFCMMessage) | ||||
| 	truncatedMessageLength := len(truncatedFCMMessage.Data["message"]) | ||||
| 	serializedTruncatedFCMMessage, _ := json.Marshal(truncatedFCMMessage) | ||||
| 	require.Equal(t, fcmMessageLimitReal, len(serializedTruncatedFCMMessage)) | ||||
| 	require.NotEqual(t, origMessageLength, truncatedMessageLength) | ||||
| } | ||||
| 
 | ||||
| func newTestConfig(t *testing.T) *Config { | ||||
| 	conf := NewConfig() | ||||
| 	conf.CacheFile = filepath.Join(t.TempDir(), "cache.db") | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue