diff --git a/main.go b/main.go index 1580b37..e0daca6 100644 --- a/main.go +++ b/main.go @@ -22,18 +22,19 @@ import ( "fmt" "os" "runtime" - . "github.com/uniqush/uniqush-push/srv" + + "github.com/uniqush/uniqush-push/srv" ) var uniqushPushConfFlags = flag.String("config", "/etc/uniqush/uniqush-push.conf", "Config file path") var uniqushPushShowVersionFlag = flag.Bool("version", false, "Version info") -var uniqushPushVersion = "uniqush-push 1.5.2" +var uniqushPushVersion = "uniqush-push 2.0.0" -func installPushSrvices() { - InstallGCM() - InstallAPNS() - InstallADM() +func installPushServices() { + srv.InstallGCM() + srv.InstallAPNS() + srv.InstallADM() } func main() { @@ -43,7 +44,7 @@ func main() { return } runtime.GOMAXPROCS(runtime.NumCPU() + 1) - installPushSrvices() + installPushServices() err := Run(*uniqushPushConfFlags, uniqushPushVersion) if err != nil { diff --git a/pushbackend.go b/pushbackend.go index 26d6f51..7a17ab9 100644 --- a/pushbackend.go +++ b/pushbackend.go @@ -20,6 +20,7 @@ package main import ( "sync" "time" + . "github.com/uniqush/log" . "github.com/uniqush/uniqush-push/db" . "github.com/uniqush/uniqush-push/push" @@ -84,7 +85,8 @@ func (self *PushBackEnd) Unsubscribe(service, sub string, dp *DeliveryPoint) err func (self *PushBackEnd) processError() { for err := range self.errChan { rid := randomUniqId() - e := self.fixError(rid, err, self.loggers[LOGGER_PUSH], 0*time.Second) + nullHandler := &NullApiResponseHandler{} + e := self.fixError(rid, "", err, self.loggers[LOGGER_PUSH], 0*time.Second, nullHandler) switch e0 := e.(type) { case *InfoReport: self.loggers[LOGGER_PUSH].Infof("%v", e0) @@ -94,7 +96,7 @@ func (self *PushBackEnd) processError() { } } -func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, after time.Duration) error { +func (self *PushBackEnd) fixError(reqId string, remoteAddr string, event error, logger Logger, after time.Duration, handler ApiResponseHandler) error { var service string var sub string var ok bool @@ -115,17 +117,20 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte if after <= 1*time.Second { after = 5 * time.Second } + providerName := err.Provider.Name() + destinationName := err.Destination.Name() if after > 1*time.Minute { - logger.Errorf("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Failed after retry", reqId, service, sub, err.Provider.Name(), err.Destination.Name()) + logger.Errorf("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Failed after retry", reqId, service, sub, providerName, destinationName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, PushServiceProvider: &providerName, DeliveryPoint: &destinationName, Code: UNIQUSH_ERROR_FAILED_RETRY}) return nil } - logger.Infof("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Retry after %v", reqId, service, sub, err.Provider.Name(), err.Destination.Name(), after) + logger.Infof("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Retry after %v", reqId, service, sub, providerName, destinationName, after) go func() { <-time.After(after) subs := make([]string, 1) subs[0] = sub after = 2 * after - self.pushImpl(reqId, service, subs, err.Content, nil, self.loggers[LOGGER_PUSH], err.Provider, err.Destination, after) + self.pushImpl(reqId, remoteAddr, service, subs, err.Content, nil, self.loggers[LOGGER_PUSH], err.Provider, err.Destination, after, handler) }() case *PushServiceProviderUpdate: if err.Provider == nil { @@ -136,10 +141,13 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte } psp := err.Provider e := self.db.ModifyPushServiceProvider(psp) + pspName := psp.Name() if e != nil { - logger.Errorf("RequestID=%v Service=%v PushServiceProvider=%v Update Failed: %v", reqId, service, psp.Name(), e) + logger.Errorf("RequestID=%v Service=%v PushServiceProvider=%v Update Failed: %v", reqId, service, pspName, e) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, PushServiceProvider: &pspName, Code: UNIQUSH_ERROR_UPDATE_PUSH_SERVICE_PROVIDER}) } else { - logger.Infof("RequestID=%v Service=%v PushServiceProvider=%v Update Success", reqId, service, psp.Name()) + logger.Infof("RequestID=%v Service=%v PushServiceProvider=%v Update Success", reqId, service, pspName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, PushServiceProvider: &pspName, Code: UNIQUSH_SUCCESS}) } case *DeliveryPointUpdate: if err.Destination == nil { @@ -150,10 +158,13 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte } dp := err.Destination e := self.db.ModifyDeliveryPoint(dp) + dpName := dp.Name() if e != nil { - logger.Errorf("Subscriber=%v DeliveryPoint=%v Update Failed: %v", sub, dp.Name(), e) + logger.Errorf("Subscriber=%v DeliveryPoint=%v Update Failed: %v", sub, dpName, e) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Subscriber: &sub, Service: &service, DeliveryPoint: &dpName, Code: UNIQUSH_ERROR_UPDATE_DELIVERY_POINT}) } else { - logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Update Success", service, sub, dp.Name()) + logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Update Success", service, sub, dpName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Subscriber: &sub, Service: &service, DeliveryPoint: &dpName, Code: UNIQUSH_SUCCESS}) } case *InvalidRegistrationUpdate: if err.Provider == nil || err.Destination == nil { @@ -167,10 +178,13 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte } dp := err.Destination e := self.Unsubscribe(service, sub, dp) + dpName := dp.Name() if e != nil { - logger.Errorf("Service=%v Subscriber=%v DeliveryPoint=%v Removing invalid reg failed: %v", service, sub, dp.Name(), e) + logger.Errorf("Service=%v Subscriber=%v DeliveryPoint=%v Removing invalid reg failed: %v", service, sub, dpName, e) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, DeliveryPoint: &dpName, Code: UNIQUSH_REMOVE_INVALID_REG}) } else { - logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Invalid registration removed", service, sub, dp.Name()) + logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Invalid registration removed", service, sub, dpName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, DeliveryPoint: &dpName, Code: UNIQUSH_REMOVE_INVALID_REG}) } case *UnsubscribeUpdate: if err.Provider == nil || err.Destination == nil { @@ -184,10 +198,13 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte } dp := err.Destination e := self.Unsubscribe(service, sub, dp) + dpName := dp.Name() if e != nil { - logger.Errorf("Service=%v Subscriber=%v DeliveryPoint=%v Unsubscribe failed: %v", service, sub, dp.Name(), e) + logger.Errorf("Service=%v Subscriber=%v DeliveryPoint=%v Unsubscribe failed: %v", service, sub, dpName, e) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, DeliveryPoint: &dpName, Code: UNIQUSH_UPDATE_UNSUBSCRIBE}) } else { - logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Unsubscribe success", service, sub, dp.Name()) + logger.Infof("Service=%v Subscriber=%v DeliveryPoint=%v Unsubscribe success", service, sub, dpName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, DeliveryPoint: &dpName, Code: UNIQUSH_UPDATE_UNSUBSCRIBE}) } default: return err @@ -195,21 +212,27 @@ func (self *PushBackEnd) fixError(reqId string, event error, logger Logger, afte return nil } -func (self *PushBackEnd) collectResult(reqId string, service string, resChan <-chan *PushResult, logger Logger, after time.Duration) { +func (self *PushBackEnd) collectResult(reqId string, remoteAddr string, service string, resChan <-chan *PushResult, logger Logger, after time.Duration, handler ApiResponseHandler) { for res := range resChan { var sub string var ok bool if res.Provider != nil && res.Destination != nil { if sub, ok = res.Destination.FixedData["subscriber"]; !ok { - logger.Errorf("RequestID=%v Subscriber=%v DeliveryPoint=%v Bad Delivery Point: No subscriber", reqId, sub, res.Destination.Name()) + destinationName := res.Destination.Name() + logger.Errorf("RequestID=%v Subscriber=%v DeliveryPoint=%v Bad Delivery Point: No subscriber", reqId, sub, destinationName) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, DeliveryPoint: &destinationName, Code: UNIQUSH_ERROR_BAD_DELIVERY_POINT}) continue } } if res.Err == nil { - logger.Infof("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v MsgId=%v Success!", reqId, service, sub, res.Provider.Name(), res.Destination.Name(), res.MsgId) + providerName := res.Provider.Name() + destinationName := res.Destination.Name() + msgId := res.MsgId + logger.Infof("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v MsgId=%v Success!", reqId, service, sub, providerName, destinationName, msgId) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, PushServiceProvider: &providerName, DeliveryPoint: &destinationName, MessageId: &msgId, Code: UNIQUSH_SUCCESS}) continue } - err := self.fixError(reqId, res.Err, logger, after) + err := self.fixError(reqId, remoteAddr, res.Err, logger, after, handler) if err != nil { pspName := "Unknown" dpName := "Unknown" @@ -220,6 +243,7 @@ func (self *PushBackEnd) collectResult(reqId string, service string, resChan <-c dpName = res.Destination.Name() } logger.Errorf("RequestID=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Failed: %v", reqId, service, sub, pspName, dpName, err) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, PushServiceProvider: &pspName, DeliveryPoint: &dpName, Code: UNIQUSH_ERROR_GENERIC}) } } } @@ -233,11 +257,11 @@ func (self *PushBackEnd) NumberOfDeliveryPoints(service, sub string, logger Logg return len(pspDpList) } -func (self *PushBackEnd) Push(reqId string, service string, subs []string, notif *Notification, perdp map[string][]string, logger Logger) { - self.pushImpl(reqId, service, subs, notif, perdp, logger, nil, nil, 0*time.Second) +func (self *PushBackEnd) Push(reqId string, remoteAddr string, service string, subs []string, notif *Notification, perdp map[string][]string, logger Logger, handler ApiResponseHandler) { + self.pushImpl(reqId, remoteAddr, service, subs, notif, perdp, logger, nil, nil, 0*time.Second, handler) } -func (self *PushBackEnd) pushImpl(reqId string, service string, subs []string, notif *Notification, perdp map[string][]string, logger Logger, provider *PushServiceProvider, dest *DeliveryPoint, after time.Duration) { +func (self *PushBackEnd) pushImpl(reqId string, remoteAddr string, service string, subs []string, notif *Notification, perdp map[string][]string, logger Logger, provider *PushServiceProvider, dest *DeliveryPoint, after time.Duration, handler ApiResponseHandler) { dpChanMap := make(map[string]chan *DeliveryPoint) wg := new(sync.WaitGroup) for _, sub := range subs { @@ -252,12 +276,14 @@ func (self *PushBackEnd) pushImpl(reqId string, service string, subs []string, n pspDpList, err = self.db.GetPushServiceProviderDeliveryPointPairs(service, sub) if err != nil { logger.Errorf("RequestID=%v Service=%v Subscriber=%v Failed: Database Error %v", reqId, service, sub, err) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, Code: UNIQUSH_ERROR_DATABASE}) continue } } if len(pspDpList) == 0 { logger.Errorf("RequestID=%v Service=%v Subscriber=%v Failed: No device", reqId, service, sub) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, Code: UNIQUSH_ERROR_NO_DEVICE}) continue } @@ -266,10 +292,12 @@ func (self *PushBackEnd) pushImpl(reqId string, service string, subs []string, n dp := pair.DeliveryPoint if psp == nil { logger.Errorf("RequestID=%v Service=%v Subscriber=%v Failed once: nil Push Service Provider", reqId, service, sub) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, Code: UNIQUSH_ERROR_NO_PUSH_SERVICE_PROVIDER}) continue } if dp == nil { logger.Errorf("RequestID=%v Service=%v Subscriber=%v Failed once: nil Delivery Point", reqId, service, sub) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Subscriber: &sub, Code: UNIQUSH_ERROR_NO_DELIVERY_POINT}) continue } var ch chan *DeliveryPoint @@ -294,7 +322,7 @@ func (self *PushBackEnd) pushImpl(reqId string, service string, subs []string, n }() wg.Add(1) go func() { - self.collectResult(reqId, service, resChan, logger, after) + self.collectResult(reqId, remoteAddr, service, resChan, logger, after, handler) wg.Done() }() } diff --git a/restapi.go b/restapi.go index bf92553..0efa129 100644 --- a/restapi.go +++ b/restapi.go @@ -147,16 +147,16 @@ func getServiceFromMap(kv map[string]string, validate bool) (service string, err return } -func (self *RestAPI) changePushServiceProvider(kv map[string]string, logger log.Logger, remoteAddr string, add bool) { +func (self *RestAPI) changePushServiceProvider(kv map[string]string, logger log.Logger, remoteAddr string, add bool) ApiResponseDetails { psp, err := self.psm.BuildPushServiceProviderFromMap(kv) if err != nil { logger.Errorf("From=%v Cannot build push service provider: %v", remoteAddr, err) - return + return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_BUILD_PUSH_SERVICE_PROVIDER} } service, err := getServiceFromMap(kv, true) if err != nil { logger.Errorf("From=%v Cannot get service name: %v; %v", remoteAddr, service, err) - return + return ApiResponseDetails{From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SERVICE} } if add { err = self.backend.AddPushServiceProvider(service, psp) @@ -165,27 +165,28 @@ func (self *RestAPI) changePushServiceProvider(kv map[string]string, logger log. } if err != nil { logger.Errorf("From=%v Failed: %v", remoteAddr, err) - return + return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_GENERIC} } - logger.Infof("From=%v Service=%v PushServiceProvider=%v Success!", remoteAddr, service, psp.Name()) - return + pspName := psp.Name() + logger.Infof("From=%v Service=%v PushServiceProvider=%v Success!", remoteAddr, service, pspName) + return ApiResponseDetails{From: &remoteAddr, Service: &service, PushServiceProvider: &pspName, Code: UNIQUSH_SUCCESS} } -func (self *RestAPI) changeSubscription(kv map[string]string, logger log.Logger, remoteAddr string, issub bool) { +func (self *RestAPI) changeSubscription(kv map[string]string, logger log.Logger, remoteAddr string, issub bool) ApiResponseDetails { dp, err := self.psm.BuildDeliveryPointFromMap(kv) if err != nil { logger.Errorf("Cannot build delivery point: %v", err) - return + return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_BUILD_DELIVERY_POINT} } service, err := getServiceFromMap(kv, true) if err != nil { logger.Errorf("From=%v Cannot get service name: %v; %v", remoteAddr, service, err) - return + return ApiResponseDetails{From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SERVICE} } subs, err := getSubscribersFromMap(kv, true) if err != nil { logger.Errorf("From=%v Service=%v Cannot get subscriber: %v", remoteAddr, service, err) - return + return ApiResponseDetails{From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SUBSCRIBER} } var psp *PushServiceProvider @@ -196,28 +197,35 @@ func (self *RestAPI) changeSubscription(kv map[string]string, logger log.Logger, } if err != nil { logger.Errorf("From=%v Failed: %v", remoteAddr, err) - return + return ApiResponseDetails{From: &remoteAddr, Code: UNIQUSH_ERROR_GENERIC} } + dpName := dp.Name() if psp == nil { - logger.Infof("From=%v Service=%v Subscriber=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], dp.Name()) + logger.Infof("From=%v Service=%v Subscriber=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], dpName) + return ApiResponseDetails{From: &remoteAddr, Service: &service, Subscriber: &subs[0], DeliveryPoint: &dpName, Code: UNIQUSH_SUCCESS} } else { - logger.Infof("From=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], psp.Name(), dp.Name()) + pspName := psp.Name() + logger.Infof("From=%v Service=%v Subscriber=%v PushServiceProvider=%v DeliveryPoint=%v Success!", remoteAddr, service, subs[0], pspName, dpName) + return ApiResponseDetails{From: &remoteAddr, Service: &service, Subscriber: &subs[0], DeliveryPoint: &dpName, PushServiceProvider: &pspName, Code: UNIQUSH_SUCCESS} } } -func (self *RestAPI) pushNotification(reqId string, kv map[string]string, perdp map[string][]string, logger log.Logger, remoteAddr string) { +func (self *RestAPI) pushNotification(reqId string, kv map[string]string, perdp map[string][]string, logger log.Logger, remoteAddr string, handler ApiResponseHandler) { service, err := getServiceFromMap(kv, true) if err != nil { logger.Errorf("RequestId=%v From=%v Cannot get service name: %v; %v", reqId, remoteAddr, service, err) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SERVICE}) return } subs, err := getSubscribersFromMap(kv, false) if err != nil { logger.Errorf("RequestId=%v From=%v Service=%v Cannot get subscriber: %v", reqId, remoteAddr, service, err) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_CANNOT_GET_SUBSCRIBER}) return } if len(subs) == 0 { logger.Errorf("RequestId=%v From=%v Service=%v NoSubscriber", reqId, remoteAddr, service) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_NO_SUBSCRIBER}) return } @@ -248,14 +256,14 @@ func (self *RestAPI) pushNotification(reqId string, kv map[string]string, perdp } if notif.IsEmpty() { - logger.Errorf("RequestId=%v From=%v Service=%v EmptyNotification", reqId, remoteAddr, service) + logger.Errorf("RequestId=%v From=%v Service=%v NrSubscribers=%v Subscribers=\"%+v\" EmptyNotification", reqId, remoteAddr, service, len(subs), subs) + handler.AddDetailsToHandler(ApiResponseDetails{RequestId: &reqId, From: &remoteAddr, Service: &service, Code: UNIQUSH_ERROR_EMPTY_NOTIFICATION}) return } logger.Infof("RequestId=%v From=%v Service=%v NrSubscribers=%v Subscribers=\"%+v\"", reqId, remoteAddr, service, len(subs), subs) - self.backend.Push(reqId, service, subs, notif, perdp, logger) - return + self.backend.Push(reqId, remoteAddr, service, subs, notif, perdp, logger, handler) } func (self *RestAPI) stop(w io.Writer, remoteAddr string) { @@ -294,6 +302,7 @@ func (self *RestAPI) numberOfDeliveryPoints(kv map[string][]string, logger log.L func (self *RestAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() remoteAddr := r.RemoteAddr + switch r.URL.Path { case QUERY_NUMBER_OF_DELIVERY_POINTS_URL: r.ParseForm() @@ -324,33 +333,38 @@ func (self *RestAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) { kv[k] = v[0] } } - writer := w - logLevel := log.LOGLEVEL_INFO self.waitGroup.Add(1) defer self.waitGroup.Done() + var handler ApiResponseHandler = nil + var details ApiResponseDetails switch r.URL.Path { case ADD_PUSH_SERVICE_PROVIDER_TO_SERVICE_URL: - weblogger := log.NewLogger(writer, "[AddPushServiceProvider]", logLevel) - logger := log.MultiLogger(weblogger, self.loggers[LOGGER_ADDPSP]) - self.changePushServiceProvider(kv, logger, remoteAddr, true) + handler = newSimpleResponseHandler(self.loggers[LOGGER_ADDPSP], "AddPushServiceProvider") + details = self.changePushServiceProvider(kv, self.loggers[LOGGER_ADDPSP], remoteAddr, true) + handler.AddDetailsToHandler(details) case REMOVE_PUSH_SERVICE_PROVIDER_TO_SERVICE_URL: - weblogger := log.NewLogger(writer, "[RemovePushServiceProvider]", logLevel) - logger := log.MultiLogger(weblogger, self.loggers[LOGGER_RMPSP]) - self.changePushServiceProvider(kv, logger, remoteAddr, false) + handler = newSimpleResponseHandler(self.loggers[LOGGER_RMPSP], "RemovePushServiceProvider") + details = self.changePushServiceProvider(kv, self.loggers[LOGGER_RMPSP], remoteAddr, false) + handler.AddDetailsToHandler(details) case ADD_DELIVERY_POINT_TO_SERVICE_URL: - weblogger := log.NewLogger(writer, "[Subscribe]", logLevel) - logger := log.MultiLogger(weblogger, self.loggers[LOGGER_SUB]) - self.changeSubscription(kv, logger, remoteAddr, true) + handler = newSimpleResponseHandler(self.loggers[LOGGER_SUB], "Subscribe") + details = self.changeSubscription(kv, self.loggers[LOGGER_SUB], remoteAddr, true) + handler.AddDetailsToHandler(details) case REMOVE_DELIVERY_POINT_FROM_SERVICE_URL: - weblogger := log.NewLogger(writer, "[Unsubscribe]", logLevel) - logger := log.MultiLogger(weblogger, self.loggers[LOGGER_UNSUB]) - self.changeSubscription(kv, logger, remoteAddr, false) + handler = newSimpleResponseHandler(self.loggers[LOGGER_UNSUB], "Unsubscribe") + details = self.changeSubscription(kv, self.loggers[LOGGER_UNSUB], remoteAddr, false) + handler.AddDetailsToHandler(details) case PUSH_NOTIFICATION_URL: - weblogger := log.NewLogger(writer, "[Push]", logLevel) - logger := log.MultiLogger(weblogger, self.loggers[LOGGER_PUSH]) + handler = newPushResponseHandler(self.loggers[LOGGER_PUSH]) rid := randomUniqId() - self.pushNotification(rid, kv, perdp, logger, remoteAddr) + self.pushNotification(rid, kv, perdp, self.loggers[LOGGER_PUSH], remoteAddr, handler) + } + if handler != nil { + _, err := w.Write(handler.ToJSON()) + if err != nil { + self.loggers[LOGGER_WEB].Errorf("Failed to write http response: %v", err) + } } } diff --git a/restapi_pushresponse.go b/restapi_pushresponse.go new file mode 100644 index 0000000..69bb0de --- /dev/null +++ b/restapi_pushresponse.go @@ -0,0 +1,69 @@ +package main + +import ( + "encoding/json" + "sync" + "time" + + "github.com/uniqush/log" +) + +type ApiPushResponseHandler struct { + response ApiPushResponse + logger log.Logger + mutex sync.Mutex +} + +var _ ApiResponseHandler = (*ApiPushResponseHandler)(nil) + +type ApiPushResponse struct { + Type string `json:"type"` + Date int64 `json:"date"` + SuccessCount int `json:"successCount"` + FailureCount int `json:"failureCount"` + DroppedCount int `json:"droppedCount"` + SuccessDetails []ApiResponseDetails `json:"successDetails"` + FailureDetails []ApiResponseDetails `json:"failureDetails"` + DroppedDetails []ApiResponseDetails `json:"droppedDetails"` +} + +func newPushResponseHandler(logger log.Logger) *ApiPushResponseHandler { + return &ApiPushResponseHandler{ + response: newApiPushResponse(), + logger: logger, + } +} + +func newApiPushResponse() ApiPushResponse { + return ApiPushResponse{ + Type: "Push", + Date: time.Now().Unix(), + SuccessDetails: make([]ApiResponseDetails, 0), + FailureDetails: make([]ApiResponseDetails, 0), + DroppedDetails: make([]ApiResponseDetails, 0), + } +} + +func (self *ApiPushResponseHandler) AddDetailsToHandler(v ApiResponseDetails) { + self.mutex.Lock() + if v.Code == UNIQUSH_SUCCESS { + self.response.SuccessDetails = append(self.response.SuccessDetails, v) + self.response.SuccessCount += 1 + } else if v.Code == UNIQUSH_UPDATE_UNSUBSCRIBE || v.Code == UNIQUSH_REMOVE_INVALID_REG { + self.response.DroppedDetails = append(self.response.DroppedDetails, v) + self.response.DroppedCount += 1 + } else { + self.response.FailureDetails = append(self.response.FailureDetails, v) + self.response.FailureCount += 1 + } + self.mutex.Unlock() +} + +func (self *ApiPushResponseHandler) ToJSON() []byte { + json, err := json.Marshal(self.response) + if err != nil { + self.logger.Errorf("Failed to marshal json [%v] as string: %v", self.response, err) + return nil + } + return json +} diff --git a/restapi_response.go b/restapi_response.go new file mode 100644 index 0000000..6773e6c --- /dev/null +++ b/restapi_response.go @@ -0,0 +1,56 @@ +package main + +const ( + /* Not errors */ + UNIQUSH_SUCCESS = "UNIQUSH_SUCCESS" + UNIQUSH_REMOVE_INVALID_REG = "UNIQUSH_REMOVE_INVALID_REG" + UNIQUSH_UPDATE_UNSUBSCRIBE = "UNIQUSH_UPDATE_UNSUBSCRIBE" + + /* Errors */ + UNIQUSH_ERROR_GENERIC = "UNIQUSH_ERROR_GENERIC" + UNIQUSH_ERROR_EMPTY_NOTIFICATION = "UNIQUSH_ERROR_EMPTY_NOTIFICATION" + UNIQUSH_ERROR_DATABASE = "UNIQUSH_ERROR_DATABASE" + UNIQUSH_ERROR_FAILED_RETRY = "UNIQUSH_ERROR_FAILED_RETRY" + + UNIQUSH_ERROR_BUILD_PUSH_SERVICE_PROVIDER = "UNIQUSH_ERROR_BUILD_PUSH_SERVICE_PROVIDER" + UNIQUSH_ERROR_UPDATE_PUSH_SERVICE_PROVIDER = "UNIQUSH_ERROR_UPDATE_PUSH_SERVICE_PROVIDER" + + UNIQUSH_ERROR_BAD_DELIVERY_POINT = "UNIQUSH_ERROR_BAD_DELIVERY_POINT" + UNIQUSH_ERROR_BUILD_DELIVERY_POINT = "UNIQUSH_ERROR_BUILD_DELIVERY_POINT" + UNIQUSH_ERROR_UPDATE_DELIVERY_POINT = "UNIQUSH_ERROR_UPDATE_DELIVERY_POINT" + + UNIQUSH_ERROR_CANNOT_GET_SERVICE = "UNIQUSH_ERROR_CANNOT_GET_SERVICE" + UNIQUSH_ERROR_CANNOT_GET_SUBSCRIBER = "UNIQUSH_ERROR_CANNOT_GET_SUBSCRIBER" + + UNIQUSH_ERROR_NO_DEVICE = "UNIQUSH_ERROR_NO_DEVICE" + UNIQUSH_ERROR_NO_DELIVERY_POINT = "UNIQUSH_ERROR_NO_DELIVERY_POINT" + UNIQUSH_ERROR_NO_PUSH_SERVICE_PROVIDER = "UNIQUSH_ERROR_NO_PUSH_SERVICE_PROVIDER" + UNIQUSH_ERROR_NO_SERVICE = "UNIQUSH_ERROR_NO_SERVICE" + UNIQUSH_ERROR_NO_SUBSCRIBER = "UNIQUSH_ERROR_NO_SUBSCRIBER" +) + +type ApiResponseDetails struct { + RequestId *string `json:"requestId"` + Service *string `json:"service"` + From *string `json:"from"` + Subscriber *string `json:"subscriber"` + PushServiceProvider *string `json:"pushServiceProvider"` + DeliveryPoint *string `json:"deliveryPoint"` + MessageId *string `json:"messageId"` + Code string `json:"code"` +} + +type ApiResponseHandler interface { + AddDetailsToHandler(v ApiResponseDetails) + ToJSON() []byte +} + +type NullApiResponseHandler struct{} + +var _ ApiResponseHandler = (*NullApiResponseHandler)(nil) + +func (self *NullApiResponseHandler) AddDetailsToHandler(v ApiResponseDetails) {} + +func (self *NullApiResponseHandler) ToJSON() []byte { + return []byte{} +} diff --git a/restapi_simpleresponse.go b/restapi_simpleresponse.go new file mode 100644 index 0000000..ade03d2 --- /dev/null +++ b/restapi_simpleresponse.go @@ -0,0 +1,60 @@ +package main + +import ( + "encoding/json" + "github.com/uniqush/log" + "time" +) + +const ( + STATUS_SUCCESS = iota + STATUS_FAILURE + STATUS_UNKNOWN +) + +type ApiSimpleResponseHandler struct { + response ApiSimpleResponse + logger log.Logger +} + +var _ ApiResponseHandler = (*ApiSimpleResponseHandler)(nil) + +type ApiSimpleResponse struct { + Type string `json:"type"` + Date int64 `json:"date"` + Status int `json:"status"` + Details ApiResponseDetails `json:"details"` +} + +func newSimpleResponseHandler(logger log.Logger, apiType string) *ApiSimpleResponseHandler { + return &ApiSimpleResponseHandler{ + response: newApiSimpleResponse(apiType), + logger: logger, + } +} + +func newApiSimpleResponse(apiType string) ApiSimpleResponse { + return ApiSimpleResponse{ + Type: apiType, + Date: time.Now().Unix(), + Status: STATUS_UNKNOWN, + } +} + +func (self *ApiSimpleResponseHandler) AddDetailsToHandler(v ApiResponseDetails) { + if v.Code == UNIQUSH_SUCCESS { + self.response.Status = STATUS_SUCCESS + } else { + self.response.Status = STATUS_FAILURE + } + self.response.Details = v +} + +func (self *ApiSimpleResponseHandler) ToJSON() []byte { + json, err := json.Marshal(self.response) + if err != nil { + self.logger.Errorf("Failed to marshal json [%v] as string: %v", self.response, err) + return nil + } + return json +} diff --git a/srv/apns-test/apns-test.sh b/srv/apns-test/apns-test.sh index 447eb24..85ec16c 100755 --- a/srv/apns-test/apns-test.sh +++ b/srv/apns-test/apns-test.sh @@ -7,7 +7,10 @@ PWD=`pwd` curl http://127.0.0.1:9898/addpsp -d service=myservice -d pushservicetype=apns -d cert=$PWD/localhost.cert -d key=$PWD/localhost.key -d addr=127.0.0.1:8080 -d skipverify=true +echo curl http://127.0.0.1:9898/subscribe -d service=myservice -d subscriber=uniqush.client -d pushservicetype=apns -d devtoken=3df3e210e7adf35f840f45b269b760d9d51081569dc4509ee98bb4d4c92a828e +echo curl http://127.0.0.1:9898/push -d service=myservice -d subscriber=uniqush.client -d msg="Hello World" +echo