aboutsummaryrefslogtreecommitdiff
path: root/marusia.go
diff options
context:
space:
mode:
Diffstat (limited to 'marusia.go')
-rw-r--r--marusia.go114
1 files changed, 114 insertions, 0 deletions
diff --git a/marusia.go b/marusia.go
new file mode 100644
index 0000000..5356720
--- /dev/null
+++ b/marusia.go
@@ -0,0 +1,114 @@
+// Copyright (c) 2020 Alexander Kiryukhin <a.kiryukhin@mail.ru>
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package marusia
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+// Marusia is main API object
+type Marusia struct {
+ handler MessageHandler
+ ctx context.Context
+ errorLogger func(error)
+}
+
+// SetCtx sets optional parent context
+func (m *Marusia) SetCtx(ctx context.Context) *Marusia {
+ m.ctx = ctx
+ return m
+}
+
+// SetErrorLogger sets optional error logger
+func (m *Marusia) SetErrorLogger(errorLogger func(error)) *Marusia {
+ m.errorLogger = errorLogger
+ return m
+}
+
+// NewMarusia is API constructor
+func NewMarusia(handler MessageHandler) *Marusia {
+ return &Marusia{handler: handler, ctx: context.Background()}
+}
+
+// MessageHandler is http.MessageHandler that proceed requests from Marusia and sends responses to Marusia
+func (m *Marusia) Handler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ reqEnvelope := new(requestEnvelope)
+ if err := json.NewDecoder(r.Body).Decode(reqEnvelope); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ if m.errorLogger != nil {
+ m.errorLogger(err)
+ }
+ return
+ }
+ ctx := getContext(m.ctx, reqEnvelope)
+ resp, err := m.handler(ctx, reqEnvelope.Request)
+ if err != nil {
+ if m.errorLogger != nil {
+ m.errorLogger(err)
+ }
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ respEnvelope := &responseEnvelope{
+ Response: resp,
+ Session: reqEnvelope.Session,
+ Version: version,
+ }
+ w.WriteHeader(http.StatusOK)
+ if err := json.NewEncoder(w).Encode(respEnvelope); err != nil {
+ if m.errorLogger != nil {
+ m.errorLogger(err)
+ }
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+ })
+}
+
+func getContext(parent context.Context, req *requestEnvelope) context.Context {
+ data := map[string]string{
+ CtxSessionID: req.Session.SessionID,
+ CtxUserID: req.Session.UserID,
+ CtxSkillID: req.Session.SkillID,
+ CtxMessageID: strconv.Itoa(req.Session.MessageID),
+ CtxClientID: req.Meta.ClientID,
+ CtxLocale: req.Meta.Locale,
+ CtxTimezone: req.Meta.Timezone,
+ }
+ var interfaces []string
+ for iface := range req.Meta.Interfaces {
+ interfaces = append(interfaces, iface)
+ }
+ data[CtxInterfaces] = strings.Join(interfaces, ",")
+ if req.Session.New {
+ data[CtxNew] = "true"
+ }
+ ctx := parent
+ for k, v := range data {
+ ctx = context.WithValue(ctx, k, v)
+ }
+ return ctx
+}