Merge pull request #36 from appleboy/multiple

Fix #35 support multiple notifications.
This commit is contained in:
Bo-Yi Wu 2016-04-09 23:15:53 -05:00
commit 91099ff74e
6 changed files with 204 additions and 151 deletions

View File

@ -17,5 +17,8 @@ docker_build: clean
tar -zxvf bin.tar.gz
-rm -rf bin.tar.gz build.tar.gz
test:
cd gopush && go test -v -covermode=count -coverprofile=coverage.out
clean:
rm -rf build.tar.gz bin.tar.gz bin/*

View File

@ -174,7 +174,7 @@ func typeForPlatForm(platform int) string {
}
}
func LogPush(status, token string, req RequestPushNotification, errPush error) {
func LogPush(status, token string, req PushNotification, errPush error) {
var plat, platColor, output string
platColor = colorForPlatForm(req.Platform)

View File

@ -41,7 +41,11 @@ type Alert struct {
TitleLocKey string `json:"title-loc-key,omitempty"`
}
type RequestPushNotification struct {
type RequestPush struct {
Notifications []PushNotification `json:"notifications" binding:"required"`
}
type PushNotification struct {
// Common
Tokens []string `json:"tokens" binding:"required"`
Platform int `json:"platform" binding:"required"`
@ -114,26 +118,33 @@ func InitAPNSClient() error {
return nil
}
func pushNotification(notification RequestPushNotification) bool {
switch notification.Platform {
case PlatFormIos:
if !PushConf.Ios.Enabled {
return false
func SendNotification(req RequestPush) int {
var count int
for _, notification := range req.Notifications {
switch notification.Platform {
case PlatFormIos:
if !PushConf.Ios.Enabled {
continue
}
count += 1
go PushToIOS(notification)
case PlatFormAndroid:
if !PushConf.Android.Enabled {
continue
}
count += 1
go PushToAndroid(notification)
}
go PushToIOS(notification)
case PlatFormAndroid:
if !PushConf.Android.Enabled {
return false
}
go PushToAndroid(notification)
}
return true
return count
}
// The iOS Notification Payload
// ref: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html
func GetIOSNotification(req RequestPushNotification) *apns.Notification {
func GetIOSNotification(req PushNotification) *apns.Notification {
notification := &apns.Notification{}
if len(req.ApnsID) > 0 {
@ -225,7 +236,7 @@ func GetIOSNotification(req RequestPushNotification) *apns.Notification {
return notification
}
func PushToIOS(req RequestPushNotification) bool {
func PushToIOS(req PushNotification) bool {
notification := GetIOSNotification(req)
@ -260,7 +271,7 @@ func PushToIOS(req RequestPushNotification) bool {
// HTTP Connection Server Reference for Android
// https://developers.google.com/cloud-messaging/http-server-ref
func GetAndroidNotification(req RequestPushNotification) gcm.HttpMessage {
func GetAndroidNotification(req PushNotification) gcm.HttpMessage {
notification := gcm.HttpMessage{}
notification.RegistrationIds = req.Tokens
@ -311,7 +322,7 @@ func GetAndroidNotification(req RequestPushNotification) gcm.HttpMessage {
return notification
}
func PushToAndroid(req RequestPushNotification) bool {
func PushToAndroid(req PushNotification) bool {
var apiKey string
notification := GetAndroidNotification(req)

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/buger/jsonparser"
"github.com/google/go-gcm"
"github.com/sideshow/apns2"
"github.com/stretchr/testify/assert"
"log"
"os"
@ -64,7 +65,7 @@ func TestIOSNotificationStructure(t *testing.T) {
test := "test"
message := "Welcome notification Server"
req := RequestPushNotification{
req := PushNotification{
ApnsID: test,
Topic: test,
Expiration: time.Now().Unix(),
@ -126,7 +127,7 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
var dat map[string]interface{}
test := "test"
req := RequestPushNotification{
req := PushNotification{
Alert: Alert{
Action: test,
ActionLocKey: test,
@ -178,7 +179,7 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
func TestAndroidNotificationStructure(t *testing.T) {
test := "test"
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{"a", "b"},
Message: "Welcome",
To: test,
@ -219,7 +220,7 @@ func TestPushToIOS(t *testing.T) {
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
Platform: 1,
Message: "Welcome",
@ -235,7 +236,7 @@ func TestPushToAndroidWrongAPIKey(t *testing.T) {
PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") + "a"
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{"aaaaaa", "bbbbb"},
Platform: 2,
Message: "Welcome",
@ -251,7 +252,7 @@ func TestPushToAndroidWrongToken(t *testing.T) {
PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY")
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{"aaaaaa", "bbbbb"},
Platform: 2,
Message: "Welcome",
@ -271,7 +272,7 @@ func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
@ -289,7 +290,7 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
@ -307,7 +308,7 @@ func TestOverwriteAndroidApiKey(t *testing.T) {
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPushNotification{
req := PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
@ -318,3 +319,133 @@ func TestOverwriteAndroidApiKey(t *testing.T) {
success := PushToAndroid(req)
assert.False(t, success)
}
func TestSenMultipleNotifications(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{
Notifications: []PushNotification{
//ios
PushNotification{
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
Platform: 1,
Message: "Welcome",
},
// android
PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
},
},
}
count := SendNotification(req)
assert.Equal(t, 2, count)
}
func TestDisabledAndroidNotifications(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
PushConf.Android.Enabled = false
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{
Notifications: []PushNotification{
//ios
PushNotification{
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
Platform: 1,
Message: "Welcome",
},
// android
PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
},
},
}
count := SendNotification(req)
assert.Equal(t, 1, count)
}
func TestDisabledIosNotifications(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = false
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{
Notifications: []PushNotification{
//ios
PushNotification{
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
Platform: 1,
Message: "Welcome",
},
// android
PushNotification{
Tokens: []string{android_token, "bbbbb"},
Platform: 2,
Message: "Welcome",
},
},
}
count := SendNotification(req)
assert.Equal(t, 1, count)
}
func TestMissingIosCertificate(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "test"
err := InitAPNSClient()
assert.Error(t, err)
}
func TestAPNSClientDevHost(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
}
func TestAPNSClientProdHost(t *testing.T) {
PushConf = BuildDefaultPushConf()
PushConf.Ios.Enabled = true
PushConf.Ios.Production = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
}

View File

@ -21,15 +21,20 @@ func rootHandler(c *gin.Context) {
}
func pushHandler(c *gin.Context) {
var form RequestPushNotification
var form RequestPush
if err := c.BindJSON(&form); err != nil {
AbortWithError(c, http.StatusBadRequest, "Bad input request, please refer to README guide.")
AbortWithError(c, http.StatusBadRequest, "Missing nitifications field.")
return
}
if len(form.Notifications) == 0 {
AbortWithError(c, http.StatusBadRequest, "Notification field is empty.")
return
}
// process notification.
pushNotification(form)
go SendNotification(form)
c.JSON(http.StatusOK, gin.H{
"text": "Welcome to notification server.",

View File

@ -92,15 +92,28 @@ func TestAPIStatusHandler(t *testing.T) {
})
}
func TestMissingParameterPushHandler(t *testing.T) {
func TestMissingNotificationsParameter(t *testing.T) {
initTest()
r := gofight.New()
// missing some parameter.
// missing notifications parameter.
r.POST("/api/push").
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusBadRequest, r.Code)
})
}
func TestEmptyNotifications(t *testing.T) {
initTest()
r := gofight.New()
// notifications is empty.
r.POST("/api/push").
SetJSON(gofight.D{
"platform": 1,
"notifications": []PushNotification{},
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
@ -108,99 +121,7 @@ func TestMissingParameterPushHandler(t *testing.T) {
})
}
func TestDisabledIosPushHandler(t *testing.T) {
initTest()
PushConf.Ios.Enabled = false
InitAPNSClient()
r := gofight.New()
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
"platform": 1,
"message": "Welcome",
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
func TestMissingIosCertificate(t *testing.T) {
initTest()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "test"
err := InitAPNSClient()
assert.Error(t, err)
}
func TestIosPushDevelopment(t *testing.T) {
initTest()
PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
r := gofight.New()
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
"platform": 1,
"message": "Welcome",
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
func TestIosPushProduction(t *testing.T) {
initTest()
PushConf.Ios.Enabled = true
PushConf.Ios.Production = true
PushConf.Ios.PemKeyPath = "../certificate/certificate-valid.pem"
InitAPNSClient()
r := gofight.New()
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
"platform": 1,
"message": "Welcome",
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
func TestDisabledAndroidPushHandler(t *testing.T) {
initTest()
PushConf.Android.Enabled = false
r := gofight.New()
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{"aaaaaa", "bbbbb"},
"platform": 2,
"message": "Welcome",
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
func TestHalfSuccessAndroidPushHandler(t *testing.T) {
func TestSuccessPushHandler(t *testing.T) {
initTest()
PushConf.Android.Enabled = true
@ -212,31 +133,13 @@ func TestHalfSuccessAndroidPushHandler(t *testing.T) {
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{android_token, "bbbbb"},
"platform": 2,
"message": "Welcome",
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code)
})
}
func TestAllSuccessAndroidPushHandler(t *testing.T) {
initTest()
PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN")
r := gofight.New()
r.POST("/api/push").
SetJSON(gofight.D{
"tokens": []string{android_token, android_token},
"platform": 2,
"message": "Welcome",
"notifications": []gofight.D{
gofight.D{
"tokens": []string{android_token, "bbbbb"},
"platform": 2,
"message": "Welcome",
},
},
}).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {