Skip to content

Commit 11b2485

Browse files
chemidyhiranya911
authored andcommitted
feat(fcm): Added support for sending an image URL with notifications (#261)
* add analytics_label in FcmOptions + fix FcmOptions for WebpushFcmOptions * fix comment * refactor fcm to FCM * add image option in notification * fix merge issue * fix ImageURL and inline error check * fix ImageURL and validattion
1 parent 3df7cc0 commit 11b2485

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

messaging/messaging.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ func (m *Message) UnmarshalJSON(b []byte) error {
187187

188188
// Notification is the basic notification template to use across all platforms.
189189
type Notification struct {
190-
Title string `json:"title,omitempty"`
191-
Body string `json:"body,omitempty"`
190+
Title string `json:"title,omitempty"`
191+
Body string `json:"body,omitempty"`
192+
ImageURL string `json:"image,omitempty"`
192193
}
193194

194195
// AndroidConfig contains messaging options specific to the Android platform.
@@ -274,6 +275,7 @@ type AndroidNotification struct {
274275
TitleLocKey string `json:"title_loc_key,omitempty"`
275276
TitleLocArgs []string `json:"title_loc_args,omitempty"`
276277
ChannelID string `json:"channel_id,omitempty"`
278+
ImageURL string `json:"image,omitempty"`
277279
}
278280

279281
// AndroidFCMOptions contains additional options for features provided by the FCM Android SDK.
@@ -619,6 +621,7 @@ type ApsAlert struct {
619621
// APNSFCMOptions contains additional options for features provided by the FCM Aps SDK.
620622
type APNSFCMOptions struct {
621623
AnalyticsLabel string `json:"analytics_label,omitempty"`
624+
ImageURL string `json:"image,omitempty"`
622625
}
623626

624627
// FCMOptions contains additional options to use across all platforms.

messaging/messaging_test.go

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,17 @@ var validMessages = []struct {
102102
name: "NotificationMessage",
103103
req: &Message{
104104
Notification: &Notification{
105-
Title: "t",
106-
Body: "b",
105+
Title: "t",
106+
Body: "b",
107+
ImageURL: "http://image.jpg",
107108
},
108109
Topic: "test-topic",
109110
},
110111
want: map[string]interface{}{
111112
"notification": map[string]interface{}{
112113
"title": "t",
113114
"body": "b",
115+
"image": "http://image.jpg",
114116
},
115117
"topic": "test-topic",
116118
},
@@ -157,6 +159,7 @@ var validMessages = []struct {
157159
BodyLocKey: "blk",
158160
BodyLocArgs: []string{"b1", "b2"},
159161
ChannelID: "channel",
162+
ImageURL: "http://image.jpg",
160163
},
161164
TTL: &ttlWithNanos,
162165
FCMOptions: &AndroidFCMOptions{
@@ -178,6 +181,7 @@ var validMessages = []struct {
178181
"body_loc_key": "blk",
179182
"body_loc_args": []interface{}{"b1", "b2"},
180183
"channel_id": "channel",
184+
"image": "http://image.jpg",
181185
},
182186
"ttl": "1.500000000s",
183187
"fcm_options": map[string]interface{}{
@@ -322,6 +326,7 @@ var validMessages = []struct {
322326
},
323327
FCMOptions: &APNSFCMOptions{
324328
AnalyticsLabel: "Analytics",
329+
ImageURL: "http://image.jpg",
325330
},
326331
},
327332
Topic: "test-topic",
@@ -344,6 +349,7 @@ var validMessages = []struct {
344349
},
345350
"fcm_options": map[string]interface{}{
346351
"analytics_label": "Analytics",
352+
"image": "http://image.jpg",
347353
},
348354
},
349355
"topic": "test-topic",
@@ -525,6 +531,16 @@ var invalidMessages = []struct {
525531
},
526532
want: "malformed topic name",
527533
},
534+
{
535+
name: "InvalidNotificationImage",
536+
req: &Message{
537+
Notification: &Notification{
538+
ImageURL: "image.jpg",
539+
},
540+
Topic: "topic",
541+
},
542+
want: `invalid image URL: "image.jpg"`,
543+
},
528544
{
529545
name: "InvalidAndroidTTL",
530546
req: &Message{
@@ -593,6 +609,18 @@ var invalidMessages = []struct {
593609
},
594610
want: "bodyLocKey is required when specifying bodyLocArgs",
595611
},
612+
{
613+
name: "InvalidAndroidImage",
614+
req: &Message{
615+
Android: &AndroidConfig{
616+
Notification: &AndroidNotification{
617+
ImageURL: "image.jpg",
618+
},
619+
},
620+
Topic: "topic",
621+
},
622+
want: `invalid image URL: "image.jpg"`,
623+
},
596624
{
597625
name: "APNSMultipleAps",
598626
req: &Message{
@@ -688,6 +716,18 @@ var invalidMessages = []struct {
688716
},
689717
want: "locKey is required when specifying locArgs",
690718
},
719+
{
720+
name: "InvalidAPNSImage",
721+
req: &Message{
722+
APNS: &APNSConfig{
723+
FCMOptions: &APNSFCMOptions{
724+
ImageURL: "image.jpg",
725+
},
726+
},
727+
Topic: "topic",
728+
},
729+
want: `invalid image URL: "image.jpg"`,
730+
},
691731
{
692732
name: "MultipleSoundSpecifications",
693733
req: &Message{

messaging/messaging_utils.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ func validateMessage(message *Message) error {
4444
}
4545
}
4646

47+
// validate Notification
48+
if err := validateNotification(message.Notification); err != nil {
49+
return err
50+
}
51+
4752
// validate AndroidConfig
4853
if err := validateAndroidConfig(message.Android); err != nil {
4954
return err
@@ -58,6 +63,20 @@ func validateMessage(message *Message) error {
5863
return validateAPNSConfig(message.APNS)
5964
}
6065

66+
func validateNotification(notification *Notification) error {
67+
if notification == nil {
68+
return nil
69+
}
70+
71+
image := notification.ImageURL
72+
if image != "" {
73+
if _, err := url.ParseRequestURI(image); err != nil {
74+
return fmt.Errorf("invalid image URL: %q", image)
75+
}
76+
}
77+
return nil
78+
}
79+
6180
func validateAndroidConfig(config *AndroidConfig) error {
6281
if config == nil {
6382
return nil
@@ -69,6 +88,7 @@ func validateAndroidConfig(config *AndroidConfig) error {
6988
if config.Priority != "" && config.Priority != "normal" && config.Priority != "high" {
7089
return fmt.Errorf("priority must be 'normal' or 'high'")
7190
}
91+
7292
// validate AndroidNotification
7393
return validateAndroidNotification(config.Notification)
7494
}
@@ -86,11 +106,26 @@ func validateAndroidNotification(notification *AndroidNotification) error {
86106
if len(notification.BodyLocArgs) > 0 && notification.BodyLocKey == "" {
87107
return fmt.Errorf("bodyLocKey is required when specifying bodyLocArgs")
88108
}
109+
image := notification.ImageURL
110+
if image != "" {
111+
if _, err := url.ParseRequestURI(image); err != nil {
112+
return fmt.Errorf("invalid image URL: %q", image)
113+
}
114+
}
89115
return nil
90116
}
91117

92118
func validateAPNSConfig(config *APNSConfig) error {
93119
if config != nil {
120+
// validate FCMOptions
121+
if config.FCMOptions != nil {
122+
image := config.FCMOptions.ImageURL
123+
if image != "" {
124+
if _, err := url.ParseRequestURI(image); err != nil {
125+
return fmt.Errorf("invalid image URL: %q", image)
126+
}
127+
}
128+
}
94129
return validateAPNSPayload(config.Payload)
95130
}
96131
return nil

0 commit comments

Comments
 (0)