fix golint error.

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
Bo-Yi Wu 2016-04-13 14:59:28 +08:00
parent 299714f777
commit d87aed23de
12 changed files with 159 additions and 115 deletions

View File

@ -34,5 +34,8 @@ endif
docker tag -f $(PRODUCTION_IMAGE):latest $(DEPLOY_ACCOUNT)/$(PRODUCTION_IMAGE):$(tag) docker tag -f $(PRODUCTION_IMAGE):latest $(DEPLOY_ACCOUNT)/$(PRODUCTION_IMAGE):$(tag)
docker push $(DEPLOY_ACCOUNT)/$(PRODUCTION_IMAGE):$(tag) docker push $(DEPLOY_ACCOUNT)/$(PRODUCTION_IMAGE):$(tag)
lint:
golint gopush
clean: clean:
-rm -rf build.tar.gz gopush.tar.gz bin/* -rm -rf build.tar.gz gopush.tar.gz bin/*

30
doc.go Normal file
View File

@ -0,0 +1,30 @@
// A push notification server using Gin framework written in Go (Golang).
//
// Details about the gopush project are found in github page:
//
// https://github.com/appleboy/gopush
//
// Support Google Cloud Message using go-gcm library for Android.
// Support HTTP/2 Apple Push Notification Service using apns2 library.
// Support YAML configuration.
// Support command line to send single Android or iOS notification.
// Support Web API to send push notification.
// Support zero downtime restarts for go servers using endless.
// Support HTTP/2 or HTTP/1.1 protocol.
//
// The pre-compiled binaries can be downloaded from release page.
//
// Send Android notification
//
// $ gopush -android -m="your message" -k="API Key" -t="Device token"
//
// Send iOS notification
//
// $ gopush -ios -m="your message" -i="API Key" -t="Device token"
//
// The default endpoint is APNs development. Please add -production flag for APNs production push endpoint.
//
// $ gopush -ios -m="your message" -i="API Key" -t="Device token" -production
//
// For more details, see the documentation and example.
//

View File

@ -1,33 +1,3 @@
// A push notification server using Gin framework written in Go (Golang).
//
// Details about the gopush project are found in github page:
//
// https://github.com/appleboy/gopush
//
// Support Google Cloud Message using go-gcm library for Android.
// Support HTTP/2 Apple Push Notification Service using apns2 library.
// Support YAML configuration.
// Support command line to send single Android or iOS notification.
// Support Web API to send push notification.
// Support zero downtime restarts for go servers using endless.
// Support HTTP/2 or HTTP/1.1 protocol.
//
// The pre-compiled binaries can be downloaded from release page.
//
// Send Android notification
//
// $ gopush -android -m="your message" -k="API Key" -t="Device token"
//
// Send iOS notification
//
// $ gopush -ios -m="your message" -i="API Key" -t="Device token"
//
// The default endpoint is APNs development. Please add -production flag for APNs production push endpoint.
//
// $ gopush -ios -m="your message" -i="API Key" -t="Device token" -production
//
// For more details, see the documentation and example.
//
package main package main
import ( import (
@ -76,7 +46,7 @@ func main() {
} }
if *apiKey != "" { if *apiKey != "" {
gopush.PushConf.Android.ApiKey = *apiKey gopush.PushConf.Android.APIKey = *apiKey
} }
// overwrite server port // overwrite server port

View File

@ -5,14 +5,16 @@ import (
"io/ioutil" "io/ioutil"
) )
// ConfYaml is config structure.
type ConfYaml struct { type ConfYaml struct {
Core SectionCore `yaml:"core"` Core SectionCore `yaml:"core"`
Api SectionApi `yaml:"api"` API SectionAPI `yaml:"api"`
Android SectionAndroid `yaml:"android"` Android SectionAndroid `yaml:"android"`
Ios SectionIos `yaml:"ios"` Ios SectionIos `yaml:"ios"`
Log SectionLog `yaml:"log"` Log SectionLog `yaml:"log"`
} }
// SectionCore is sub seciont of config.
type SectionCore struct { type SectionCore struct {
Port string `yaml:"port"` Port string `yaml:"port"`
MaxNotification int `yaml:"max_notification"` MaxNotification int `yaml:"max_notification"`
@ -22,16 +24,19 @@ type SectionCore struct {
KeyPath string `yaml:"key_path"` KeyPath string `yaml:"key_path"`
} }
type SectionApi struct { // SectionAPI is sub seciont of config.
PushUri string `yaml:"push_uri"` type SectionAPI struct {
StatGoUri string `yaml:"stat_go_uri"` PushURI string `yaml:"push_uri"`
StatGoURI string `yaml:"stat_go_uri"`
} }
// SectionAndroid is sub seciont of config.
type SectionAndroid struct { type SectionAndroid struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`
ApiKey string `yaml:"apikey"` APIKey string `yaml:"apikey"`
} }
// SectionIos is sub seciont of config.
type SectionIos struct { type SectionIos struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`
PemCertPath string `yaml:"pem_cert_path"` PemCertPath string `yaml:"pem_cert_path"`
@ -39,6 +44,7 @@ type SectionIos struct {
Production bool `yaml:"production"` Production bool `yaml:"production"`
} }
// SectionLog is sub seciont of config.
type SectionLog struct { type SectionLog struct {
Format string `yaml:"format"` Format string `yaml:"format"`
AccessLog string `yaml:"access_log"` AccessLog string `yaml:"access_log"`
@ -47,6 +53,7 @@ type SectionLog struct {
ErrorLevel string `yaml:"error_level"` ErrorLevel string `yaml:"error_level"`
} }
// BuildDefaultPushConf is default config setting.
func BuildDefaultPushConf() ConfYaml { func BuildDefaultPushConf() ConfYaml {
var conf ConfYaml var conf ConfYaml
@ -59,12 +66,12 @@ func BuildDefaultPushConf() ConfYaml {
conf.Core.MaxNotification = 100 conf.Core.MaxNotification = 100
// Api // Api
conf.Api.PushUri = "/api/push" conf.API.PushURI = "/api/push"
conf.Api.StatGoUri = "/api/status" conf.API.StatGoURI = "/api/status"
// Android // Android
conf.Android.Enabled = false conf.Android.Enabled = false
conf.Android.ApiKey = "" conf.Android.APIKey = ""
// iOS // iOS
conf.Ios.Enabled = false conf.Ios.Enabled = false
@ -82,6 +89,7 @@ func BuildDefaultPushConf() ConfYaml {
return conf return conf
} }
// LoadConfYaml provide load yml config.
func LoadConfYaml(confPath string) (ConfYaml, error) { func LoadConfYaml(confPath string) (ConfYaml, error) {
var config ConfYaml var config ConfYaml

View File

@ -1,15 +1,20 @@
package gopush package gopush
const ( const (
// Version is gorush server version.
Version = "1.0.0" Version = "1.0.0"
) )
const ( const (
// PlatFormIos constant is 1 for iOS
PlatFormIos = iota + 1 PlatFormIos = iota + 1
// PlatFormAndroid constant is 2 for Android
PlatFormAndroid PlatFormAndroid
) )
const ( const (
StatusSucceededPush = "succeeded-push" // SucceededPush is log block
StatusFailedPush = "failed-push" SucceededPush = "succeeded-push"
// FailedPush is log block
FailedPush = "failed-push"
) )

View File

@ -7,9 +7,14 @@ import (
) )
var ( var (
PushConf ConfYaml // PushConf is gorush config
PushConf ConfYaml
// CertificatePemIos is ios certificate file
CertificatePemIos tls.Certificate CertificatePemIos tls.Certificate
ApnsClient *apns.Client // ApnsClient is apns client
LogAccess *logrus.Logger ApnsClient *apns.Client
LogError *logrus.Logger // LogAccess is log server request log
LogAccess *logrus.Logger
// LogError is log server error log
LogError *logrus.Logger
) )

View File

@ -21,6 +21,7 @@ var (
reset = string([]byte{27, 91, 48, 109}) reset = string([]byte{27, 91, 48, 109})
) )
// LogReq is http request log
type LogReq struct { type LogReq struct {
URI string `json:"uri"` URI string `json:"uri"`
Method string `json:"method"` Method string `json:"method"`
@ -29,6 +30,7 @@ type LogReq struct {
Agent string `json:"agent"` Agent string `json:"agent"`
} }
// LogPushEntry is push response log
type LogPushEntry struct { type LogPushEntry struct {
Type string `json:"type"` Type string `json:"type"`
Platform string `json:"platform"` Platform string `json:"platform"`
@ -52,6 +54,7 @@ type LogPushEntry struct {
Category string `json:"category,omitempty"` Category string `json:"category,omitempty"`
} }
// InitLog use for initial log module
func InitLog() error { func InitLog() error {
var err error var err error
@ -92,6 +95,7 @@ func InitLog() error {
return nil return nil
} }
// SetLogOut provide log stdout and stderr output
func SetLogOut(log *logrus.Logger, outString string) error { func SetLogOut(log *logrus.Logger, outString string) error {
switch outString { switch outString {
case "stdout": case "stdout":
@ -111,6 +115,8 @@ func SetLogOut(log *logrus.Logger, outString string) error {
return nil return nil
} }
// SetLogLevel is define log level what you want
// log level: panic, fatal, error, warn, info and debug
func SetLogLevel(log *logrus.Logger, levelString string) error { func SetLogLevel(log *logrus.Logger, levelString string) error {
level, err := logrus.ParseLevel(levelString) level, err := logrus.ParseLevel(levelString)
@ -123,6 +129,7 @@ func SetLogLevel(log *logrus.Logger, levelString string) error {
return nil return nil
} }
// LogRequest record http request
func LogRequest(uri string, method string, ip string, contentType string, agent string) { func LogRequest(uri string, method string, ip string, contentType string, agent string) {
var output string var output string
log := &LogReq{ log := &LogReq{
@ -134,9 +141,9 @@ func LogRequest(uri string, method string, ip string, contentType string, agent
} }
if PushConf.Log.Format == "json" { if PushConf.Log.Format == "json" {
logJson, _ := json.Marshal(log) logJSON, _ := json.Marshal(log)
output = string(logJson) output = string(logJSON)
} else { } else {
// format is string // format is string
output = fmt.Sprintf("|%s header %s| %s %s %s %s %s", output = fmt.Sprintf("|%s header %s| %s %s %s %s %s",
@ -174,6 +181,7 @@ func typeForPlatForm(platform int) string {
} }
} }
// LogPush record user push request and server response.
func LogPush(status, token string, req PushNotification, errPush error) { func LogPush(status, token string, req PushNotification, errPush error) {
var plat, platColor, output string var plat, platColor, output string
@ -194,19 +202,19 @@ func LogPush(status, token string, req PushNotification, errPush error) {
} }
if PushConf.Log.Format == "json" { if PushConf.Log.Format == "json" {
logJson, _ := json.Marshal(log) logJSON, _ := json.Marshal(log)
output = string(logJson) output = string(logJSON)
} else { } else {
switch status { switch status {
case StatusSucceededPush: case SucceededPush:
output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] %s", output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] %s",
green, log.Type, reset, green, log.Type, reset,
platColor, log.Platform, reset, platColor, log.Platform, reset,
log.Token, log.Token,
log.Message, log.Message,
) )
case StatusFailedPush: case FailedPush:
output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] | %s | Error Message: %s", output = fmt.Sprintf("|%s %s %s| %s%s%s [%s] | %s | Error Message: %s",
red, log.Type, reset, red, log.Type, reset,
platColor, log.Platform, reset, platColor, log.Platform, reset,
@ -218,13 +226,14 @@ func LogPush(status, token string, req PushNotification, errPush error) {
} }
switch status { switch status {
case StatusSucceededPush: case SucceededPush:
LogAccess.Info(string(output)) LogAccess.Info(string(output))
case StatusFailedPush: case FailedPush:
LogError.Error(string(output)) LogError.Error(string(output))
} }
} }
// LogMiddleware provide gin router handler.
func LogMiddleware() gin.HandlerFunc { func LogMiddleware() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
LogRequest(c.Request.URL.Path, c.Request.Method, c.ClientIP(), c.ContentType(), c.Request.Header.Get("User-Agent")) LogRequest(c.Request.URL.Path, c.Request.Method, c.ClientIP(), c.ContentType(), c.Request.Header.Get("User-Agent"))

View File

@ -10,22 +10,24 @@ import (
"time" "time"
) )
// D provide string array
type D map[string]interface{} type D map[string]interface{}
const ( const (
// PriorityLow will tell APNs to send the push message at a time that takes // ApnsPriorityLow will tell APNs to send the push message at a time that takes
// into account power considerations for the device. Notifications with this // into account power considerations for the device. Notifications with this
// priority might be grouped and delivered in bursts. They are throttled, and // priority might be grouped and delivered in bursts. They are throttled, and
// in some cases are not delivered. // in some cases are not delivered.
ApnsPriorityLow = 5 ApnsPriorityLow = 5
// PriorityHigh will tell APNs to send the push message immediately. // ApnsPriorityHigh will tell APNs to send the push message immediately.
// Notifications with this priority must trigger an alert, sound, or badge on // Notifications with this priority must trigger an alert, sound, or badge on
// the target device. It is an error to use this priority for a push // the target device. It is an error to use this priority for a push
// notification that contains only the content-available key. // notification that contains only the content-available key.
ApnsPriorityHigh = 10 ApnsPriorityHigh = 10
) )
// Alert is APNs payload
type Alert struct { type Alert struct {
Action string `json:"action,omitempty"` Action string `json:"action,omitempty"`
ActionLocKey string `json:"action-loc-key,omitempty"` ActionLocKey string `json:"action-loc-key,omitempty"`
@ -38,10 +40,12 @@ type Alert struct {
TitleLocKey string `json:"title-loc-key,omitempty"` TitleLocKey string `json:"title-loc-key,omitempty"`
} }
// RequestPush support multiple notification request.
type RequestPush struct { type RequestPush struct {
Notifications []PushNotification `json:"notifications" binding:"required"` Notifications []PushNotification `json:"notifications" binding:"required"`
} }
// PushNotification is single notification request
type PushNotification struct { type PushNotification struct {
// Common // Common
Tokens []string `json:"tokens" binding:"required"` Tokens []string `json:"tokens" binding:"required"`
@ -54,7 +58,7 @@ type PushNotification struct {
Data D `json:"data,omitempty"` Data D `json:"data,omitempty"`
// Android // Android
ApiKey string `json:"api_key,omitempty"` APIKey string `json:"api_key,omitempty"`
To string `json:"to,omitempty"` To string `json:"to,omitempty"`
CollapseKey string `json:"collapse_key,omitempty"` CollapseKey string `json:"collapse_key,omitempty"`
DelayWhileIdle bool `json:"delay_while_idle,omitempty"` DelayWhileIdle bool `json:"delay_while_idle,omitempty"`
@ -73,9 +77,10 @@ type PushNotification struct {
Alert Alert `json:"alert,omitempty"` Alert Alert `json:"alert,omitempty"`
} }
// CheckPushConf provide check your yml config.
func CheckPushConf() error { func CheckPushConf() error {
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled { if !PushConf.Ios.Enabled && !PushConf.Android.Enabled {
return errors.New("Please enable iOS or Android config in yaml config") return errors.New("Please enable iOS or Android config in yml config")
} }
if PushConf.Ios.Enabled { if PushConf.Ios.Enabled {
@ -85,7 +90,7 @@ func CheckPushConf() error {
} }
if PushConf.Android.Enabled { if PushConf.Android.Enabled {
if PushConf.Android.ApiKey == "" { if PushConf.Android.APIKey == "" {
return errors.New("Missing Android API Key") return errors.New("Missing Android API Key")
} }
} }
@ -93,6 +98,7 @@ func CheckPushConf() error {
return nil return nil
} }
// InitAPNSClient use for initialize APNs Client.
func InitAPNSClient() error { func InitAPNSClient() error {
if PushConf.Ios.Enabled { if PushConf.Ios.Enabled {
var err error var err error
@ -115,6 +121,7 @@ func InitAPNSClient() error {
return nil return nil
} }
// SendNotification provide send all push request.
func SendNotification(req RequestPush) int { func SendNotification(req RequestPush) int {
var count int var count int
for _, notification := range req.Notifications { for _, notification := range req.Notifications {
@ -124,14 +131,14 @@ func SendNotification(req RequestPush) int {
continue continue
} }
count += 1 count++
go PushToIOS(notification) go PushToIOS(notification)
case PlatFormAndroid: case PlatFormAndroid:
if !PushConf.Android.Enabled { if !PushConf.Android.Enabled {
continue continue
} }
count += 1 count++
go PushToAndroid(notification) go PushToAndroid(notification)
} }
} }
@ -139,6 +146,7 @@ func SendNotification(req RequestPush) int {
return count return count
} }
// GetIOSNotification use for define iOS notificaiton.
// The iOS Notification Payload // The iOS Notification Payload
// ref: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html // ref: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html
func GetIOSNotification(req PushNotification) *apns.Notification { func GetIOSNotification(req PushNotification) *apns.Notification {
@ -233,6 +241,7 @@ func GetIOSNotification(req PushNotification) *apns.Notification {
return notification return notification
} }
// PushToIOS provide send notification to APNs server.
func PushToIOS(req PushNotification) bool { func PushToIOS(req PushNotification) bool {
notification := GetIOSNotification(req) notification := GetIOSNotification(req)
@ -245,7 +254,7 @@ func PushToIOS(req PushNotification) bool {
if err != nil { if err != nil {
// apns server error // apns server error
LogPush(StatusFailedPush, token, req, err) LogPush(FailedPush, token, req, err)
return false return false
} }
@ -253,19 +262,20 @@ func PushToIOS(req PushNotification) bool {
if res.StatusCode != 200 { if res.StatusCode != 200 {
// error message: // error message:
// ref: https://github.com/sideshow/apns2/blob/master/response.go#L14-L65 // ref: https://github.com/sideshow/apns2/blob/master/response.go#L14-L65
LogPush(StatusFailedPush, token, req, errors.New(res.Reason)) LogPush(FailedPush, token, req, errors.New(res.Reason))
return false return false
} }
if res.Sent() { if res.Sent() {
LogPush(StatusSucceededPush, token, req, nil) LogPush(SucceededPush, token, req, nil)
} }
} }
return true return true
} }
// GetAndroidNotification use for define Android notificaiton.
// HTTP Connection Server Reference for Android // HTTP Connection Server Reference for Android
// https://developers.google.com/cloud-messaging/http-server-ref // https://developers.google.com/cloud-messaging/http-server-ref
func GetAndroidNotification(req PushNotification) gcm.HttpMessage { func GetAndroidNotification(req PushNotification) gcm.HttpMessage {
@ -331,16 +341,17 @@ func GetAndroidNotification(req PushNotification) gcm.HttpMessage {
return notification return notification
} }
// PushToAndroid provide send notification to Android server.
func PushToAndroid(req PushNotification) bool { func PushToAndroid(req PushNotification) bool {
var apiKey string var APIKey string
notification := GetAndroidNotification(req) notification := GetAndroidNotification(req)
if apiKey = PushConf.Android.ApiKey; req.ApiKey != "" { if APIKey = PushConf.Android.APIKey; req.APIKey != "" {
apiKey = req.ApiKey APIKey = req.APIKey
} }
res, err := gcm.SendHttp(apiKey, notification) res, err := gcm.SendHttp(APIKey, notification)
if err != nil { if err != nil {
// GCM server error // GCM server error
@ -353,11 +364,11 @@ func PushToAndroid(req PushNotification) bool {
for k, result := range res.Results { for k, result := range res.Results {
if result.Error != "" { if result.Error != "" {
LogPush(StatusFailedPush, req.Tokens[k], req, errors.New(result.Error)) LogPush(FailedPush, req.Tokens[k], req, errors.New(result.Error))
continue continue
} }
LogPush(StatusSucceededPush, req.Tokens[k], req, nil) LogPush(SucceededPush, req.Tokens[k], req, nil)
} }
return true return true

View File

@ -18,7 +18,7 @@ func TestDisabledAndroidIosConf(t *testing.T) {
err := CheckPushConf() err := CheckPushConf()
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "Please enable iOS or Android config in yaml config", err.Error()) assert.Equal(t, "Please enable iOS or Android config in yml config", err.Error())
} }
func TestMissingIOSCertificate(t *testing.T) { func TestMissingIOSCertificate(t *testing.T) {
@ -37,7 +37,7 @@ func TestMissingAndroidAPIKey(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = "" PushConf.Android.APIKey = ""
err := CheckPushConf() err := CheckPushConf()
@ -49,7 +49,7 @@ func TestCorrectConf(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = "xxxxx" PushConf.Android.APIKey = "xxxxx"
PushConf.Ios.Enabled = true PushConf.Ios.Enabled = true
PushConf.Ios.PemKeyPath = "xxxxx" PushConf.Ios.PemKeyPath = "xxxxx"
@ -237,7 +237,7 @@ func TestPushToAndroidWrongAPIKey(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") + "a" PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY") + "a"
req := PushNotification{ req := PushNotification{
Tokens: []string{"aaaaaa", "bbbbb"}, Tokens: []string{"aaaaaa", "bbbbb"},
@ -253,7 +253,7 @@ func TestPushToAndroidWrongToken(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
req := PushNotification{ req := PushNotification{
Tokens: []string{"aaaaaa", "bbbbb"}, Tokens: []string{"aaaaaa", "bbbbb"},
@ -269,14 +269,14 @@ func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
// log for json // log for json
PushConf.Log.Format = "json" PushConf.Log.Format = "json"
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := PushNotification{ req := PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
} }
@ -289,12 +289,12 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := PushNotification{ req := PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
} }
@ -303,20 +303,20 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
assert.True(t, success) assert.True(t, success)
} }
func TestOverwriteAndroidApiKey(t *testing.T) { func TestOverwriteAndroidAPIKey(t *testing.T) {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := PushNotification{ req := PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
// overwrite android api key // overwrite android api key
ApiKey: "1234", APIKey: "1234",
} }
success := PushToAndroid(req) success := PushToAndroid(req)
@ -331,9 +331,9 @@ func TestSenMultipleNotifications(t *testing.T) {
InitAPNSClient() InitAPNSClient()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{ req := RequestPush{
Notifications: []PushNotification{ Notifications: []PushNotification{
@ -345,7 +345,7 @@ func TestSenMultipleNotifications(t *testing.T) {
}, },
// android // android
PushNotification{ PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
}, },
@ -364,9 +364,9 @@ func TestDisabledAndroidNotifications(t *testing.T) {
InitAPNSClient() InitAPNSClient()
PushConf.Android.Enabled = false PushConf.Android.Enabled = false
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{ req := RequestPush{
Notifications: []PushNotification{ Notifications: []PushNotification{
@ -378,7 +378,7 @@ func TestDisabledAndroidNotifications(t *testing.T) {
}, },
// android // android
PushNotification{ PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
}, },
@ -397,9 +397,9 @@ func TestDisabledIosNotifications(t *testing.T) {
InitAPNSClient() InitAPNSClient()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
req := RequestPush{ req := RequestPush{
Notifications: []PushNotification{ Notifications: []PushNotification{
@ -411,7 +411,7 @@ func TestDisabledIosNotifications(t *testing.T) {
}, },
// android // android
PushNotification{ PushNotification{
Tokens: []string{android_token, "bbbbb"}, Tokens: []string{androidToken, "bbbbb"},
Platform: 2, Platform: 2,
Message: "Welcome", Message: "Welcome",
}, },

View File

@ -8,7 +8,7 @@ import (
"net/http" "net/http"
) )
func AbortWithError(c *gin.Context, code int, message string) { func abortWithError(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{ c.JSON(code, gin.H{
"code": code, "code": code,
"message": message, "message": message,
@ -29,21 +29,21 @@ func pushHandler(c *gin.Context) {
if err := c.BindJSON(&form); err != nil { if err := c.BindJSON(&form); err != nil {
msg = "Missing notifications field." msg = "Missing notifications field."
LogAccess.Debug(msg) LogAccess.Debug(msg)
AbortWithError(c, http.StatusBadRequest, msg) abortWithError(c, http.StatusBadRequest, msg)
return return
} }
if len(form.Notifications) == 0 { if len(form.Notifications) == 0 {
msg = "Notifications field is empty." msg = "Notifications field is empty."
LogAccess.Debug(msg) LogAccess.Debug(msg)
AbortWithError(c, http.StatusBadRequest, msg) abortWithError(c, http.StatusBadRequest, msg)
return return
} }
if len(form.Notifications) > PushConf.Core.MaxNotification { if len(form.Notifications) > PushConf.Core.MaxNotification {
msg = fmt.Sprintf("Number of notifications(%d) over limit(%d)", len(form.Notifications), PushConf.Core.MaxNotification) msg = fmt.Sprintf("Number of notifications(%d) over limit(%d)", len(form.Notifications), PushConf.Core.MaxNotification)
LogAccess.Debug(msg) LogAccess.Debug(msg)
AbortWithError(c, http.StatusBadRequest, msg) abortWithError(c, http.StatusBadRequest, msg)
return return
} }
@ -55,7 +55,7 @@ func pushHandler(c *gin.Context) {
}) })
} }
func GetMainEngine() *gin.Engine { func routerEngine() *gin.Engine {
// set server mode // set server mode
gin.SetMode(PushConf.Core.Mode) gin.SetMode(PushConf.Core.Mode)
@ -67,19 +67,20 @@ func GetMainEngine() *gin.Engine {
r.Use(VersionMiddleware()) r.Use(VersionMiddleware())
r.Use(LogMiddleware()) r.Use(LogMiddleware())
r.GET(PushConf.Api.StatGoUri, api.StatusHandler) r.GET(PushConf.API.StatGoURI, api.StatusHandler)
r.POST(PushConf.Api.PushUri, pushHandler) r.POST(PushConf.API.PushURI, pushHandler)
r.GET("/", rootHandler) r.GET("/", rootHandler)
return r return r
} }
// RunHTTPServer provide run http or https protocol.
func RunHTTPServer() error { func RunHTTPServer() error {
var err error var err error
if PushConf.Core.SSL && PushConf.Core.CertPath != "" && PushConf.Core.KeyPath != "" { if PushConf.Core.SSL && PushConf.Core.CertPath != "" && PushConf.Core.KeyPath != "" {
err = endless.ListenAndServeTLS(":"+PushConf.Core.Port, PushConf.Core.CertPath, PushConf.Core.KeyPath, GetMainEngine()) err = endless.ListenAndServeTLS(":"+PushConf.Core.Port, PushConf.Core.CertPath, PushConf.Core.KeyPath, routerEngine())
} else { } else {
err = endless.ListenAndServe(":"+PushConf.Core.Port, GetMainEngine()) err = endless.ListenAndServe(":"+PushConf.Core.Port, routerEngine())
} }
return err return err

View File

@ -12,7 +12,7 @@ import (
"time" "time"
) )
var go_version = runtime.Version() var goVersion = runtime.Version()
func initTest() { func initTest() {
PushConf = BuildDefaultPushConf() PushConf = BuildDefaultPushConf()
@ -66,7 +66,7 @@ func TestRootHandler(t *testing.T) {
PushConf.Log.Format = "json" PushConf.Log.Format = "json"
r.GET("/"). r.GET("/").
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
data := []byte(r.Body.String()) data := []byte(r.Body.String())
value, _ := jsonparser.GetString(data, "text") value, _ := jsonparser.GetString(data, "text")
@ -82,12 +82,12 @@ func TestAPIStatusHandler(t *testing.T) {
r := gofight.New() r := gofight.New()
r.GET("/api/status"). r.GET("/api/status").
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
data := []byte(r.Body.String()) data := []byte(r.Body.String())
value, _ := jsonparser.GetString(data, "go_version") value, _ := jsonparser.GetString(data, "goVersion")
assert.Equal(t, go_version, value) assert.Equal(t, goVersion, value)
assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, http.StatusOK, r.Code)
}) })
} }
@ -99,7 +99,7 @@ func TestMissingNotificationsParameter(t *testing.T) {
// missing notifications parameter. // missing notifications parameter.
r.POST("/api/push"). r.POST("/api/push").
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusBadRequest, r.Code) assert.Equal(t, http.StatusBadRequest, r.Code)
}) })
@ -115,7 +115,7 @@ func TestEmptyNotifications(t *testing.T) {
SetJSON(gofight.D{ SetJSON(gofight.D{
"notifications": []PushNotification{}, "notifications": []PushNotification{},
}). }).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusBadRequest, r.Code) assert.Equal(t, http.StatusBadRequest, r.Code)
}) })
@ -144,7 +144,7 @@ func TestOutOfRangeMaxNotifications(t *testing.T) {
}, },
}, },
}). }).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusBadRequest, r.Code) assert.Equal(t, http.StatusBadRequest, r.Code)
}) })
@ -154,9 +154,9 @@ func TestSuccessPushHandler(t *testing.T) {
initTest() initTest()
PushConf.Android.Enabled = true PushConf.Android.Enabled = true
PushConf.Android.ApiKey = os.Getenv("ANDROID_API_KEY") PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
android_token := os.Getenv("ANDROID_TEST_TOKEN") androidToken := os.Getenv("ANDROID_TEST_TOKEN")
r := gofight.New() r := gofight.New()
@ -164,13 +164,13 @@ func TestSuccessPushHandler(t *testing.T) {
SetJSON(gofight.D{ SetJSON(gofight.D{
"notifications": []gofight.D{ "notifications": []gofight.D{
gofight.D{ gofight.D{
"tokens": []string{android_token, "bbbbb"}, "tokens": []string{androidToken, "bbbbb"},
"platform": 2, "platform": 2,
"message": "Welcome", "message": "Welcome",
}, },
}, },
}). }).
Run(GetMainEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { Run(routerEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, http.StatusOK, r.Code)
}) })

View File

@ -6,6 +6,7 @@ import (
"runtime" "runtime"
) )
// PrintGoPushVersion provide print server engine
func PrintGoPushVersion() { func PrintGoPushVersion() {
fmt.Printf(`GoPush %s, Compiler: %s %s, Copyright (C) 2016 Bo-Yi Wu, Inc.`, fmt.Printf(`GoPush %s, Compiler: %s %s, Copyright (C) 2016 Bo-Yi Wu, Inc.`,
Version, Version,
@ -13,6 +14,7 @@ func PrintGoPushVersion() {
runtime.Version()) runtime.Version())
} }
// VersionMiddleware : add version on header.
func VersionMiddleware() gin.HandlerFunc { func VersionMiddleware() gin.HandlerFunc {
// Set out header value for each response // Set out header value for each response
return func(c *gin.Context) { return func(c *gin.Context) {