chore: support single queue and multiple worker (#589)
This commit is contained in:
parent
0658f18430
commit
ab8b1991ab
|
@ -243,7 +243,7 @@ type SectionGRPC struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConf load config from file and read in environment variables that match
|
// LoadConf load config from file and read in environment variables that match
|
||||||
func LoadConf(confPath string) (ConfYaml, error) {
|
func LoadConf(confPath ...string) (ConfYaml, error) {
|
||||||
var conf ConfYaml
|
var conf ConfYaml
|
||||||
|
|
||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yaml")
|
||||||
|
@ -251,8 +251,8 @@ func LoadConf(confPath string) (ConfYaml, error) {
|
||||||
viper.SetEnvPrefix("gorush") // will be uppercased automatically
|
viper.SetEnvPrefix("gorush") // will be uppercased automatically
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
|
||||||
if confPath != "" {
|
if len(confPath) > 0 && confPath[0] != "" {
|
||||||
content, err := ioutil.ReadFile(confPath)
|
content, err := ioutil.ReadFile(confPath[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conf, err
|
return conf, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ type ConfigTestSuite struct {
|
||||||
|
|
||||||
func (suite *ConfigTestSuite) SetupTest() {
|
func (suite *ConfigTestSuite) SetupTest() {
|
||||||
var err error
|
var err error
|
||||||
suite.ConfGorushDefault, err = LoadConf("")
|
suite.ConfGorushDefault, err = LoadConf()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to load default config.yml")
|
panic("failed to load default config.yml")
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,6 @@ func TestLoadConfigFromEnv(t *testing.T) {
|
||||||
|
|
||||||
func TestLoadWrongDefaultYAMLConfig(t *testing.T) {
|
func TestLoadWrongDefaultYAMLConfig(t *testing.T) {
|
||||||
defaultConf = []byte(`a`)
|
defaultConf = []byte(`a`)
|
||||||
_, err := LoadConf("")
|
_, err := LoadConf()
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package gorush
|
|
||||||
|
|
||||||
// Stat variable for redis
|
|
||||||
const (
|
|
||||||
TotalCountKey = "gorush-total-count"
|
|
||||||
IosSuccessKey = "gorush-ios-success-count"
|
|
||||||
IosErrorKey = "gorush-ios-error-count"
|
|
||||||
AndroidSuccessKey = "gorush-android-success-count"
|
|
||||||
AndroidErrorKey = "gorush-android-error-count"
|
|
||||||
HuaweiSuccessKey = "gorush-huawei-success-count"
|
|
||||||
HuaweiErrorKey = "gorush-huawei-error-count"
|
|
||||||
)
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEmptyFeedbackURL(t *testing.T) {
|
func TestEmptyFeedbackURL(t *testing.T) {
|
||||||
// PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
logEntry := logx.LogPushEntry{
|
logEntry := logx.LogPushEntry{
|
||||||
ID: "",
|
ID: "",
|
||||||
Type: "",
|
Type: "",
|
||||||
|
@ -23,13 +23,13 @@ func TestEmptyFeedbackURL(t *testing.T) {
|
||||||
Error: "",
|
Error: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
err := DispatchFeedback(logEntry, PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHTTPErrorInFeedbackCall(t *testing.T) {
|
func TestHTTPErrorInFeedbackCall(t *testing.T) {
|
||||||
config, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
config.Core.FeedbackURL = "http://test.example.com/api/"
|
cfg.Core.FeedbackURL = "http://test.example.com/api/"
|
||||||
logEntry := logx.LogPushEntry{
|
logEntry := logx.LogPushEntry{
|
||||||
ID: "",
|
ID: "",
|
||||||
Type: "",
|
Type: "",
|
||||||
|
@ -39,7 +39,7 @@ func TestHTTPErrorInFeedbackCall(t *testing.T) {
|
||||||
Error: "",
|
Error: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
err := DispatchFeedback(logEntry, config.Core.FeedbackURL, config.Core.FeedbackTimeout)
|
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ func TestSuccessfulFeedbackCall(t *testing.T) {
|
||||||
)
|
)
|
||||||
defer httpMock.Close()
|
defer httpMock.Close()
|
||||||
|
|
||||||
config, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
config.Core.FeedbackURL = httpMock.URL
|
cfg.Core.FeedbackURL = httpMock.URL
|
||||||
logEntry := logx.LogPushEntry{
|
logEntry := logx.LogPushEntry{
|
||||||
ID: "",
|
ID: "",
|
||||||
Type: "",
|
Type: "",
|
||||||
|
@ -70,6 +70,6 @@ func TestSuccessfulFeedbackCall(t *testing.T) {
|
||||||
Error: "",
|
Error: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
err := DispatchFeedback(logEntry, config.Core.FeedbackURL, config.Core.FeedbackTimeout)
|
err := DispatchFeedback(logEntry, cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
package gorush
|
package gorush
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/appleboy/gorush/config"
|
|
||||||
|
|
||||||
"github.com/appleboy/go-fcm"
|
"github.com/appleboy/go-fcm"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||||
"github.com/sideshow/apns2"
|
"github.com/sideshow/apns2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// PushConf is gorush config
|
|
||||||
PushConf config.ConfYaml
|
|
||||||
// QueueNotification is chan type
|
|
||||||
QueueNotification chan PushNotification
|
|
||||||
// ApnsClient is apns client
|
// ApnsClient is apns client
|
||||||
ApnsClient *apns2.Client
|
ApnsClient *apns2.Client
|
||||||
// FCMClient is apns client
|
// FCMClient is apns client
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package gorush
|
package gorush
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
|
@ -12,33 +10,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
if err := logx.InitLog(
|
if err := logx.InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := status.InitAppStatus(PushConf); err != nil {
|
if err := status.InitAppStatus(cfg); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(int(PushConf.Core.WorkerNum))
|
|
||||||
InitWorkers(ctx, wg, PushConf.Core.WorkerNum, PushConf.Core.QueueNum)
|
|
||||||
|
|
||||||
if err := status.InitAppStatus(PushConf); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
close(QueueNotification)
|
|
||||||
cancel()
|
|
||||||
}()
|
|
||||||
|
|
||||||
m.Run()
|
m.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/appleboy/go-fcm"
|
"github.com/appleboy/go-fcm"
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||||
|
@ -54,8 +55,8 @@ type RequestPush struct {
|
||||||
|
|
||||||
// PushNotification is single notification request
|
// PushNotification is single notification request
|
||||||
type PushNotification struct {
|
type PushNotification struct {
|
||||||
wg *sync.WaitGroup
|
Wg *sync.WaitGroup
|
||||||
log *[]logx.LogPushEntry
|
Log *[]logx.LogPushEntry
|
||||||
|
|
||||||
// Common
|
// Common
|
||||||
ID string `json:"notif_id,omitempty"`
|
ID string `json:"notif_id,omitempty"`
|
||||||
|
@ -112,22 +113,22 @@ type PushNotification struct {
|
||||||
|
|
||||||
// WaitDone decrements the WaitGroup counter.
|
// WaitDone decrements the WaitGroup counter.
|
||||||
func (p *PushNotification) WaitDone() {
|
func (p *PushNotification) WaitDone() {
|
||||||
if p.wg != nil {
|
if p.Wg != nil {
|
||||||
p.wg.Done()
|
p.Wg.Done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddWaitCount increments the WaitGroup counter.
|
// AddWaitCount increments the WaitGroup counter.
|
||||||
func (p *PushNotification) AddWaitCount() {
|
func (p *PushNotification) AddWaitCount() {
|
||||||
if p.wg != nil {
|
if p.Wg != nil {
|
||||||
p.wg.Add(1)
|
p.Wg.Add(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLog record fail log of notification
|
// AddLog record fail log of notification
|
||||||
func (p *PushNotification) AddLog(log logx.LogPushEntry) {
|
func (p *PushNotification) AddLog(log logx.LogPushEntry) {
|
||||||
if p.log != nil {
|
if p.Log != nil {
|
||||||
*p.log = append(*p.log, log)
|
*p.Log = append(*p.Log, log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,39 +200,55 @@ func SetProxy(proxy string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckPushConf provide check your yml config.
|
// CheckPushConf provide check your yml config.
|
||||||
func CheckPushConf() error {
|
func CheckPushConf(cfg config.ConfYaml) error {
|
||||||
if !PushConf.Ios.Enabled && !PushConf.Android.Enabled && !PushConf.Huawei.Enabled {
|
if !cfg.Ios.Enabled && !cfg.Android.Enabled && !cfg.Huawei.Enabled {
|
||||||
return errors.New("Please enable iOS, Android or Huawei config in yml config")
|
return errors.New("Please enable iOS, Android or Huawei config in yml config")
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Ios.Enabled {
|
if cfg.Ios.Enabled {
|
||||||
if PushConf.Ios.KeyPath == "" && PushConf.Ios.KeyBase64 == "" {
|
if cfg.Ios.KeyPath == "" && cfg.Ios.KeyBase64 == "" {
|
||||||
return errors.New("Missing iOS certificate key")
|
return errors.New("Missing iOS certificate key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check certificate file exist
|
// check certificate file exist
|
||||||
if PushConf.Ios.KeyPath != "" {
|
if cfg.Ios.KeyPath != "" {
|
||||||
if _, err := os.Stat(PushConf.Ios.KeyPath); os.IsNotExist(err) {
|
if _, err := os.Stat(cfg.Ios.KeyPath); os.IsNotExist(err) {
|
||||||
return errors.New("certificate file does not exist")
|
return errors.New("certificate file does not exist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Android.Enabled {
|
if cfg.Android.Enabled {
|
||||||
if PushConf.Android.APIKey == "" {
|
if cfg.Android.APIKey == "" {
|
||||||
return errors.New("Missing Android API Key")
|
return errors.New("Missing Android API Key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Huawei.Enabled {
|
if cfg.Huawei.Enabled {
|
||||||
if PushConf.Huawei.AppSecret == "" {
|
if cfg.Huawei.AppSecret == "" {
|
||||||
return errors.New("Missing Huawei App Secret")
|
return errors.New("Missing Huawei App Secret")
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Huawei.AppID == "" {
|
if cfg.Huawei.AppID == "" {
|
||||||
return errors.New("Missing Huawei App ID")
|
return errors.New("Missing Huawei App ID")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendNotification send notification
|
||||||
|
func SendNotification(cfg config.ConfYaml, req PushNotification) {
|
||||||
|
defer func() {
|
||||||
|
req.WaitDone()
|
||||||
|
}()
|
||||||
|
|
||||||
|
switch req.Platform {
|
||||||
|
case core.PlatFormIos:
|
||||||
|
PushToIOS(cfg, req)
|
||||||
|
case core.PlatFormAndroid:
|
||||||
|
PushToAndroid(cfg, req)
|
||||||
|
case core.PlatFormHuawei:
|
||||||
|
PushToHuawei(cfg, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
@ -50,23 +51,23 @@ type Sound struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitAPNSClient use for initialize APNs Client.
|
// InitAPNSClient use for initialize APNs Client.
|
||||||
func InitAPNSClient() error {
|
func InitAPNSClient(cfg config.ConfYaml) error {
|
||||||
if PushConf.Ios.Enabled {
|
if cfg.Ios.Enabled {
|
||||||
var err error
|
var err error
|
||||||
var authKey *ecdsa.PrivateKey
|
var authKey *ecdsa.PrivateKey
|
||||||
var certificateKey tls.Certificate
|
var certificateKey tls.Certificate
|
||||||
var ext string
|
var ext string
|
||||||
|
|
||||||
if PushConf.Ios.KeyPath != "" {
|
if cfg.Ios.KeyPath != "" {
|
||||||
ext = filepath.Ext(PushConf.Ios.KeyPath)
|
ext = filepath.Ext(cfg.Ios.KeyPath)
|
||||||
|
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".p12":
|
case ".p12":
|
||||||
certificateKey, err = certificate.FromP12File(PushConf.Ios.KeyPath, PushConf.Ios.Password)
|
certificateKey, err = certificate.FromP12File(cfg.Ios.KeyPath, cfg.Ios.Password)
|
||||||
case ".pem":
|
case ".pem":
|
||||||
certificateKey, err = certificate.FromPemFile(PushConf.Ios.KeyPath, PushConf.Ios.Password)
|
certificateKey, err = certificate.FromPemFile(cfg.Ios.KeyPath, cfg.Ios.Password)
|
||||||
case ".p8":
|
case ".p8":
|
||||||
authKey, err = token.AuthKeyFromFile(PushConf.Ios.KeyPath)
|
authKey, err = token.AuthKeyFromFile(cfg.Ios.KeyPath)
|
||||||
default:
|
default:
|
||||||
err = errors.New("wrong certificate key extension")
|
err = errors.New("wrong certificate key extension")
|
||||||
}
|
}
|
||||||
|
@ -76,9 +77,9 @@ func InitAPNSClient() error {
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if PushConf.Ios.KeyBase64 != "" {
|
} else if cfg.Ios.KeyBase64 != "" {
|
||||||
ext = "." + PushConf.Ios.KeyType
|
ext = "." + cfg.Ios.KeyType
|
||||||
key, err := base64.StdEncoding.DecodeString(PushConf.Ios.KeyBase64)
|
key, err := base64.StdEncoding.DecodeString(cfg.Ios.KeyBase64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.LogError.Error("base64 decode error:", err.Error())
|
logx.LogError.Error("base64 decode error:", err.Error())
|
||||||
|
|
||||||
|
@ -86,9 +87,9 @@ func InitAPNSClient() error {
|
||||||
}
|
}
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".p12":
|
case ".p12":
|
||||||
certificateKey, err = certificate.FromP12Bytes(key, PushConf.Ios.Password)
|
certificateKey, err = certificate.FromP12Bytes(key, cfg.Ios.Password)
|
||||||
case ".pem":
|
case ".pem":
|
||||||
certificateKey, err = certificate.FromPemBytes(key, PushConf.Ios.Password)
|
certificateKey, err = certificate.FromPemBytes(key, cfg.Ios.Password)
|
||||||
case ".p8":
|
case ".p8":
|
||||||
authKey, err = token.AuthKeyFromBytes(key)
|
authKey, err = token.AuthKeyFromBytes(key)
|
||||||
default:
|
default:
|
||||||
|
@ -103,7 +104,7 @@ func InitAPNSClient() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ext == ".p8" {
|
if ext == ".p8" {
|
||||||
if PushConf.Ios.KeyID == "" || PushConf.Ios.TeamID == "" {
|
if cfg.Ios.KeyID == "" || cfg.Ios.TeamID == "" {
|
||||||
msg := "You should provide ios.KeyID and ios.TeamID for P8 token"
|
msg := "You should provide ios.KeyID and ios.TeamID for P8 token"
|
||||||
logx.LogError.Error(msg)
|
logx.LogError.Error(msg)
|
||||||
return errors.New(msg)
|
return errors.New(msg)
|
||||||
|
@ -111,14 +112,14 @@ func InitAPNSClient() error {
|
||||||
token := &token.Token{
|
token := &token.Token{
|
||||||
AuthKey: authKey,
|
AuthKey: authKey,
|
||||||
// KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
|
// KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
|
||||||
KeyID: PushConf.Ios.KeyID,
|
KeyID: cfg.Ios.KeyID,
|
||||||
// TeamID from developer account (View Account -> Membership)
|
// TeamID from developer account (View Account -> Membership)
|
||||||
TeamID: PushConf.Ios.TeamID,
|
TeamID: cfg.Ios.TeamID,
|
||||||
}
|
}
|
||||||
|
|
||||||
ApnsClient, err = newApnsTokenClient(token)
|
ApnsClient, err = newApnsTokenClient(cfg, token)
|
||||||
} else {
|
} else {
|
||||||
ApnsClient, err = newApnsClient(certificateKey)
|
ApnsClient, err = newApnsClient(cfg, certificateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if h2Transport, ok := ApnsClient.HTTPClient.Transport.(*http2.Transport); ok {
|
if h2Transport, ok := ApnsClient.HTTPClient.Transport.(*http2.Transport); ok {
|
||||||
|
@ -130,21 +131,23 @@ func InitAPNSClient() error {
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newApnsClient(certificate tls.Certificate) (*apns2.Client, error) {
|
func newApnsClient(cfg config.ConfYaml, certificate tls.Certificate) (*apns2.Client, error) {
|
||||||
var client *apns2.Client
|
var client *apns2.Client
|
||||||
|
|
||||||
if PushConf.Ios.Production {
|
if cfg.Ios.Production {
|
||||||
client = apns2.NewClient(certificate).Production()
|
client = apns2.NewClient(certificate).Production()
|
||||||
} else {
|
} else {
|
||||||
client = apns2.NewClient(certificate).Development()
|
client = apns2.NewClient(certificate).Development()
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Core.HTTPProxy == "" {
|
if cfg.Core.HTTPProxy == "" {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,16 +178,16 @@ func newApnsClient(certificate tls.Certificate) (*apns2.Client, error) {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newApnsTokenClient(token *token.Token) (*apns2.Client, error) {
|
func newApnsTokenClient(cfg config.ConfYaml, token *token.Token) (*apns2.Client, error) {
|
||||||
var client *apns2.Client
|
var client *apns2.Client
|
||||||
|
|
||||||
if PushConf.Ios.Production {
|
if cfg.Ios.Production {
|
||||||
client = apns2.NewTokenClient(token).Production()
|
client = apns2.NewTokenClient(token).Production()
|
||||||
} else {
|
} else {
|
||||||
client = apns2.NewTokenClient(token).Development()
|
client = apns2.NewTokenClient(token).Development()
|
||||||
}
|
}
|
||||||
|
|
||||||
if PushConf.Core.HTTPProxy == "" {
|
if cfg.Core.HTTPProxy == "" {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,13 +368,13 @@ func GetIOSNotification(req PushNotification) *apns2.Notification {
|
||||||
return notification
|
return notification
|
||||||
}
|
}
|
||||||
|
|
||||||
func getApnsClient(req PushNotification) (client *apns2.Client) {
|
func getApnsClient(cfg config.ConfYaml, req PushNotification) (client *apns2.Client) {
|
||||||
if req.Production {
|
if req.Production {
|
||||||
client = ApnsClient.Production()
|
client = ApnsClient.Production()
|
||||||
} else if req.Development {
|
} else if req.Development {
|
||||||
client = ApnsClient.Development()
|
client = ApnsClient.Development()
|
||||||
} else {
|
} else {
|
||||||
if PushConf.Ios.Production {
|
if cfg.Ios.Production {
|
||||||
client = ApnsClient.Production()
|
client = ApnsClient.Production()
|
||||||
} else {
|
} else {
|
||||||
client = ApnsClient.Development()
|
client = ApnsClient.Development()
|
||||||
|
@ -381,12 +384,12 @@ func getApnsClient(req PushNotification) (client *apns2.Client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushToIOS provide send notification to APNs server.
|
// PushToIOS provide send notification to APNs server.
|
||||||
func PushToIOS(req PushNotification) {
|
func PushToIOS(cfg config.ConfYaml, req PushNotification) {
|
||||||
logx.LogAccess.Debug("Start push notification for iOS")
|
logx.LogAccess.Debug("Start push notification for iOS")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
maxRetry = PushConf.Ios.MaxRetry
|
maxRetry = cfg.Ios.MaxRetry
|
||||||
)
|
)
|
||||||
|
|
||||||
if req.Retry > 0 && req.Retry < maxRetry {
|
if req.Retry > 0 && req.Retry < maxRetry {
|
||||||
|
@ -397,7 +400,7 @@ Retry:
|
||||||
var newTokens []string
|
var newTokens []string
|
||||||
|
|
||||||
notification := GetIOSNotification(req)
|
notification := GetIOSNotification(req)
|
||||||
client := getApnsClient(req)
|
client := getApnsClient(cfg, req)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for _, token := range req.Tokens {
|
for _, token := range req.Tokens {
|
||||||
|
@ -416,17 +419,17 @@ Retry:
|
||||||
err = errors.New(res.Reason)
|
err = errors.New(res.Reason)
|
||||||
}
|
}
|
||||||
// apns server error
|
// apns server error
|
||||||
logPush(core.FailedPush, token, req, err)
|
logPush(cfg, core.FailedPush, token, req, err)
|
||||||
|
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, token, req, err))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, token, req, err))
|
||||||
} else if PushConf.Core.FeedbackURL != "" {
|
} else if cfg.Core.FeedbackURL != "" {
|
||||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||||
err := DispatchFeedback(log, url, timeout)
|
err := DispatchFeedback(log, url, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
}(logx.LogError, createLogPushEntry(core.FailedPush, token, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, token, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
status.StatStorage.AddIosError(1)
|
status.StatStorage.AddIosError(1)
|
||||||
|
@ -438,7 +441,7 @@ Retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
if res != nil && res.Sent() {
|
if res != nil && res.Sent() {
|
||||||
logPush(core.SucceededPush, token, req, nil)
|
logPush(cfg, core.SucceededPush, token, req, nil)
|
||||||
status.StatStorage.AddIosSuccess(1)
|
status.StatStorage.AddIosSuccess(1)
|
||||||
}
|
}
|
||||||
// free push slot
|
// free push slot
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
package gorush
|
package gorush
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/sideshow/apns2"
|
"github.com/sideshow/apns2"
|
||||||
|
@ -27,29 +24,29 @@ const authkeyInvalidP8 = `TUlHSEFnRUFNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQkcwd2
|
||||||
const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ0ViVnpmUG5aUHhmQXl4cUUKWlYwNWxhQW9KQWwrLzZYdDJPNG1PQjYxMXNPaFJBTkNBQVNnRlRLandKQUFVOTVnKysvdnpLV0hrekFWbU5NSQp0QjV2VGpaT09Jd25FYjcwTXNXWkZJeVVGRDFQOUd3c3R6NCtha0hYN3ZJOEJINmhIbUJtZmVRbAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==`
|
const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ0ViVnpmUG5aUHhmQXl4cUUKWlYwNWxhQW9KQWwrLzZYdDJPNG1PQjYxMXNPaFJBTkNBQVNnRlRLandKQUFVOTVnKysvdnpLV0hrekFWbU5NSQp0QjV2VGpaT09Jd25FYjcwTXNXWkZJeVVGRDFQOUd3c3R6NCtha0hYN3ZJOEJINmhIbUJtZmVRbAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==`
|
||||||
|
|
||||||
func TestDisabledAndroidIosConf(t *testing.T) {
|
func TestDisabledAndroidIosConf(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Android.Enabled = false
|
cfg.Android.Enabled = false
|
||||||
PushConf.Huawei.Enabled = false
|
cfg.Huawei.Enabled = false
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "Please enable iOS, Android or Huawei config in yml config", err.Error())
|
assert.Equal(t, "Please enable iOS, Android or Huawei config in yml config", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingIOSCertificate(t *testing.T) {
|
func TestMissingIOSCertificate(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = ""
|
cfg.Ios.KeyBase64 = ""
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "Missing iOS certificate key", err.Error())
|
assert.Equal(t, "Missing iOS certificate key", err.Error())
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = "test.pem"
|
cfg.Ios.KeyPath = "test.pem"
|
||||||
err = CheckPushConf()
|
err = CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "certificate file does not exist", err.Error())
|
assert.Equal(t, "certificate file does not exist", err.Error())
|
||||||
|
@ -566,166 +563,130 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
|
||||||
assert.Contains(t, locArgs, "b")
|
assert.Contains(t, locArgs, "b")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDisabledIosNotifications(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Ios.Enabled = false
|
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
|
||||||
err := InitAPNSClient()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// ios
|
|
||||||
{
|
|
||||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
|
||||||
Platform: core.PlatFormIos,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
Tokens: []string{androidToken, androidToken + "_"},
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 2, count)
|
|
||||||
assert.Equal(t, 0, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrongIosCertificateExt(t *testing.T) {
|
func TestWrongIosCertificateExt(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "test"
|
cfg.Ios.KeyPath = "test"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "wrong certificate key extension", err.Error())
|
assert.Equal(t, "wrong certificate key extension", err.Error())
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = "abcd"
|
cfg.Ios.KeyBase64 = "abcd"
|
||||||
PushConf.Ios.KeyType = "abcd"
|
cfg.Ios.KeyType = "abcd"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "wrong certificate key type", err.Error())
|
assert.Equal(t, "wrong certificate key type", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPNSClientDevHost(t *testing.T) {
|
func TestAPNSClientDevHost(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = certificateValidP12
|
cfg.Ios.KeyBase64 = certificateValidP12
|
||||||
PushConf.Ios.KeyType = "p12"
|
cfg.Ios.KeyType = "p12"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPNSClientProdHost(t *testing.T) {
|
func TestAPNSClientProdHost(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.Production = true
|
cfg.Ios.Production = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = certificateValidPEM
|
cfg.Ios.KeyBase64 = certificateValidPEM
|
||||||
PushConf.Ios.KeyType = "pem"
|
cfg.Ios.KeyType = "pem"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPNSClientInvaildToken(t *testing.T) {
|
func TestAPNSClientInvaildToken(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/authkey-invalid.p8"
|
cfg.Ios.KeyPath = "../certificate/authkey-invalid.p8"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = authkeyInvalidP8
|
cfg.Ios.KeyBase64 = authkeyInvalidP8
|
||||||
PushConf.Ios.KeyType = "p8"
|
cfg.Ios.KeyType = "p8"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
// empty key-id or team-id
|
// empty key-id or team-id
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
PushConf.Ios.KeyID = "key-id"
|
cfg.Ios.KeyID = "key-id"
|
||||||
PushConf.Ios.TeamID = ""
|
cfg.Ios.TeamID = ""
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
PushConf.Ios.KeyID = ""
|
cfg.Ios.KeyID = ""
|
||||||
PushConf.Ios.TeamID = "team-id"
|
cfg.Ios.TeamID = "team-id"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPNSClientVaildToken(t *testing.T) {
|
func TestAPNSClientVaildToken(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||||
PushConf.Ios.KeyID = "key-id"
|
cfg.Ios.KeyID = "key-id"
|
||||||
PushConf.Ios.TeamID = "team-id"
|
cfg.Ios.TeamID = "team-id"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
|
|
||||||
PushConf.Ios.Production = true
|
cfg.Ios.Production = true
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||||
|
|
||||||
// test base64
|
// test base64
|
||||||
PushConf.Ios.Production = false
|
cfg.Ios.Production = false
|
||||||
PushConf.Ios.KeyPath = ""
|
cfg.Ios.KeyPath = ""
|
||||||
PushConf.Ios.KeyBase64 = authkeyValidP8
|
cfg.Ios.KeyBase64 = authkeyValidP8
|
||||||
PushConf.Ios.KeyType = "p8"
|
cfg.Ios.KeyType = "p8"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
|
|
||||||
PushConf.Ios.Production = true
|
cfg.Ios.Production = true
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPNSClientUseProxy(t *testing.T) {
|
func TestAPNSClientUseProxy(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.p12"
|
||||||
PushConf.Core.HTTPProxy = "http://127.0.0.1:8080"
|
cfg.Core.HTTPProxy = "http://127.0.0.1:8080"
|
||||||
_ = SetProxy(PushConf.Core.HTTPProxy)
|
_ = SetProxy(cfg.Core.HTTPProxy)
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
|
|
||||||
|
@ -733,13 +694,13 @@ func TestAPNSClientUseProxy(t *testing.T) {
|
||||||
actualProxyURL, err := ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
actualProxyURL, err := ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
expectedProxyURL, _ := url.ParseRequestURI(PushConf.Core.HTTPProxy)
|
expectedProxyURL, _ := url.ParseRequestURI(cfg.Core.HTTPProxy)
|
||||||
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
||||||
|
|
||||||
PushConf.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
cfg.Ios.KeyPath = "../certificate/authkey-valid.p8"
|
||||||
PushConf.Ios.TeamID = "example.team"
|
cfg.Ios.TeamID = "example.team"
|
||||||
PushConf.Ios.KeyID = "example.key"
|
cfg.Ios.KeyID = "example.key"
|
||||||
err = InitAPNSClient()
|
err = InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
|
||||||
assert.NotNil(t, ApnsClient.Token)
|
assert.NotNil(t, ApnsClient.Token)
|
||||||
|
@ -748,21 +709,21 @@ func TestAPNSClientUseProxy(t *testing.T) {
|
||||||
actualProxyURL, err = ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
actualProxyURL, err = ApnsClient.HTTPClient.Transport.(*http.Transport).Proxy(req)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
expectedProxyURL, _ = url.ParseRequestURI(PushConf.Core.HTTPProxy)
|
expectedProxyURL, _ = url.ParseRequestURI(cfg.Core.HTTPProxy)
|
||||||
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
assert.Equal(t, expectedProxyURL, actualProxyURL)
|
||||||
|
|
||||||
http.DefaultTransport.(*http.Transport).Proxy = nil
|
http.DefaultTransport.(*http.Transport).Proxy = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPushToIOS(t *testing.T) {
|
func TestPushToIOS(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
MaxConcurrentIOSPushes = make(chan struct{}, PushConf.Ios.MaxConcurrentPushes)
|
MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
err = status.InitAppStatus(PushConf)
|
err = status.InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
req := PushNotification{
|
req := PushNotification{
|
||||||
|
@ -772,37 +733,37 @@ func TestPushToIOS(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send fail
|
// send fail
|
||||||
PushToIOS(req)
|
PushToIOS(cfg, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApnsHostFromRequest(t *testing.T) {
|
func TestApnsHostFromRequest(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
err := InitAPNSClient()
|
err := InitAPNSClient(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
err = status.InitAppStatus(PushConf)
|
err = status.InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
req := PushNotification{
|
req := PushNotification{
|
||||||
Production: true,
|
Production: true,
|
||||||
}
|
}
|
||||||
client := getApnsClient(req)
|
client := getApnsClient(cfg, req)
|
||||||
assert.Equal(t, apns2.HostProduction, client.Host)
|
assert.Equal(t, apns2.HostProduction, client.Host)
|
||||||
|
|
||||||
req = PushNotification{
|
req = PushNotification{
|
||||||
Development: true,
|
Development: true,
|
||||||
}
|
}
|
||||||
client = getApnsClient(req)
|
client = getApnsClient(cfg, req)
|
||||||
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
||||||
|
|
||||||
req = PushNotification{}
|
req = PushNotification{}
|
||||||
PushConf.Ios.Production = true
|
cfg.Ios.Production = true
|
||||||
client = getApnsClient(req)
|
client = getApnsClient(cfg, req)
|
||||||
assert.Equal(t, apns2.HostProduction, client.Host)
|
assert.Equal(t, apns2.HostProduction, client.Host)
|
||||||
|
|
||||||
PushConf.Ios.Production = false
|
cfg.Ios.Production = false
|
||||||
client = getApnsClient(req)
|
client = getApnsClient(cfg, req)
|
||||||
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
assert.Equal(t, apns2.HostDevelopment, client.Host)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,27 +4,29 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/appleboy/go-fcm"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
|
||||||
|
"github.com/appleboy/go-fcm"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitFCMClient use for initialize FCM Client.
|
// InitFCMClient use for initialize FCM Client.
|
||||||
func InitFCMClient(key string) (*fcm.Client, error) {
|
func InitFCMClient(cfg config.ConfYaml, key string) (*fcm.Client, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if key == "" {
|
if key == "" && cfg.Android.APIKey == "" {
|
||||||
return nil, errors.New("Missing Android API Key")
|
return nil, errors.New("Missing Android API Key")
|
||||||
}
|
}
|
||||||
|
|
||||||
if key != PushConf.Android.APIKey {
|
if key != "" && key != cfg.Android.APIKey {
|
||||||
return fcm.NewClient(key)
|
return fcm.NewClient(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if FCMClient == nil {
|
if FCMClient == nil {
|
||||||
FCMClient, err = fcm.NewClient(key)
|
FCMClient, err = fcm.NewClient(cfg.Android.APIKey)
|
||||||
return FCMClient, err
|
return FCMClient, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,13 +106,13 @@ func GetAndroidNotification(req PushNotification) *fcm.Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushToAndroid provide send notification to Android server.
|
// PushToAndroid provide send notification to Android server.
|
||||||
func PushToAndroid(req PushNotification) {
|
func PushToAndroid(cfg config.ConfYaml, req PushNotification) {
|
||||||
logx.LogAccess.Debug("Start push notification for Android")
|
logx.LogAccess.Debug("Start push notification for Android")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
client *fcm.Client
|
client *fcm.Client
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
maxRetry = PushConf.Android.MaxRetry
|
maxRetry = cfg.Android.MaxRetry
|
||||||
)
|
)
|
||||||
|
|
||||||
if req.Retry > 0 && req.Retry < maxRetry {
|
if req.Retry > 0 && req.Retry < maxRetry {
|
||||||
|
@ -128,9 +130,9 @@ Retry:
|
||||||
notification := GetAndroidNotification(req)
|
notification := GetAndroidNotification(req)
|
||||||
|
|
||||||
if req.APIKey != "" {
|
if req.APIKey != "" {
|
||||||
client, err = InitFCMClient(req.APIKey)
|
client, err = InitFCMClient(cfg, req.APIKey)
|
||||||
} else {
|
} else {
|
||||||
client, err = InitFCMClient(PushConf.Android.APIKey)
|
client, err = InitFCMClient(cfg, cfg.Android.APIKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -145,28 +147,28 @@ Retry:
|
||||||
logx.LogError.Error("FCM server send message error: " + err.Error())
|
logx.LogError.Error("FCM server send message error: " + err.Error())
|
||||||
|
|
||||||
if req.IsTopic() {
|
if req.IsTopic() {
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, req.To, req, err))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, req.To, req, err))
|
||||||
} else if PushConf.Core.FeedbackURL != "" {
|
} else if cfg.Core.FeedbackURL != "" {
|
||||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||||
err := DispatchFeedback(log, url, timeout)
|
err := DispatchFeedback(log, url, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
}(logx.LogError, createLogPushEntry(core.FailedPush, req.To, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, req.To, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
}
|
}
|
||||||
status.StatStorage.AddAndroidError(1)
|
status.StatStorage.AddAndroidError(1)
|
||||||
} else {
|
} else {
|
||||||
for _, token := range req.Tokens {
|
for _, token := range req.Tokens {
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, token, req, err))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, token, req, err))
|
||||||
} else if PushConf.Core.FeedbackURL != "" {
|
} else if cfg.Core.FeedbackURL != "" {
|
||||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||||
err := DispatchFeedback(log, url, timeout)
|
err := DispatchFeedback(log, url, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
}(logx.LogError, createLogPushEntry(core.FailedPush, token, req, err), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, token, req, err), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status.StatStorage.AddAndroidError(int64(len(req.Tokens)))
|
status.StatStorage.AddAndroidError(int64(len(req.Tokens)))
|
||||||
|
@ -198,21 +200,21 @@ Retry:
|
||||||
newTokens = append(newTokens, to)
|
newTokens = append(newTokens, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
logPush(core.FailedPush, to, req, result.Error)
|
logPush(cfg, core.FailedPush, to, req, result.Error)
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, to, req, result.Error))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, to, req, result.Error))
|
||||||
} else if PushConf.Core.FeedbackURL != "" {
|
} else if cfg.Core.FeedbackURL != "" {
|
||||||
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
go func(logger *logrus.Logger, log logx.LogPushEntry, url string, timeout int64) {
|
||||||
err := DispatchFeedback(log, url, timeout)
|
err := DispatchFeedback(log, url, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
}(logx.LogError, createLogPushEntry(core.FailedPush, to, req, result.Error), PushConf.Core.FeedbackURL, PushConf.Core.FeedbackTimeout)
|
}(logx.LogError, createLogPushEntry(cfg, core.FailedPush, to, req, result.Error), cfg.Core.FeedbackURL, cfg.Core.FeedbackTimeout)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logPush(core.SucceededPush, to, req, nil)
|
logPush(cfg, core.SucceededPush, to, req, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// result from Send messages to topics
|
// result from Send messages to topics
|
||||||
|
@ -226,12 +228,12 @@ Retry:
|
||||||
logx.LogAccess.Debug("Send Topic Message: ", to)
|
logx.LogAccess.Debug("Send Topic Message: ", to)
|
||||||
// Success
|
// Success
|
||||||
if res.MessageID != 0 {
|
if res.MessageID != 0 {
|
||||||
logPush(core.SucceededPush, to, req, nil)
|
logPush(cfg, core.SucceededPush, to, req, nil)
|
||||||
} else {
|
} else {
|
||||||
// failure
|
// failure
|
||||||
logPush(core.FailedPush, to, req, res.Error)
|
logPush(cfg, core.FailedPush, to, req, res.Error)
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, to, req, res.Error))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, to, req, res.Error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,9 +242,9 @@ Retry:
|
||||||
if len(res.FailedRegistrationIDs) > 0 {
|
if len(res.FailedRegistrationIDs) > 0 {
|
||||||
newTokens = append(newTokens, res.FailedRegistrationIDs...)
|
newTokens = append(newTokens, res.FailedRegistrationIDs...)
|
||||||
|
|
||||||
logPush(core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails"))
|
logPush(cfg, core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails"))
|
||||||
if PushConf.Core.Sync {
|
if cfg.Core.Sync {
|
||||||
req.AddLog(createLogPushEntry(core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails")))
|
req.AddLog(createLogPushEntry(cfg, core.FailedPush, notification.To, req, errors.New("device group: partial success or all fails")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +257,7 @@ Retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createLogPushEntry(status, token string, req PushNotification, err error) logx.LogPushEntry {
|
func createLogPushEntry(cfg config.ConfYaml, status, token string, req PushNotification, err error) logx.LogPushEntry {
|
||||||
return logx.GetLogPushEntry(&logx.InputLog{
|
return logx.GetLogPushEntry(&logx.InputLog{
|
||||||
ID: req.ID,
|
ID: req.ID,
|
||||||
Status: status,
|
Status: status,
|
||||||
|
@ -263,12 +265,12 @@ func createLogPushEntry(status, token string, req PushNotification, err error) l
|
||||||
Message: req.Message,
|
Message: req.Message,
|
||||||
Platform: req.Platform,
|
Platform: req.Platform,
|
||||||
Error: err,
|
Error: err,
|
||||||
HideToken: PushConf.Log.HideToken,
|
HideToken: cfg.Log.HideToken,
|
||||||
Format: PushConf.Log.Format,
|
Format: cfg.Log.Format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func logPush(status, token string, req PushNotification, err error) {
|
func logPush(cfg config.ConfYaml, status, token string, req PushNotification, err error) {
|
||||||
logx.LogPush(&logx.InputLog{
|
logx.LogPush(&logx.InputLog{
|
||||||
ID: req.ID,
|
ID: req.ID,
|
||||||
Status: status,
|
Status: status,
|
||||||
|
@ -276,7 +278,7 @@ func logPush(status, token string, req PushNotification, err error) {
|
||||||
Message: req.Message,
|
Message: req.Message,
|
||||||
Platform: req.Platform,
|
Platform: req.Platform,
|
||||||
Error: err,
|
Error: err,
|
||||||
HideToken: PushConf.Log.HideToken,
|
HideToken: cfg.Log.HideToken,
|
||||||
Format: PushConf.Log.Format,
|
Format: cfg.Log.Format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMissingAndroidAPIKey(t *testing.T) {
|
func TestMissingAndroidAPIKey(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = ""
|
cfg.Android.APIKey = ""
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "Missing Android API Key", err.Error())
|
assert.Equal(t, "Missing Android API Key", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingKeyForInitFCMClient(t *testing.T) {
|
func TestMissingKeyForInitFCMClient(t *testing.T) {
|
||||||
client, err := InitFCMClient("")
|
cfg, _ := config.LoadConf()
|
||||||
|
cfg.Android.APIKey = ""
|
||||||
|
client, err := InitFCMClient(cfg, "")
|
||||||
|
|
||||||
assert.Nil(t, client)
|
assert.Nil(t, client)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -33,10 +35,10 @@ func TestMissingKeyForInitFCMClient(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPushToAndroidWrongToken(t *testing.T) {
|
func TestPushToAndroidWrongToken(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
|
||||||
req := PushNotification{
|
req := PushNotification{
|
||||||
Tokens: []string{"aaaaaa", "bbbbb"},
|
Tokens: []string{"aaaaaa", "bbbbb"},
|
||||||
|
@ -45,16 +47,16 @@ func TestPushToAndroidWrongToken(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Android Success count: 0, Failure count: 2
|
// Android Success count: 0, Failure count: 2
|
||||||
PushToAndroid(req)
|
PushToAndroid(cfg, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
|
func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
// log for json
|
// log for json
|
||||||
PushConf.Log.Format = "json"
|
cfg.Log.Format = "json"
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
@ -64,14 +66,14 @@ func TestPushToAndroidRightTokenForJSONLog(t *testing.T) {
|
||||||
Message: "Welcome",
|
Message: "Welcome",
|
||||||
}
|
}
|
||||||
|
|
||||||
PushToAndroid(req)
|
PushToAndroid(cfg, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
|
func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
@ -81,15 +83,15 @@ func TestPushToAndroidRightTokenForStringLog(t *testing.T) {
|
||||||
Message: "Welcome",
|
Message: "Welcome",
|
||||||
}
|
}
|
||||||
|
|
||||||
PushToAndroid(req)
|
PushToAndroid(cfg, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverwriteAndroidAPIKey(t *testing.T) {
|
func TestOverwriteAndroidAPIKey(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Core.Sync = true
|
cfg.Core.Sync = true
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
@ -100,13 +102,13 @@ func TestOverwriteAndroidAPIKey(t *testing.T) {
|
||||||
// overwrite android api key
|
// overwrite android api key
|
||||||
APIKey: "1234",
|
APIKey: "1234",
|
||||||
|
|
||||||
log: &[]logx.LogPushEntry{},
|
Log: &[]logx.LogPushEntry{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// FCM server error: 401 error: 401 Unauthorized (Wrong API Key)
|
// FCM server error: 401 error: 401 Unauthorized (Wrong API Key)
|
||||||
PushToAndroid(req)
|
PushToAndroid(cfg, req)
|
||||||
|
|
||||||
assert.Len(t, *req.log, 2)
|
assert.Len(t, *req.Log, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFCMMessage(t *testing.T) {
|
func TestFCMMessage(t *testing.T) {
|
||||||
|
@ -188,10 +190,10 @@ func TestFCMMessage(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckAndroidMessage(t *testing.T) {
|
func TestCheckAndroidMessage(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
|
||||||
timeToLive := uint(2419201)
|
timeToLive := uint(2419201)
|
||||||
req := PushNotification{
|
req := PushNotification{
|
||||||
|
@ -201,7 +203,7 @@ func TestCheckAndroidMessage(t *testing.T) {
|
||||||
TimeToLive: &timeToLive,
|
TimeToLive: &timeToLive,
|
||||||
}
|
}
|
||||||
|
|
||||||
PushToAndroid(req)
|
PushToAndroid(cfg, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAndroidNotificationStructure(t *testing.T) {
|
func TestAndroidNotificationStructure(t *testing.T) {
|
||||||
|
|
|
@ -6,10 +6,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/config"
|
c "github.com/msalihkarakasli/go-hms-push/push/config"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/core"
|
"github.com/msalihkarakasli/go-hms-push/push/core"
|
||||||
"github.com/msalihkarakasli/go-hms-push/push/model"
|
"github.com/msalihkarakasli/go-hms-push/push/model"
|
||||||
)
|
)
|
||||||
|
@ -21,7 +22,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPushClient use for create HMS Push
|
// GetPushClient use for create HMS Push
|
||||||
func GetPushClient(conf *config.Config) (*core.HMSClient, error) {
|
func GetPushClient(conf *c.Config) (*core.HMSClient, error) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
client, err := core.NewHttpClient(conf)
|
client, err := core.NewHttpClient(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -35,7 +36,7 @@ func GetPushClient(conf *config.Config) (*core.HMSClient, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitHMSClient use for initialize HMS Client.
|
// InitHMSClient use for initialize HMS Client.
|
||||||
func InitHMSClient(appSecret, appID string) (*core.HMSClient, error) {
|
func InitHMSClient(cfg config.ConfYaml, appSecret, appID string) (*core.HMSClient, error) {
|
||||||
if appSecret == "" {
|
if appSecret == "" {
|
||||||
return nil, errors.New("Missing Huawei App Secret")
|
return nil, errors.New("Missing Huawei App Secret")
|
||||||
}
|
}
|
||||||
|
@ -44,14 +45,14 @@ func InitHMSClient(appSecret, appID string) (*core.HMSClient, error) {
|
||||||
return nil, errors.New("Missing Huawei App ID")
|
return nil, errors.New("Missing Huawei App ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := &config.Config{
|
conf := &c.Config{
|
||||||
AppId: appID,
|
AppId: appID,
|
||||||
AppSecret: appSecret,
|
AppSecret: appSecret,
|
||||||
AuthUrl: "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
|
AuthUrl: "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
|
||||||
PushUrl: "https://push-api.cloud.huawei.com",
|
PushUrl: "https://push-api.cloud.huawei.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
if appSecret != PushConf.Huawei.AppSecret || appID != PushConf.Huawei.AppID {
|
if appSecret != cfg.Huawei.AppSecret || appID != cfg.Huawei.AppID {
|
||||||
return GetPushClient(conf)
|
return GetPushClient(conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,13 +166,13 @@ func GetHuaweiNotification(req PushNotification) (*model.MessageRequest, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushToHuawei provide send notification to Android server.
|
// PushToHuawei provide send notification to Android server.
|
||||||
func PushToHuawei(req PushNotification) bool {
|
func PushToHuawei(cfg config.ConfYaml, req PushNotification) bool {
|
||||||
logx.LogAccess.Debug("Start push notification for Huawei")
|
logx.LogAccess.Debug("Start push notification for Huawei")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
client *core.HMSClient
|
client *core.HMSClient
|
||||||
retryCount = 0
|
retryCount = 0
|
||||||
maxRetry = PushConf.Huawei.MaxRetry
|
maxRetry = cfg.Huawei.MaxRetry
|
||||||
)
|
)
|
||||||
|
|
||||||
if req.Retry > 0 && req.Retry < maxRetry {
|
if req.Retry > 0 && req.Retry < maxRetry {
|
||||||
|
@ -190,7 +191,7 @@ Retry:
|
||||||
|
|
||||||
notification, _ := GetHuaweiNotification(req)
|
notification, _ := GetHuaweiNotification(req)
|
||||||
|
|
||||||
client, err = InitHMSClient(PushConf.Huawei.AppSecret, PushConf.Huawei.AppID)
|
client, err = InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// HMS server error
|
// HMS server error
|
||||||
|
|
|
@ -8,31 +8,32 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMissingHuaweiAppSecret(t *testing.T) {
|
func TestMissingHuaweiAppSecret(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Huawei.Enabled = true
|
cfg.Huawei.Enabled = true
|
||||||
PushConf.Huawei.AppSecret = ""
|
cfg.Huawei.AppSecret = ""
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "Missing Huawei App Secret", err.Error())
|
assert.Equal(t, "Missing Huawei App Secret", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingHuaweiAppID(t *testing.T) {
|
func TestMissingHuaweiAppID(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Huawei.Enabled = true
|
cfg.Huawei.Enabled = true
|
||||||
PushConf.Huawei.AppID = ""
|
cfg.Huawei.AppID = ""
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "Missing Huawei App ID", err.Error())
|
assert.Equal(t, "Missing Huawei App ID", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingAppSecretForInitHMSClient(t *testing.T) {
|
func TestMissingAppSecretForInitHMSClient(t *testing.T) {
|
||||||
client, err := InitHMSClient("", "APP_SECRET")
|
cfg, _ := config.LoadConf()
|
||||||
|
client, err := InitHMSClient(cfg, "", "APP_SECRET")
|
||||||
|
|
||||||
assert.Nil(t, client)
|
assert.Nil(t, client)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -40,7 +41,8 @@ func TestMissingAppSecretForInitHMSClient(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingAppIDForInitHMSClient(t *testing.T) {
|
func TestMissingAppIDForInitHMSClient(t *testing.T) {
|
||||||
client, err := InitHMSClient("APP_ID", "")
|
cfg, _ := config.LoadConf()
|
||||||
|
client, err := InitHMSClient(cfg, "APP_ID", "")
|
||||||
|
|
||||||
assert.Nil(t, client)
|
assert.Nil(t, client)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
|
@ -1,210 +1,26 @@
|
||||||
package gorush
|
package gorush
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCorrectConf(t *testing.T) {
|
func TestCorrectConf(t *testing.T) {
|
||||||
PushConf, _ = config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
cfg.Android.Enabled = true
|
||||||
PushConf.Android.APIKey = "xxxxx"
|
cfg.Android.APIKey = "xxxxx"
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
cfg.Ios.Enabled = true
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
|
|
||||||
err := CheckPushConf()
|
err := CheckPushConf(cfg)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSenMultipleNotifications(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
|
||||||
err := InitAPNSClient()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// ios
|
|
||||||
{
|
|
||||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
|
||||||
Platform: core.PlatFormIos,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
Tokens: []string{androidToken, "bbbbb"},
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 3, count)
|
|
||||||
assert.Equal(t, 0, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDisabledAndroidNotifications(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
|
||||||
err := InitAPNSClient()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = false
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// ios
|
|
||||||
{
|
|
||||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
|
||||||
Platform: core.PlatFormIos,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
Tokens: []string{androidToken, "bbbbb"},
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 1, count)
|
|
||||||
assert.Equal(t, 0, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncModeForNotifications(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Ios.Enabled = true
|
|
||||||
PushConf.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
|
||||||
err := InitAPNSClient()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
|
|
||||||
// enable sync mode
|
|
||||||
PushConf.Core.Sync = true
|
|
||||||
|
|
||||||
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// ios
|
|
||||||
{
|
|
||||||
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
|
||||||
Platform: core.PlatFormIos,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
Tokens: []string{androidToken, "bbbbb"},
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "Welcome",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 3, count)
|
|
||||||
assert.Equal(t, 2, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncModeForTopicNotification(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
PushConf.Log.HideToken = false
|
|
||||||
|
|
||||||
// enable sync mode
|
|
||||||
PushConf.Core.Sync = true
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
// error:InvalidParameters
|
|
||||||
// Check that the provided parameters have the right name and type.
|
|
||||||
To: "/topics/foo-bar@@@##",
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
// success
|
|
||||||
To: "/topics/foo-bar",
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
|
||||||
},
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
// success
|
|
||||||
Condition: "'dogs' in topics || 'cats' in topics",
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 2, count)
|
|
||||||
assert.Equal(t, 1, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncModeForDeviceGroupNotification(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
PushConf, _ = config.LoadConf("")
|
|
||||||
|
|
||||||
PushConf.Android.Enabled = true
|
|
||||||
PushConf.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
|
||||||
PushConf.Log.HideToken = false
|
|
||||||
|
|
||||||
// enable sync mode
|
|
||||||
PushConf.Core.Sync = true
|
|
||||||
|
|
||||||
req := RequestPush{
|
|
||||||
Notifications: []PushNotification{
|
|
||||||
// android
|
|
||||||
{
|
|
||||||
To: "aUniqueKey",
|
|
||||||
Platform: core.PlatFormAndroid,
|
|
||||||
Message: "This is a Firebase Cloud Messaging Device Group Message!",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
count, logs := HandleNotification(ctx, req)
|
|
||||||
assert.Equal(t, 1, count)
|
|
||||||
assert.Equal(t, 1, len(logs))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetProxyURL(t *testing.T) {
|
func TestSetProxyURL(t *testing.T) {
|
||||||
err := SetProxy("87.236.233.92:8080")
|
err := SetProxy("87.236.233.92:8080")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
124
gorush/worker.go
124
gorush/worker.go
|
@ -1,124 +0,0 @@
|
||||||
package gorush
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/appleboy/gorush/core"
|
|
||||||
"github.com/appleboy/gorush/logx"
|
|
||||||
"github.com/appleboy/gorush/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// InitWorkers for initialize all workers.
|
|
||||||
func InitWorkers(ctx context.Context, wg *sync.WaitGroup, workerNum, queueNum int64) {
|
|
||||||
logx.LogAccess.Info("worker number is ", workerNum, ", queue number is ", queueNum)
|
|
||||||
QueueNotification = make(chan PushNotification, queueNum)
|
|
||||||
for i := int64(0); i < workerNum; i++ {
|
|
||||||
go startWorker(ctx, wg, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendNotification is send message to iOS, Android or Huawei
|
|
||||||
func SendNotification(ctx context.Context, req PushNotification) {
|
|
||||||
if PushConf.Core.Sync {
|
|
||||||
defer req.WaitDone()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch req.Platform {
|
|
||||||
case core.PlatFormIos:
|
|
||||||
PushToIOS(req)
|
|
||||||
case core.PlatFormAndroid:
|
|
||||||
PushToAndroid(req)
|
|
||||||
case core.PlatFormHuawei:
|
|
||||||
PushToHuawei(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startWorker(ctx context.Context, wg *sync.WaitGroup, num int64) {
|
|
||||||
defer wg.Done()
|
|
||||||
for notification := range QueueNotification {
|
|
||||||
SendNotification(ctx, notification)
|
|
||||||
}
|
|
||||||
logx.LogAccess.Info("closed the worker num ", num)
|
|
||||||
}
|
|
||||||
|
|
||||||
// markFailedNotification adds failure logs for all tokens in push notification
|
|
||||||
func markFailedNotification(notification *PushNotification, reason string) {
|
|
||||||
logx.LogError.Error(reason)
|
|
||||||
for _, token := range notification.Tokens {
|
|
||||||
notification.AddLog(logx.GetLogPushEntry(&logx.InputLog{
|
|
||||||
ID: notification.ID,
|
|
||||||
Status: core.FailedPush,
|
|
||||||
Token: token,
|
|
||||||
Message: notification.Message,
|
|
||||||
Platform: notification.Platform,
|
|
||||||
Error: errors.New(reason),
|
|
||||||
HideToken: PushConf.Log.HideToken,
|
|
||||||
Format: PushConf.Log.Format,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
notification.WaitDone()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleNotification add notification to queue list.
|
|
||||||
func HandleNotification(ctx context.Context, req RequestPush) (int, []logx.LogPushEntry) {
|
|
||||||
var count int
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
newNotification := []*PushNotification{}
|
|
||||||
for i := range req.Notifications {
|
|
||||||
notification := &req.Notifications[i]
|
|
||||||
switch notification.Platform {
|
|
||||||
case core.PlatFormIos:
|
|
||||||
if !PushConf.Ios.Enabled {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case core.PlatFormAndroid:
|
|
||||||
if !PushConf.Android.Enabled {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case core.PlatFormHuawei:
|
|
||||||
if !PushConf.Huawei.Enabled {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newNotification = append(newNotification, notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
log := make([]logx.LogPushEntry, 0, count)
|
|
||||||
for _, notification := range newNotification {
|
|
||||||
if PushConf.Core.Sync {
|
|
||||||
notification.wg = &wg
|
|
||||||
notification.log = &log
|
|
||||||
notification.AddWaitCount()
|
|
||||||
}
|
|
||||||
if !tryEnqueue(*notification, QueueNotification) {
|
|
||||||
markFailedNotification(notification, "max capacity reached")
|
|
||||||
}
|
|
||||||
count += len(notification.Tokens)
|
|
||||||
// Count topic message
|
|
||||||
if notification.To != "" {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if PushConf.Core.Sync {
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
status.StatStorage.AddTotalCount(int64(count))
|
|
||||||
|
|
||||||
return count, log
|
|
||||||
}
|
|
||||||
|
|
||||||
// tryEnqueue tries to enqueue a job to the given job channel. Returns true if
|
|
||||||
// the operation was successful, and false if enqueuing would not have been
|
|
||||||
// possible without blocking. Job is not enqueued in the latter case.
|
|
||||||
func tryEnqueue(job PushNotification, jobChan chan<- PushNotification) bool {
|
|
||||||
select {
|
|
||||||
case jobChan <- job:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package gorush
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTryEnqueue(t *testing.T) {
|
|
||||||
chn := make(chan PushNotification, 2)
|
|
||||||
assert.True(t, tryEnqueue(PushNotification{}, chn))
|
|
||||||
assert.Equal(t, 1, len(chn))
|
|
||||||
assert.True(t, tryEnqueue(PushNotification{}, chn))
|
|
||||||
assert.Equal(t, 2, len(chn))
|
|
||||||
assert.False(t, tryEnqueue(PushNotification{}, chn))
|
|
||||||
assert.Equal(t, 2, len(chn))
|
|
||||||
}
|
|
|
@ -38,75 +38,75 @@ func TestSetLogOut(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitDefaultLog(t *testing.T) {
|
func TestInitDefaultLog(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
// no errors on default config
|
// no errors on default config
|
||||||
assert.Nil(t, InitLog(
|
assert.Nil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
|
|
||||||
PushConf.Log.AccessLevel = "invalid"
|
cfg.Log.AccessLevel = "invalid"
|
||||||
|
|
||||||
assert.NotNil(t, InitLog(
|
assert.NotNil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessLevel(t *testing.T) {
|
func TestAccessLevel(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Log.AccessLevel = "invalid"
|
cfg.Log.AccessLevel = "invalid"
|
||||||
|
|
||||||
assert.NotNil(t, InitLog(
|
assert.NotNil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorLevel(t *testing.T) {
|
func TestErrorLevel(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Log.ErrorLevel = "invalid"
|
cfg.Log.ErrorLevel = "invalid"
|
||||||
|
|
||||||
assert.NotNil(t, InitLog(
|
assert.NotNil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessLogPath(t *testing.T) {
|
func TestAccessLogPath(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Log.AccessLog = "logs/access.log"
|
cfg.Log.AccessLog = "logs/access.log"
|
||||||
|
|
||||||
assert.NotNil(t, InitLog(
|
assert.NotNil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorLogPath(t *testing.T) {
|
func TestErrorLogPath(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
PushConf.Log.ErrorLog = "logs/error.log"
|
cfg.Log.ErrorLog = "logs/error.log"
|
||||||
|
|
||||||
assert.NotNil(t, InitLog(
|
assert.NotNil(t, InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
127
main.go
127
main.go
|
@ -11,7 +11,6 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -19,6 +18,7 @@ import (
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
"github.com/appleboy/gorush/router"
|
"github.com/appleboy/gorush/router"
|
||||||
"github.com/appleboy/gorush/rpc"
|
"github.com/appleboy/gorush/rpc"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
@ -105,10 +105,8 @@ func main() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// set default parameters.
|
// set default parameters.
|
||||||
gorush.PushConf, err = config.LoadConf(configFile)
|
cfg, err := config.LoadConf(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Load yaml config file error: '%v'", err)
|
log.Printf("Load yaml config file error: '%v'", err)
|
||||||
|
|
||||||
|
@ -116,67 +114,67 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize push slots for concurrent iOS pushes
|
// Initialize push slots for concurrent iOS pushes
|
||||||
gorush.MaxConcurrentIOSPushes = make(chan struct{}, gorush.PushConf.Ios.MaxConcurrentPushes)
|
gorush.MaxConcurrentIOSPushes = make(chan struct{}, cfg.Ios.MaxConcurrentPushes)
|
||||||
|
|
||||||
if opts.Ios.KeyPath != "" {
|
if opts.Ios.KeyPath != "" {
|
||||||
gorush.PushConf.Ios.KeyPath = opts.Ios.KeyPath
|
cfg.Ios.KeyPath = opts.Ios.KeyPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Ios.KeyID != "" {
|
if opts.Ios.KeyID != "" {
|
||||||
gorush.PushConf.Ios.KeyID = opts.Ios.KeyID
|
cfg.Ios.KeyID = opts.Ios.KeyID
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Ios.TeamID != "" {
|
if opts.Ios.TeamID != "" {
|
||||||
gorush.PushConf.Ios.TeamID = opts.Ios.TeamID
|
cfg.Ios.TeamID = opts.Ios.TeamID
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Ios.Password != "" {
|
if opts.Ios.Password != "" {
|
||||||
gorush.PushConf.Ios.Password = opts.Ios.Password
|
cfg.Ios.Password = opts.Ios.Password
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Android.APIKey != "" {
|
if opts.Android.APIKey != "" {
|
||||||
gorush.PushConf.Android.APIKey = opts.Android.APIKey
|
cfg.Android.APIKey = opts.Android.APIKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Huawei.AppSecret != "" {
|
if opts.Huawei.AppSecret != "" {
|
||||||
gorush.PushConf.Huawei.AppSecret = opts.Huawei.AppSecret
|
cfg.Huawei.AppSecret = opts.Huawei.AppSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Huawei.AppID != "" {
|
if opts.Huawei.AppID != "" {
|
||||||
gorush.PushConf.Huawei.AppID = opts.Huawei.AppID
|
cfg.Huawei.AppID = opts.Huawei.AppID
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Stat.Engine != "" {
|
if opts.Stat.Engine != "" {
|
||||||
gorush.PushConf.Stat.Engine = opts.Stat.Engine
|
cfg.Stat.Engine = opts.Stat.Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Stat.Redis.Addr != "" {
|
if opts.Stat.Redis.Addr != "" {
|
||||||
gorush.PushConf.Stat.Redis.Addr = opts.Stat.Redis.Addr
|
cfg.Stat.Redis.Addr = opts.Stat.Redis.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite server port and address
|
// overwrite server port and address
|
||||||
if opts.Core.Port != "" {
|
if opts.Core.Port != "" {
|
||||||
gorush.PushConf.Core.Port = opts.Core.Port
|
cfg.Core.Port = opts.Core.Port
|
||||||
}
|
}
|
||||||
if opts.Core.Address != "" {
|
if opts.Core.Address != "" {
|
||||||
gorush.PushConf.Core.Address = opts.Core.Address
|
cfg.Core.Address = opts.Core.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = logx.InitLog(
|
if err = logx.InitLog(
|
||||||
gorush.PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
gorush.PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
gorush.PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
gorush.PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatalf("Can't load log module, error: %v", err)
|
log.Fatalf("Can't load log module, error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Core.HTTPProxy != "" {
|
if opts.Core.HTTPProxy != "" {
|
||||||
gorush.PushConf.Core.HTTPProxy = opts.Core.HTTPProxy
|
cfg.Core.HTTPProxy = opts.Core.HTTPProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
if gorush.PushConf.Core.HTTPProxy != "" {
|
if cfg.Core.HTTPProxy != "" {
|
||||||
err = gorush.SetProxy(gorush.PushConf.Core.HTTPProxy)
|
err = gorush.SetProxy(cfg.Core.HTTPProxy)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.LogError.Fatalf("Set Proxy error: %v", err)
|
logx.LogError.Fatalf("Set Proxy error: %v", err)
|
||||||
|
@ -184,7 +182,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ping {
|
if ping {
|
||||||
if err := pinger(); err != nil {
|
if err := pinger(cfg); err != nil {
|
||||||
logx.LogError.Warnf("ping server error: %v", err)
|
logx.LogError.Warnf("ping server error: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -192,7 +190,7 @@ func main() {
|
||||||
|
|
||||||
// send android notification
|
// send android notification
|
||||||
if opts.Android.Enabled {
|
if opts.Android.Enabled {
|
||||||
gorush.PushConf.Android.Enabled = opts.Android.Enabled
|
cfg.Android.Enabled = opts.Android.Enabled
|
||||||
req := gorush.PushNotification{
|
req := gorush.PushNotification{
|
||||||
Platform: core.PlatFormAndroid,
|
Platform: core.PlatFormAndroid,
|
||||||
Message: message,
|
Message: message,
|
||||||
|
@ -214,18 +212,18 @@ func main() {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
if err := status.InitAppStatus(cfg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gorush.PushToAndroid(req)
|
gorush.PushToAndroid(cfg, req)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// send huawei notification
|
// send huawei notification
|
||||||
if opts.Huawei.Enabled {
|
if opts.Huawei.Enabled {
|
||||||
gorush.PushConf.Huawei.Enabled = opts.Huawei.Enabled
|
cfg.Huawei.Enabled = opts.Huawei.Enabled
|
||||||
req := gorush.PushNotification{
|
req := gorush.PushNotification{
|
||||||
Platform: core.PlatFormHuawei,
|
Platform: core.PlatFormHuawei,
|
||||||
Message: message,
|
Message: message,
|
||||||
|
@ -247,11 +245,11 @@ func main() {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
if err := status.InitAppStatus(cfg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gorush.PushToHuawei(req)
|
gorush.PushToHuawei(cfg, req)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -259,10 +257,10 @@ func main() {
|
||||||
// send ios notification
|
// send ios notification
|
||||||
if opts.Ios.Enabled {
|
if opts.Ios.Enabled {
|
||||||
if opts.Ios.Production {
|
if opts.Ios.Production {
|
||||||
gorush.PushConf.Ios.Production = opts.Ios.Production
|
cfg.Ios.Production = opts.Ios.Production
|
||||||
}
|
}
|
||||||
|
|
||||||
gorush.PushConf.Ios.Enabled = opts.Ios.Enabled
|
cfg.Ios.Enabled = opts.Ios.Enabled
|
||||||
req := gorush.PushNotification{
|
req := gorush.PushNotification{
|
||||||
Platform: core.PlatFormIos,
|
Platform: core.PlatFormIos,
|
||||||
Message: message,
|
Message: message,
|
||||||
|
@ -284,68 +282,71 @@ func main() {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := status.InitAppStatus(gorush.PushConf); err != nil {
|
if err := status.InitAppStatus(cfg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gorush.InitAPNSClient(); err != nil {
|
if err := gorush.InitAPNSClient(cfg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gorush.PushToIOS(req)
|
gorush.PushToIOS(cfg, req)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = gorush.CheckPushConf(); err != nil {
|
if err = gorush.CheckPushConf(cfg); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Core.PID.Path != "" {
|
if opts.Core.PID.Path != "" {
|
||||||
gorush.PushConf.Core.PID.Path = opts.Core.PID.Path
|
cfg.Core.PID.Path = opts.Core.PID.Path
|
||||||
gorush.PushConf.Core.PID.Enabled = true
|
cfg.Core.PID.Enabled = true
|
||||||
gorush.PushConf.Core.PID.Override = true
|
cfg.Core.PID.Override = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = createPIDFile(); err != nil {
|
if err = createPIDFile(cfg); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = status.InitAppStatus(gorush.PushConf); err != nil {
|
if err = status.InitAppStatus(cfg); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q := queue.NewQueue(cfg)
|
||||||
|
q.Start()
|
||||||
|
|
||||||
finished := make(chan struct{})
|
finished := make(chan struct{})
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
wg.Add(int(gorush.PushConf.Core.WorkerNum))
|
|
||||||
ctx := withContextFunc(context.Background(), func() {
|
ctx := withContextFunc(context.Background(), func() {
|
||||||
logx.LogAccess.Info("close the notification queue channel, current queue len: ", len(gorush.QueueNotification))
|
logx.LogAccess.Info("close the queue system, current queue usage: ", q.Usage())
|
||||||
close(gorush.QueueNotification)
|
// stop queue system
|
||||||
wg.Wait()
|
q.Stop()
|
||||||
logx.LogAccess.Info("the notification queue has been clear")
|
// wait job completed
|
||||||
|
q.Wait()
|
||||||
close(finished)
|
close(finished)
|
||||||
// close the connection with storage
|
// close the connection with storage
|
||||||
logx.LogAccess.Info("close the storage connection: ", gorush.PushConf.Stat.Engine)
|
logx.LogAccess.Info("close the storage connection: ", cfg.Stat.Engine)
|
||||||
if err := status.StatStorage.Close(); err != nil {
|
if err := status.StatStorage.Close(); err != nil {
|
||||||
logx.LogError.Fatal("can't close the storage connection: ", err.Error())
|
logx.LogError.Fatal("can't close the storage connection: ", err.Error())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
gorush.InitWorkers(ctx, wg, gorush.PushConf.Core.WorkerNum, gorush.PushConf.Core.QueueNum)
|
// gorush.InitQueue(cfg.Core.WorkerNum, cfg.Core.QueueNum)
|
||||||
|
// gorush.InitWorkers(ctx, wg, cfg.Core.WorkerNum, cfg.Core.QueueNum)
|
||||||
|
|
||||||
if gorush.PushConf.Ios.Enabled {
|
if cfg.Ios.Enabled {
|
||||||
if err = gorush.InitAPNSClient(); err != nil {
|
if err = gorush.InitAPNSClient(cfg); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gorush.PushConf.Android.Enabled {
|
if cfg.Android.Enabled {
|
||||||
if _, err = gorush.InitFCMClient(gorush.PushConf.Android.APIKey); err != nil {
|
if _, err = gorush.InitFCMClient(cfg, cfg.Android.APIKey); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gorush.PushConf.Huawei.Enabled {
|
if cfg.Huawei.Enabled {
|
||||||
if _, err = gorush.InitHMSClient(gorush.PushConf.Huawei.AppSecret, gorush.PushConf.Huawei.AppID); err != nil {
|
if _, err = gorush.InitHMSClient(cfg, cfg.Huawei.AppSecret, cfg.Huawei.AppID); err != nil {
|
||||||
logx.LogError.Fatal(err)
|
logx.LogError.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,12 +355,12 @@ func main() {
|
||||||
|
|
||||||
// Run httpd server
|
// Run httpd server
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return router.RunHTTPServer(ctx, gorush.PushConf)
|
return router.RunHTTPServer(ctx, cfg, q)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Run gRPC internal server
|
// Run gRPC internal server
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return rpc.RunGRPCServer(ctx)
|
return rpc.RunGRPCServer(ctx, cfg)
|
||||||
})
|
})
|
||||||
|
|
||||||
// check job completely
|
// check job completely
|
||||||
|
@ -426,7 +427,7 @@ func usage() {
|
||||||
|
|
||||||
// handles pinging the endpoint and returns an error if the
|
// handles pinging the endpoint and returns an error if the
|
||||||
// agent is in an unhealthy state.
|
// agent is in an unhealthy state.
|
||||||
func pinger() error {
|
func pinger(cfg config.ConfYaml) error {
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
Dial: (&net.Dialer{
|
Dial: (&net.Dialer{
|
||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
|
@ -437,7 +438,7 @@ func pinger() error {
|
||||||
Timeout: time.Second * 10,
|
Timeout: time.Second * 10,
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
}
|
}
|
||||||
resp, err := client.Get("http://localhost:" + gorush.PushConf.Core.Port + gorush.PushConf.API.HealthURI)
|
resp, err := client.Get("http://localhost:" + cfg.Core.Port + cfg.API.HealthURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -448,14 +449,14 @@ func pinger() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPIDFile() error {
|
func createPIDFile(cfg config.ConfYaml) error {
|
||||||
if !gorush.PushConf.Core.PID.Enabled {
|
if !cfg.Core.PID.Enabled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pidPath := gorush.PushConf.Core.PID.Path
|
pidPath := cfg.Core.PID.Path
|
||||||
_, err := os.Stat(pidPath)
|
_, err := os.Stat(pidPath)
|
||||||
if os.IsNotExist(err) || gorush.PushConf.Core.PID.Override {
|
if os.IsNotExist(err) || cfg.Core.PID.Override {
|
||||||
currentPid := os.Getpid()
|
currentPid := os.Getpid()
|
||||||
if err := os.MkdirAll(filepath.Dir(pidPath), os.ModePerm); err != nil {
|
if err := os.MkdirAll(filepath.Dir(pidPath), os.ModePerm); err != nil {
|
||||||
return fmt.Errorf("Can't create PID folder on %v", err)
|
return fmt.Errorf("Can't create PID folder on %v", err)
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
package queue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
|
"github.com/appleboy/gorush/logx"
|
||||||
|
"github.com/appleboy/gorush/queue/simple"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// A Queue is a message queue.
|
||||||
|
Queue struct {
|
||||||
|
workerCount int
|
||||||
|
queueCount int
|
||||||
|
routineGroup *routineGroup
|
||||||
|
quit chan struct{}
|
||||||
|
worker Worker
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewQueue returns a Queue.
|
||||||
|
func NewQueue(cfg config.ConfYaml) *Queue {
|
||||||
|
q := &Queue{
|
||||||
|
workerCount: int(cfg.Core.WorkerNum),
|
||||||
|
queueCount: int(cfg.Core.QueueNum),
|
||||||
|
routineGroup: newRoutineGroup(),
|
||||||
|
quit: make(chan struct{}),
|
||||||
|
worker: simple.NewWorker(cfg),
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.workerCount != 0 {
|
||||||
|
q.workerCount = runtime.NumCPU()
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.queueCount == 0 {
|
||||||
|
q.queueCount = runtime.NumCPU() << 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capacity for queue max size
|
||||||
|
func (q *Queue) Capacity() int {
|
||||||
|
return q.worker.Capacity()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage for count of queue usage
|
||||||
|
func (q *Queue) Usage() int {
|
||||||
|
return q.worker.Usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config update current config
|
||||||
|
func (q *Queue) Config(cfg config.ConfYaml) {
|
||||||
|
q.worker.Config(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start to enable all worker
|
||||||
|
func (q *Queue) Start() {
|
||||||
|
q.startWorker()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops q.
|
||||||
|
func (q *Queue) Stop() {
|
||||||
|
q.worker.Stop()
|
||||||
|
close(q.quit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait all process
|
||||||
|
func (q *Queue) Wait() {
|
||||||
|
q.routineGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enqueue queue all job
|
||||||
|
func (q *Queue) Enqueue(job interface{}) error {
|
||||||
|
return q.worker.Enqueue(job)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) startWorker() {
|
||||||
|
for i := 0; i < q.workerCount; i++ {
|
||||||
|
go func(num int) {
|
||||||
|
q.routineGroup.Run(func() {
|
||||||
|
logx.LogAccess.Info("started the worker num ", num)
|
||||||
|
q.worker.Run(q.quit)
|
||||||
|
logx.LogAccess.Info("closed the worker num ", num)
|
||||||
|
})
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package simple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
|
"github.com/appleboy/gorush/gorush"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Worker for simple queue using channel
|
||||||
|
type Worker struct {
|
||||||
|
cfg config.ConfYaml
|
||||||
|
queueNotification chan gorush.PushNotification
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run start the worker
|
||||||
|
func (s *Worker) Run(_ chan struct{}) {
|
||||||
|
for notification := range s.queueNotification {
|
||||||
|
gorush.SendNotification(s.cfg, notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop worker
|
||||||
|
func (s *Worker) Stop() {
|
||||||
|
close(s.queueNotification)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capacity for channel
|
||||||
|
func (s *Worker) Capacity() int {
|
||||||
|
return cap(s.queueNotification)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage for count of channel usage
|
||||||
|
func (s *Worker) Usage() int {
|
||||||
|
return len(s.queueNotification)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enqueue send notification to queue
|
||||||
|
func (s *Worker) Enqueue(job interface{}) error {
|
||||||
|
select {
|
||||||
|
case s.queueNotification <- job.(gorush.PushNotification):
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.New("max capacity reached")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config update current config
|
||||||
|
func (s *Worker) Config(cfg config.ConfYaml) {
|
||||||
|
s.cfg = cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWorker for struct
|
||||||
|
func NewWorker(cfg config.ConfYaml) *Worker {
|
||||||
|
return &Worker{
|
||||||
|
cfg: cfg,
|
||||||
|
queueNotification: make(chan gorush.PushNotification, cfg.Core.QueueNum),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package queue
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type routineGroup struct {
|
||||||
|
waitGroup sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoutineGroup() *routineGroup {
|
||||||
|
return new(routineGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *routineGroup) Run(fn func()) {
|
||||||
|
g.waitGroup.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer g.waitGroup.Done()
|
||||||
|
fn()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *routineGroup) Wait() {
|
||||||
|
g.waitGroup.Wait()
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package queue
|
||||||
|
|
||||||
|
import "github.com/appleboy/gorush/config"
|
||||||
|
|
||||||
|
// Worker interface
|
||||||
|
type Worker interface {
|
||||||
|
Run(chan struct{})
|
||||||
|
Stop()
|
||||||
|
Enqueue(job interface{}) error
|
||||||
|
Capacity() int
|
||||||
|
Usage() int
|
||||||
|
Config(config.ConfYaml)
|
||||||
|
}
|
114
router/server.go
114
router/server.go
|
@ -3,14 +3,18 @@ package router
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
"github.com/appleboy/gorush/metric"
|
"github.com/appleboy/gorush/metric"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
|
||||||
api "github.com/appleboy/gin-status-api"
|
api "github.com/appleboy/gin-status-api"
|
||||||
|
@ -26,14 +30,12 @@ import (
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var isTerm bool
|
var (
|
||||||
|
isTerm bool
|
||||||
|
doOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Support metrics
|
|
||||||
m := metric.NewMetrics(func() int {
|
|
||||||
return len(gorush.QueueNotification)
|
|
||||||
})
|
|
||||||
prometheus.MustRegister(m)
|
|
||||||
isTerm = isatty.IsTerminal(os.Stdout.Fd())
|
isTerm = isatty.IsTerminal(os.Stdout.Fd())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ func versionHandler(c *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushHandler(cfg config.ConfYaml) gin.HandlerFunc {
|
func pushHandler(cfg config.ConfYaml, q *queue.Queue) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
var form gorush.RequestPush
|
var form gorush.RequestPush
|
||||||
var msg string
|
var msg string
|
||||||
|
@ -101,7 +103,7 @@ func pushHandler(cfg config.ConfYaml) gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
counts, logs := gorush.HandleNotification(ctx, form)
|
counts, logs := handleNotification(ctx, cfg, form, q)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": "ok",
|
"success": "ok",
|
||||||
|
@ -121,12 +123,13 @@ func metricsHandler(c *gin.Context) {
|
||||||
promhttp.Handler().ServeHTTP(c.Writer, c.Request)
|
promhttp.Handler().ServeHTTP(c.Writer, c.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func appStatusHandler(c *gin.Context) {
|
func appStatusHandler(q *queue.Queue) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
result := status.App{}
|
result := status.App{}
|
||||||
|
|
||||||
result.Version = GetVersion()
|
result.Version = GetVersion()
|
||||||
result.QueueMax = cap(gorush.QueueNotification)
|
result.QueueMax = q.Capacity()
|
||||||
result.QueueUsage = len(gorush.QueueNotification)
|
result.QueueUsage = q.Usage()
|
||||||
result.TotalCount = status.StatStorage.GetTotalCount()
|
result.TotalCount = status.StatStorage.GetTotalCount()
|
||||||
result.Ios.PushSuccess = status.StatStorage.GetIosSuccess()
|
result.Ios.PushSuccess = status.StatStorage.GetIosSuccess()
|
||||||
result.Ios.PushError = status.StatStorage.GetIosError()
|
result.Ios.PushError = status.StatStorage.GetIosError()
|
||||||
|
@ -136,6 +139,7 @@ func appStatusHandler(c *gin.Context) {
|
||||||
result.Huawei.PushError = status.StatStorage.GetHuaweiError()
|
result.Huawei.PushError = status.StatStorage.GetHuaweiError()
|
||||||
|
|
||||||
c.JSON(http.StatusOK, result)
|
c.JSON(http.StatusOK, result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sysStatsHandler() gin.HandlerFunc {
|
func sysStatsHandler() gin.HandlerFunc {
|
||||||
|
@ -153,7 +157,7 @@ func StatMiddleware() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoTLSServer(cfg config.ConfYaml) *http.Server {
|
func autoTLSServer(cfg config.ConfYaml, q *queue.Queue) *http.Server {
|
||||||
m := autocert.Manager{
|
m := autocert.Manager{
|
||||||
Prompt: autocert.AcceptTOS,
|
Prompt: autocert.AcceptTOS,
|
||||||
HostPolicy: autocert.HostWhitelist(cfg.Core.AutoTLS.Host),
|
HostPolicy: autocert.HostWhitelist(cfg.Core.AutoTLS.Host),
|
||||||
|
@ -163,11 +167,11 @@ func autoTLSServer(cfg config.ConfYaml) *http.Server {
|
||||||
return &http.Server{
|
return &http.Server{
|
||||||
Addr: ":https",
|
Addr: ":https",
|
||||||
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
||||||
Handler: routerEngine(cfg),
|
Handler: routerEngine(cfg, q),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
func routerEngine(cfg config.ConfYaml, q *queue.Queue) *gin.Engine {
|
||||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||||
if cfg.Core.Mode == "debug" {
|
if cfg.Core.Mode == "debug" {
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||||
|
@ -184,6 +188,14 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support metrics
|
||||||
|
doOnce.Do(func() {
|
||||||
|
m := metric.NewMetrics(func() int {
|
||||||
|
return q.Usage()
|
||||||
|
})
|
||||||
|
prometheus.MustRegister(m)
|
||||||
|
})
|
||||||
|
|
||||||
// set server mode
|
// set server mode
|
||||||
gin.SetMode(cfg.Core.Mode)
|
gin.SetMode(cfg.Core.Mode)
|
||||||
|
|
||||||
|
@ -202,10 +214,10 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
||||||
r.Use(StatMiddleware())
|
r.Use(StatMiddleware())
|
||||||
|
|
||||||
r.GET(cfg.API.StatGoURI, api.GinHandler)
|
r.GET(cfg.API.StatGoURI, api.GinHandler)
|
||||||
r.GET(cfg.API.StatAppURI, appStatusHandler)
|
r.GET(cfg.API.StatAppURI, appStatusHandler(q))
|
||||||
r.GET(cfg.API.ConfigURI, configHandler(cfg))
|
r.GET(cfg.API.ConfigURI, configHandler(cfg))
|
||||||
r.GET(cfg.API.SysStatURI, sysStatsHandler())
|
r.GET(cfg.API.SysStatURI, sysStatsHandler())
|
||||||
r.POST(cfg.API.PushURI, pushHandler(cfg))
|
r.POST(cfg.API.PushURI, pushHandler(cfg, q))
|
||||||
r.GET(cfg.API.MetricURI, metricsHandler)
|
r.GET(cfg.API.MetricURI, metricsHandler)
|
||||||
r.GET(cfg.API.HealthURI, heartbeatHandler)
|
r.GET(cfg.API.HealthURI, heartbeatHandler)
|
||||||
r.HEAD(cfg.API.HealthURI, heartbeatHandler)
|
r.HEAD(cfg.API.HealthURI, heartbeatHandler)
|
||||||
|
@ -214,3 +226,73 @@ func routerEngine(cfg config.ConfYaml) *gin.Engine {
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// markFailedNotification adds failure logs for all tokens in push notification
|
||||||
|
func markFailedNotification(cfg config.ConfYaml, notification *gorush.PushNotification, reason string) {
|
||||||
|
logx.LogError.Error(reason)
|
||||||
|
for _, token := range notification.Tokens {
|
||||||
|
notification.AddLog(logx.GetLogPushEntry(&logx.InputLog{
|
||||||
|
ID: notification.ID,
|
||||||
|
Status: core.FailedPush,
|
||||||
|
Token: token,
|
||||||
|
Message: notification.Message,
|
||||||
|
Platform: notification.Platform,
|
||||||
|
Error: errors.New(reason),
|
||||||
|
HideToken: cfg.Log.HideToken,
|
||||||
|
Format: cfg.Log.Format,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
notification.WaitDone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleNotification add notification to queue list.
|
||||||
|
func handleNotification(ctx context.Context, cfg config.ConfYaml, req gorush.RequestPush, q *queue.Queue) (int, []logx.LogPushEntry) {
|
||||||
|
var count int
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
newNotification := []*gorush.PushNotification{}
|
||||||
|
for i := range req.Notifications {
|
||||||
|
notification := &req.Notifications[i]
|
||||||
|
switch notification.Platform {
|
||||||
|
case core.PlatFormIos:
|
||||||
|
if !cfg.Ios.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case core.PlatFormAndroid:
|
||||||
|
if !cfg.Android.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case core.PlatFormHuawei:
|
||||||
|
if !cfg.Huawei.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newNotification = append(newNotification, notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
log := make([]logx.LogPushEntry, 0, count)
|
||||||
|
for _, notification := range newNotification {
|
||||||
|
if cfg.Core.Sync {
|
||||||
|
notification.Wg = &wg
|
||||||
|
notification.Log = &log
|
||||||
|
notification.AddWaitCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.Enqueue(*notification); err != nil {
|
||||||
|
markFailedNotification(cfg, notification, "max capacity reached")
|
||||||
|
}
|
||||||
|
|
||||||
|
count += len(notification.Tokens)
|
||||||
|
// Count topic message
|
||||||
|
if notification.To != "" {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Core.Sync {
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
status.StatStorage.AddTotalCount(int64(count))
|
||||||
|
|
||||||
|
return count, log
|
||||||
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ import (
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
|
|
||||||
"github.com/apex/gateway"
|
"github.com/apex/gateway"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunHTTPServer provide run http or https protocol.
|
// RunHTTPServer provide run http or https protocol.
|
||||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server) (err error) {
|
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, q *queue.Queue, s ...*http.Server) (err error) {
|
||||||
if !cfg.Core.Enabled {
|
if !cfg.Core.Enabled {
|
||||||
logx.LogAccess.Debug("httpd server is disabled.")
|
logx.LogAccess.Debug("httpd server is disabled.")
|
||||||
return nil
|
return nil
|
||||||
|
@ -21,5 +22,5 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
||||||
|
|
||||||
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
||||||
|
|
||||||
return gateway.ListenAndServe(cfg.Core.Address+":"+cfg.Core.Port, routerEngine(cfg))
|
return gateway.ListenAndServe(cfg.Core.Address+":"+cfg.Core.Port, routerEngine(cfg, q))
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,13 @@ import (
|
||||||
|
|
||||||
"github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunHTTPServer provide run http or https protocol.
|
// RunHTTPServer provide run http or https protocol.
|
||||||
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server) (err error) {
|
func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, q *queue.Queue, s ...*http.Server) (err error) {
|
||||||
var server *http.Server
|
var server *http.Server
|
||||||
|
|
||||||
if !cfg.Core.Enabled {
|
if !cfg.Core.Enabled {
|
||||||
|
@ -28,7 +29,7 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
server = &http.Server{
|
server = &http.Server{
|
||||||
Addr: cfg.Core.Address + ":" + cfg.Core.Port,
|
Addr: cfg.Core.Address + ":" + cfg.Core.Port,
|
||||||
Handler: routerEngine(cfg),
|
Handler: routerEngine(cfg, q),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
server = s[0]
|
server = s[0]
|
||||||
|
@ -36,7 +37,7 @@ func RunHTTPServer(ctx context.Context, cfg config.ConfYaml, s ...*http.Server)
|
||||||
|
|
||||||
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
logx.LogAccess.Info("HTTPD server is running on " + cfg.Core.Port + " port.")
|
||||||
if cfg.Core.AutoTLS.Enabled {
|
if cfg.Core.AutoTLS.Enabled {
|
||||||
return startServer(ctx, autoTLSServer(cfg), cfg)
|
return startServer(ctx, autoTLSServer(cfg, q), cfg)
|
||||||
} else if cfg.Core.SSL {
|
} else if cfg.Core.SSL {
|
||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
MinVersion: tls.VersionTLS10,
|
MinVersion: tls.VersionTLS10,
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
"github.com/appleboy/gorush/queue"
|
||||||
"github.com/appleboy/gorush/status"
|
"github.com/appleboy/gorush/status"
|
||||||
|
|
||||||
"github.com/appleboy/gofight/v2"
|
"github.com/appleboy/gofight/v2"
|
||||||
|
@ -23,7 +24,10 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var goVersion = runtime.Version()
|
var (
|
||||||
|
goVersion = runtime.Version()
|
||||||
|
q *queue.Queue
|
||||||
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
cfg := initTest()
|
cfg := initTest()
|
||||||
|
@ -40,11 +44,14 @@ func TestMain(m *testing.M) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q = queue.NewQueue(cfg)
|
||||||
|
q.Start()
|
||||||
|
defer q.Stop()
|
||||||
m.Run()
|
m.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTest() config.ConfYaml {
|
func initTest() config.ConfYaml {
|
||||||
cfg, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
cfg.Core.Mode = "test"
|
cfg.Core.Mode = "test"
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
@ -88,7 +95,7 @@ func TestRunNormalServer(t *testing.T) {
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -112,7 +119,7 @@ func TestRunTLSServer(t *testing.T) {
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -140,7 +147,7 @@ func TestRunTLSBase64Server(t *testing.T) {
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -159,7 +166,7 @@ func TestRunAutoTLSServer(t *testing.T) {
|
||||||
cfg.Core.AutoTLS.Enabled = true
|
cfg.Core.AutoTLS.Enabled = true
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
assert.NoError(t, RunHTTPServer(ctx, cfg))
|
assert.NoError(t, RunHTTPServer(ctx, cfg, q))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -179,7 +186,7 @@ func TestLoadTLSCertError(t *testing.T) {
|
||||||
cfg.Core.CertPath = "../config/config.yml"
|
cfg.Core.CertPath = "../config/config.yml"
|
||||||
cfg.Core.KeyPath = "../config/config.yml"
|
cfg.Core.KeyPath = "../config/config.yml"
|
||||||
|
|
||||||
assert.Error(t, RunHTTPServer(context.Background(), cfg))
|
assert.Error(t, RunHTTPServer(context.Background(), cfg, q))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingTLSCertcfgg(t *testing.T) {
|
func TestMissingTLSCertcfgg(t *testing.T) {
|
||||||
|
@ -192,8 +199,8 @@ func TestMissingTLSCertcfgg(t *testing.T) {
|
||||||
cfg.Core.CertBase64 = ""
|
cfg.Core.CertBase64 = ""
|
||||||
cfg.Core.KeyBase64 = ""
|
cfg.Core.KeyBase64 = ""
|
||||||
|
|
||||||
err := RunHTTPServer(context.Background(), cfg)
|
err := RunHTTPServer(context.Background(), cfg, q)
|
||||||
assert.Error(t, RunHTTPServer(context.Background(), cfg))
|
assert.Error(t, RunHTTPServer(context.Background(), cfg, q))
|
||||||
assert.Equal(t, "missing https cert config", err.Error())
|
assert.Equal(t, "missing https cert config", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +213,7 @@ func TestRootHandler(t *testing.T) {
|
||||||
cfg.Log.Format = "json"
|
cfg.Log.Format = "json"
|
||||||
|
|
||||||
r.GET("/").
|
r.GET("/").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
data := r.Body.Bytes()
|
data := r.Body.Bytes()
|
||||||
|
|
||||||
value, _ := jsonparser.GetString(data, "text")
|
value, _ := jsonparser.GetString(data, "text")
|
||||||
|
@ -223,7 +230,7 @@ func TestAPIStatusGoHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/api/stat/go").
|
r.GET("/api/stat/go").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
data := r.Body.Bytes()
|
data := r.Body.Bytes()
|
||||||
|
|
||||||
value, _ := jsonparser.GetString(data, "go_version")
|
value, _ := jsonparser.GetString(data, "go_version")
|
||||||
|
@ -242,7 +249,7 @@ func TestAPIStatusAppHandler(t *testing.T) {
|
||||||
SetVersion(appVersion)
|
SetVersion(appVersion)
|
||||||
|
|
||||||
r.GET("/api/stat/app").
|
r.GET("/api/stat/app").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
data := r.Body.Bytes()
|
data := r.Body.Bytes()
|
||||||
|
|
||||||
value, _ := jsonparser.GetString(data, "version")
|
value, _ := jsonparser.GetString(data, "version")
|
||||||
|
@ -258,7 +265,7 @@ func TestAPIConfigHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/api/config").
|
r.GET("/api/config").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusCreated, r.Code)
|
assert.Equal(t, http.StatusCreated, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -270,7 +277,7 @@ func TestMissingNotificationsParameter(t *testing.T) {
|
||||||
|
|
||||||
// missing notifications parameter.
|
// missing notifications parameter.
|
||||||
r.POST("/api/push").
|
r.POST("/api/push").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||||
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
|
||||||
})
|
})
|
||||||
|
@ -286,7 +293,7 @@ func TestEmptyNotifications(t *testing.T) {
|
||||||
SetJSON(gofight.D{
|
SetJSON(gofight.D{
|
||||||
"notifications": []gorush.PushNotification{},
|
"notifications": []gorush.PushNotification{},
|
||||||
}).
|
}).
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -314,8 +321,8 @@ func TestMutableContent(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).
|
}).
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
// json: cannot unmarshal number into Go struct field PushNotification.mutable_content of type bool
|
// json: cannot unmarshal number into Go struct field gorush.PushNotification.mutable_content of type bool
|
||||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -343,7 +350,7 @@ func TestOutOfRangeMaxNotifications(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).
|
}).
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusBadRequest, r.Code)
|
assert.Equal(t, http.StatusBadRequest, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -369,7 +376,7 @@ func TestSuccessPushHandler(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).
|
}).
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -380,7 +387,7 @@ func TestSysStatsHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/sys/stats").
|
r.GET("/sys/stats").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -391,7 +398,7 @@ func TestMetricsHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/metrics").
|
r.GET("/metrics").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -402,7 +409,7 @@ func TestGETHeartbeatHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/healthz").
|
r.GET("/healthz").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -413,7 +420,7 @@ func TestHEADHeartbeatHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.HEAD("/healthz").
|
r.HEAD("/healthz").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -425,7 +432,7 @@ func TestVersionHandler(t *testing.T) {
|
||||||
r := gofight.New()
|
r := gofight.New()
|
||||||
|
|
||||||
r.GET("/version").
|
r.GET("/version").
|
||||||
Run(routerEngine(cfg), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {
|
||||||
assert.Equal(t, http.StatusOK, r.Code)
|
assert.Equal(t, http.StatusOK, r.Code)
|
||||||
data := r.Body.Bytes()
|
data := r.Body.Bytes()
|
||||||
|
|
||||||
|
@ -438,8 +445,231 @@ func TestVersionHandler(t *testing.T) {
|
||||||
func TestDisabledHTTPServer(t *testing.T) {
|
func TestDisabledHTTPServer(t *testing.T) {
|
||||||
cfg := initTest()
|
cfg := initTest()
|
||||||
cfg.Core.Enabled = false
|
cfg.Core.Enabled = false
|
||||||
err := RunHTTPServer(context.Background(), cfg)
|
err := RunHTTPServer(context.Background(), cfg, q)
|
||||||
cfg.Core.Enabled = true
|
cfg.Core.Enabled = true
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSenMultipleNotifications(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Ios.Enabled = true
|
||||||
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
|
err := gorush.InitAPNSClient(cfg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
cfg.Android.Enabled = true
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// ios
|
||||||
|
{
|
||||||
|
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||||
|
Platform: core.PlatFormIos,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
Tokens: []string{androidToken, "bbbbb"},
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 3, count)
|
||||||
|
assert.Equal(t, 0, len(logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisabledAndroidNotifications(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Ios.Enabled = true
|
||||||
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
|
err := gorush.InitAPNSClient(cfg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
cfg.Android.Enabled = false
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// ios
|
||||||
|
{
|
||||||
|
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||||
|
Platform: core.PlatFormIos,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
Tokens: []string{androidToken, "bbbbb"},
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 1, count)
|
||||||
|
assert.Equal(t, 0, len(logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncModeForNotifications(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Ios.Enabled = true
|
||||||
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
|
err := gorush.InitAPNSClient(cfg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
cfg.Android.Enabled = true
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
|
||||||
|
// enable sync mode
|
||||||
|
cfg.Core.Sync = true
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// ios
|
||||||
|
{
|
||||||
|
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||||
|
Platform: core.PlatFormIos,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
Tokens: []string{androidToken, "bbbbb"},
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 3, count)
|
||||||
|
assert.Equal(t, 2, len(logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncModeForTopicNotification(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Android.Enabled = true
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
cfg.Log.HideToken = false
|
||||||
|
|
||||||
|
// enable sync mode
|
||||||
|
cfg.Core.Sync = true
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
// error:InvalidParameters
|
||||||
|
// Check that the provided parameters have the right name and type.
|
||||||
|
To: "/topics/foo-bar@@@##",
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
// success
|
||||||
|
To: "/topics/foo-bar",
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
// success
|
||||||
|
Condition: "'dogs' in topics || 'cats' in topics",
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "This is a Firebase Cloud Messaging Topic Message!",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 2, count)
|
||||||
|
assert.Equal(t, 1, len(logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncModeForDeviceGroupNotification(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Android.Enabled = true
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
cfg.Log.HideToken = false
|
||||||
|
|
||||||
|
// enable sync mode
|
||||||
|
cfg.Core.Sync = true
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
To: "aUniqueKey",
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "This is a Firebase Cloud Messaging Device Group Message!",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 1, count)
|
||||||
|
assert.Equal(t, 1, len(logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisabledIosNotifications(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := initTest()
|
||||||
|
|
||||||
|
cfg.Ios.Enabled = false
|
||||||
|
cfg.Ios.KeyPath = "../certificate/certificate-valid.pem"
|
||||||
|
err := gorush.InitAPNSClient(cfg)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
cfg.Android.Enabled = true
|
||||||
|
cfg.Android.APIKey = os.Getenv("ANDROID_API_KEY")
|
||||||
|
q.Config(cfg)
|
||||||
|
|
||||||
|
androidToken := os.Getenv("ANDROID_TEST_TOKEN")
|
||||||
|
|
||||||
|
req := gorush.RequestPush{
|
||||||
|
Notifications: []gorush.PushNotification{
|
||||||
|
// ios
|
||||||
|
{
|
||||||
|
Tokens: []string{"11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"},
|
||||||
|
Platform: core.PlatFormIos,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
// android
|
||||||
|
{
|
||||||
|
Tokens: []string{androidToken, androidToken + "_"},
|
||||||
|
Platform: core.PlatFormAndroid,
|
||||||
|
Message: "Welcome",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
count, logs := handleNotification(ctx, cfg, req, q)
|
||||||
|
assert.Equal(t, 2, count)
|
||||||
|
assert.Equal(t, 0, len(logs))
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/core"
|
"github.com/appleboy/gorush/core"
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/gorush"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
@ -19,14 +20,16 @@ import (
|
||||||
|
|
||||||
// Server is used to implement gorush grpc server.
|
// Server is used to implement gorush grpc server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
cfg config.ConfYaml
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
// statusMap stores the serving status of the services this Server monitors.
|
// statusMap stores the serving status of the services this Server monitors.
|
||||||
statusMap map[string]proto.HealthCheckResponse_ServingStatus
|
statusMap map[string]proto.HealthCheckResponse_ServingStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer returns a new Server.
|
// NewServer returns a new Server.
|
||||||
func NewServer() *Server {
|
func NewServer(cfg config.ConfYaml) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
|
cfg: cfg,
|
||||||
statusMap: make(map[string]proto.HealthCheckResponse_ServingStatus),
|
statusMap: make(map[string]proto.HealthCheckResponse_ServingStatus),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +101,7 @@ func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*prot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go gorush.SendNotification(ctx, notification)
|
go gorush.SendNotification(s.cfg, notification)
|
||||||
|
|
||||||
return &proto.NotificationReply{
|
return &proto.NotificationReply{
|
||||||
Success: true,
|
Success: true,
|
||||||
|
@ -107,26 +110,26 @@ func (s *Server) Send(ctx context.Context, in *proto.NotificationRequest) (*prot
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunGRPCServer run gorush grpc server
|
// RunGRPCServer run gorush grpc server
|
||||||
func RunGRPCServer(ctx context.Context) error {
|
func RunGRPCServer(ctx context.Context, cfg config.ConfYaml) error {
|
||||||
if !gorush.PushConf.GRPC.Enabled {
|
if !cfg.GRPC.Enabled {
|
||||||
logx.LogAccess.Info("gRPC server is disabled.")
|
logx.LogAccess.Info("gRPC server is disabled.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s := grpc.NewServer()
|
s := grpc.NewServer()
|
||||||
rpcSrv := NewServer()
|
rpcSrv := NewServer(cfg)
|
||||||
proto.RegisterGorushServer(s, rpcSrv)
|
proto.RegisterGorushServer(s, rpcSrv)
|
||||||
proto.RegisterHealthServer(s, rpcSrv)
|
proto.RegisterHealthServer(s, rpcSrv)
|
||||||
|
|
||||||
// Register reflection service on gRPC server.
|
// Register reflection service on gRPC server.
|
||||||
reflection.Register(s)
|
reflection.Register(s)
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", ":"+gorush.PushConf.GRPC.Port)
|
lis, err := net.Listen("tcp", ":"+cfg.GRPC.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.LogError.Fatalln(err)
|
logx.LogError.Fatalln(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logx.LogAccess.Info("gRPC server is running on " + gorush.PushConf.GRPC.Port + " port.")
|
logx.LogAccess.Info("gRPC server is running on " + cfg.GRPC.Port + " port.")
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/appleboy/gorush/gorush"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/appleboy/gorush/logx"
|
"github.com/appleboy/gorush/logx"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
@ -13,22 +13,29 @@ import (
|
||||||
|
|
||||||
const gRPCAddr = "localhost:9000"
|
const gRPCAddr = "localhost:9000"
|
||||||
|
|
||||||
|
func initTest() config.ConfYaml {
|
||||||
|
cfg, _ := config.LoadConf()
|
||||||
|
cfg.Core.Mode = "test"
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
func TestGracefulShutDownGRPCServer(t *testing.T) {
|
func TestGracefulShutDownGRPCServer(t *testing.T) {
|
||||||
|
cfg := initTest()
|
||||||
// server configs
|
// server configs
|
||||||
logx.InitLog(
|
logx.InitLog(
|
||||||
gorush.PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
gorush.PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
gorush.PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
gorush.PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
)
|
)
|
||||||
gorush.PushConf.GRPC.Enabled = true
|
cfg.GRPC.Enabled = true
|
||||||
gorush.PushConf.GRPC.Port = "9000"
|
cfg.GRPC.Port = "9000"
|
||||||
gorush.PushConf.Log.Format = "json"
|
cfg.Log.Format = "json"
|
||||||
|
|
||||||
// Run gRPC server
|
// Run gRPC server
|
||||||
ctx, gRPCContextCancel := context.WithCancel(context.Background())
|
ctx, gRPCContextCancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
if err := RunGRPCServer(ctx); err != nil {
|
if err := RunGRPCServer(ctx, cfg); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -12,12 +12,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
if err := logx.InitLog(
|
if err := logx.InitLog(
|
||||||
PushConf.Log.AccessLevel,
|
cfg.Log.AccessLevel,
|
||||||
PushConf.Log.AccessLog,
|
cfg.Log.AccessLog,
|
||||||
PushConf.Log.ErrorLevel,
|
cfg.Log.ErrorLevel,
|
||||||
PushConf.Log.ErrorLog,
|
cfg.Log.ErrorLog,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,9 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStorageDriverExist(t *testing.T) {
|
func TestStorageDriverExist(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "Test"
|
cfg.Stat.Engine = "Test"
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ func TestStatForMemoryEngine(t *testing.T) {
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
var val int64
|
var val int64
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "memory"
|
cfg.Stat.Engine = "memory"
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
StatStorage.AddTotalCount(100)
|
StatStorage.AddTotalCount(100)
|
||||||
|
@ -61,31 +61,31 @@ func TestStatForMemoryEngine(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedisServerSuccess(t *testing.T) {
|
func TestRedisServerSuccess(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "redis"
|
cfg.Stat.Engine = "redis"
|
||||||
PushConf.Stat.Redis.Addr = "redis:6379"
|
cfg.Stat.Redis.Addr = "redis:6379"
|
||||||
|
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRedisServerError(t *testing.T) {
|
func TestRedisServerError(t *testing.T) {
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "redis"
|
cfg.Stat.Engine = "redis"
|
||||||
PushConf.Stat.Redis.Addr = "redis:6370"
|
cfg.Stat.Redis.Addr = "redis:6370"
|
||||||
|
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStatForRedisEngine(t *testing.T) {
|
func TestStatForRedisEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "redis"
|
cfg.Stat.Engine = "redis"
|
||||||
PushConf.Stat.Redis.Addr = "redis:6379"
|
cfg.Stat.Redis.Addr = "redis:6379"
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
StatStorage.Init()
|
StatStorage.Init()
|
||||||
|
@ -112,8 +112,8 @@ func TestStatForRedisEngine(t *testing.T) {
|
||||||
func TestDefaultEngine(t *testing.T) {
|
func TestDefaultEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
// defaul engine as memory
|
// defaul engine as memory
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
StatStorage.Reset()
|
StatStorage.Reset()
|
||||||
|
@ -138,9 +138,9 @@ func TestDefaultEngine(t *testing.T) {
|
||||||
|
|
||||||
func TestStatForBoltDBEngine(t *testing.T) {
|
func TestStatForBoltDBEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
PushConf, _ := config.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
PushConf.Stat.Engine = "boltdb"
|
cfg.Stat.Engine = "boltdb"
|
||||||
err := InitAppStatus(PushConf)
|
err := InitAppStatus(cfg)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
StatStorage.Reset()
|
StatStorage.Reset()
|
||||||
|
@ -165,7 +165,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
||||||
|
|
||||||
// func TestStatForBuntDBEngine(t *testing.T) {
|
// func TestStatForBuntDBEngine(t *testing.T) {
|
||||||
// var val int64
|
// var val int64
|
||||||
// PushConf.Stat.Engine = "buntdb"
|
// cfg.Stat.Engine = "buntdb"
|
||||||
// err := InitAppStatus()
|
// err := InitAppStatus()
|
||||||
// assert.Nil(t, err)
|
// assert.Nil(t, err)
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
||||||
|
|
||||||
// func TestStatForLevelDBEngine(t *testing.T) {
|
// func TestStatForLevelDBEngine(t *testing.T) {
|
||||||
// var val int64
|
// var val int64
|
||||||
// PushConf.Stat.Engine = "leveldb"
|
// cfg.Stat.Engine = "leveldb"
|
||||||
// err := InitAppStatus()
|
// err := InitAppStatus()
|
||||||
// assert.Nil(t, err)
|
// assert.Nil(t, err)
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ func TestStatForBoltDBEngine(t *testing.T) {
|
||||||
|
|
||||||
// func TestStatForBadgerEngine(t *testing.T) {
|
// func TestStatForBadgerEngine(t *testing.T) {
|
||||||
// var val int64
|
// var val int64
|
||||||
// PushConf.Stat.Engine = "badger"
|
// cfg.Stat.Engine = "badger"
|
||||||
// err := InitAppStatus()
|
// err := InitAppStatus()
|
||||||
// assert.Nil(t, err)
|
// assert.Nil(t, err)
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,16 @@ package badger
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
c "github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBadgerEngine(t *testing.T) {
|
func TestBadgerEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
|
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
badger := New(config)
|
badger := New(cfg)
|
||||||
err := badger.Init()
|
err := badger.Init()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
badger.Reset()
|
badger.Reset()
|
||||||
|
|
|
@ -3,16 +3,16 @@ package boltdb
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
c "github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBoltDBEngine(t *testing.T) {
|
func TestBoltDBEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
|
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
boltDB := New(config)
|
boltDB := New(cfg)
|
||||||
err := boltDB.Init()
|
err := boltDB.Init()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
boltDB.Reset()
|
boltDB.Reset()
|
||||||
|
|
|
@ -4,21 +4,21 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
c "github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBuntDBEngine(t *testing.T) {
|
func TestBuntDBEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
|
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
if _, err := os.Stat(config.Stat.BuntDB.Path); os.IsNotExist(err) {
|
if _, err := os.Stat(cfg.Stat.BuntDB.Path); os.IsNotExist(err) {
|
||||||
err := os.RemoveAll(config.Stat.BuntDB.Path)
|
err := os.RemoveAll(cfg.Stat.BuntDB.Path)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buntDB := New(config)
|
buntDB := New(cfg)
|
||||||
err := buntDB.Init()
|
err := buntDB.Init()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
buntDB.Reset()
|
buntDB.Reset()
|
||||||
|
|
|
@ -4,21 +4,21 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
c "github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLevelDBEngine(t *testing.T) {
|
func TestLevelDBEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
|
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
|
|
||||||
if _, err := os.Stat(config.Stat.LevelDB.Path); os.IsNotExist(err) {
|
if _, err := os.Stat(cfg.Stat.LevelDB.Path); os.IsNotExist(err) {
|
||||||
err = os.RemoveAll(config.Stat.LevelDB.Path)
|
err = os.RemoveAll(cfg.Stat.LevelDB.Path)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
levelDB := New(config)
|
levelDB := New(cfg)
|
||||||
err := levelDB.Init()
|
err := levelDB.Init()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
levelDB.Reset()
|
levelDB.Reset()
|
||||||
|
|
|
@ -4,15 +4,15 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
c "github.com/appleboy/gorush/config"
|
"github.com/appleboy/gorush/config"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRedisServerError(t *testing.T) {
|
func TestRedisServerError(t *testing.T) {
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
config.Stat.Redis.Addr = "redis:6370"
|
cfg.Stat.Redis.Addr = "redis:6370"
|
||||||
|
|
||||||
redis := New(config)
|
redis := New(cfg)
|
||||||
err := redis.Init()
|
err := redis.Init()
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
@ -21,10 +21,10 @@ func TestRedisServerError(t *testing.T) {
|
||||||
func TestRedisEngine(t *testing.T) {
|
func TestRedisEngine(t *testing.T) {
|
||||||
var val int64
|
var val int64
|
||||||
|
|
||||||
config, _ := c.LoadConf("")
|
cfg, _ := config.LoadConf()
|
||||||
config.Stat.Redis.Addr = "redis:6379"
|
cfg.Stat.Redis.Addr = "redis:6379"
|
||||||
|
|
||||||
redis := New(config)
|
redis := New(cfg)
|
||||||
err := redis.Init()
|
err := redis.Init()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
redis.Reset()
|
redis.Reset()
|
||||||
|
|
Loading…
Reference in New Issue