Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
17
services/gateway/handlers/static.go
Normal file
17
services/gateway/handlers/static.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"fiskerinc.com/modules/utils/envtool"
|
||||
)
|
||||
|
||||
// DocsHandler serves API docs for the gateway
|
||||
func DocsHandler() http.Handler {
|
||||
fp := envtool.GetEnv("DOCS", "")
|
||||
if fp == "" {
|
||||
return nil
|
||||
}
|
||||
fs := http.FileServer(http.Dir(fp))
|
||||
return fs
|
||||
}
|
||||
37
services/gateway/handlers/static_test.go
Normal file
37
services/gateway/handlers/static_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package handlers_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gateway/handlers"
|
||||
|
||||
"fiskerinc.com/modules/httpclient/tester"
|
||||
"fiskerinc.com/modules/testhelper"
|
||||
"fiskerinc.com/modules/testrunner"
|
||||
)
|
||||
|
||||
func TestDocsHandler(t *testing.T) {
|
||||
os.Setenv("DOCS", "/non-existent-folder")
|
||||
handler := handlers.DocsHandler()
|
||||
|
||||
tests := []testrunner.TestCase{
|
||||
{
|
||||
Name: "Simple",
|
||||
HttpTestCase: &tester.HttpTestCase{
|
||||
Request: testhelper.MakeTestRequest(http.MethodGet, "http://example.com/docs", nil),
|
||||
ExpectedStatus: http.StatusNotFound,
|
||||
ExpectedResponse: `404 page not found
|
||||
`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if test.HttpTestCase != nil {
|
||||
w := test.HttpTestCase.Test(handler.ServeHTTP)
|
||||
test.HttpTestCase.ValidateHttp(t, test.Name, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
111
services/gateway/handlers/websocket.go
Normal file
111
services/gateway/handlers/websocket.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"gateway/services"
|
||||
|
||||
"gateway/websocket"
|
||||
|
||||
"fiskerinc.com/modules/logger"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
||||
)
|
||||
|
||||
// SecureSessionWebsocketHandler initiates a websocket connection off an HTTP request
|
||||
func SecureSessionWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
session, err := websocket.NewSecureSession(w, r)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Send()
|
||||
logger.Warn().Msgf("wshandler: bad request %v", websocket.PrintRequest(r))
|
||||
return
|
||||
}
|
||||
|
||||
go runSessionLifeCycle(ctx, session)
|
||||
}
|
||||
|
||||
// InsecureSessionWebsocketHandler initiates a websocket connection off an HTTP request from mobile
|
||||
func InsecureSessionWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
session, err := websocket.NewInsecureSession(w, r)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Send()
|
||||
logger.Warn().Msgf("wshandler: bad request %v", websocket.PrintRequest(r))
|
||||
return
|
||||
}
|
||||
|
||||
go runSessionLifeCycle(ctx, session)
|
||||
}
|
||||
|
||||
// WebsocketSession handles the life cycle of a websocket
|
||||
func runSessionLifeCycle(ctx context.Context, session websocket.SessionInterface) {
|
||||
defer session.Close()
|
||||
span, ctx := tracer.StartSpanFromContext(ctx, "websocket")
|
||||
defer span.Finish()
|
||||
err := session.Authenticate()
|
||||
if err != nil {
|
||||
logger.At(logger.Warn(), session.Key(), "conn").Str("ip", session.GetIP()).Err(err).Send()
|
||||
return
|
||||
}
|
||||
addServices(session)
|
||||
defer removeServices(session)
|
||||
producer, err := services.GetKafkaProducer()
|
||||
if err != nil {
|
||||
logger.Error().Str("id", session.Key()).Err(err).Send()
|
||||
return
|
||||
}
|
||||
logger.Debug().Msgf("websocket session: start listening%v", session.GetID())
|
||||
err = session.Listen(ctx, producer)
|
||||
if err != nil {
|
||||
logger.At(logger.Warn(), session.Key(), "conn").Err(err).Send()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// addServices notifies all services upon websocket connection
|
||||
func addServices(session websocket.SessionInterface) error {
|
||||
id := session.Key()
|
||||
|
||||
services.GetConnections().Add(session)
|
||||
|
||||
logger.Debug().Msgf("websocket session: addServices lifecycle %v", id)
|
||||
services.AddRemoveRedisListeners(true, id)
|
||||
producer, err := services.GetKafkaProducer()
|
||||
if err != nil {
|
||||
logger.At(logger.Error(), session.Key(), "Kafka producer failed").Err(err).Send()
|
||||
return err
|
||||
}
|
||||
if err = session.Load(producer); err != nil {
|
||||
logger.At(logger.Warn(), session.Key(), "conn").Err(err).Send()
|
||||
}
|
||||
logger.At(logger.Debug(), "Session", id).Msgf("connection added %s", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeServices notifies all services upon websocket disconnection
|
||||
func removeServices(session websocket.SessionInterface) error {
|
||||
id := session.Key()
|
||||
|
||||
if err := services.GetConnections().Remove(session); err != nil {
|
||||
// if error returned, the session did not exist or is different session
|
||||
// that means we should not remove the current id from pub sub and queues
|
||||
logger.At(logger.Error(), session.Key(), "conn").Err(err).Send()
|
||||
return err
|
||||
}
|
||||
|
||||
services.AddRemoveRedisListeners(false, id)
|
||||
producer, err := services.GetKafkaProducer()
|
||||
if err != nil {
|
||||
logger.At(logger.Error(), session.Key(), "Kafka producer").Err(err).Send()
|
||||
return err
|
||||
}
|
||||
|
||||
if err = session.Teardown(producer); err != nil {
|
||||
logger.At(logger.Warn(), session.Key(), "conn").Err(err).Send()
|
||||
}
|
||||
logger.At(logger.Debug(), "Session", id).Msgf("connection removed %s", id)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user