stream initial status report

This commit is contained in:
Frederik Löffert 2019-01-08 14:46:36 +01:00
parent 8de4e11d32
commit 397708958a
8 changed files with 172 additions and 39 deletions

35
model/report.go Normal file
View File

@ -0,0 +1,35 @@
package model
import (
"time"
)
type ReportStatus string
type MessageStatus string
const (
ReportStatusValid ReportStatus = "valid"
ReportStatusInvalid ReportStatus = "invalid"
ReportStatusUnknown ReportStatus = "unknown"
MessageStatusInfo MessageStatus = "info"
MessageStatusWarning MessageStatus = "warning"
MessageStatusError MessageStatus = "error"
)
type Report struct {
Name string
URL string
Status ReportStatus
DateTime time.Time
Hash string
Workspace string
Messages struct {
Status MessageStatus
NodeID string
Message string
Data map[string]string
}
}

7
model/status.go Normal file
View File

@ -0,0 +1,7 @@
package model
type Status struct {
Workspaces []string
ProviderReports map[string]Report `json:"providerReports"`
ConsumerReports map[string]Report `json:"consumerReports"`
}

View File

@ -13,10 +13,22 @@ import (
"github.com/foomo/neosproxy/client/cms"
"github.com/foomo/neosproxy/logging"
"github.com/gorilla/mux"
"gopkg.in/yaml.v2"
content_cache "github.com/foomo/neosproxy/cache/content"
)
type mime string
const (
mimeTextPlain mime = "text/plain"
mimeApplicationJSON mime = "application/json"
)
// ------------------------------------------------------------------------------------------------
// ~ Proxy handler methods
// ------------------------------------------------------------------------------------------------
func (p *Proxy) getContent(w http.ResponseWriter, r *http.Request) {
// duration
@ -199,6 +211,34 @@ func (p *Proxy) streamCachedNeosContentServerExport(w http.ResponseWriter, r *ht
log.WithDuration(start).WithField("size", bytefmt.ByteSize(uint64(written))).Info("streamed file")
}
func (p *Proxy) streamStatus(w http.ResponseWriter, r *http.Request) {
// logger
log := p.setupLogger(r, "status")
// stream
var errEncode error
contentNegotioation := parseAcceptHeader(r.Header.Get("accept"))
switch contentNegotioation {
case mimeApplicationJSON:
w.Header().Set("Content-Type", string(mimeApplicationJSON))
encoder := json.NewEncoder(w)
errEncode = encoder.Encode(p.status)
case mimeTextPlain:
w.Header().Set("Content-Type", "application/x-yaml")
encoder := yaml.NewEncoder(w)
errEncode = encoder.Encode(p.status)
}
// error handling
if errEncode != nil {
log.WithError(errEncode).WithField("content-negotiation", contentNegotioation).Error("failed streaming status")
w.WriteHeader(http.StatusInternalServerError)
return
}
}
// ------------------------------------------------------------------------------------------------
// ~ Private methods
// ------------------------------------------------------------------------------------------------
@ -213,3 +253,18 @@ func getParameter(m map[string]string, key string) string {
}
return ""
}
func parseAcceptHeader(accept string) mime {
mimes := strings.Split(accept, ",")
for _, mime := range mimes {
values := strings.Split(mime, ";")
switch values[0] {
case string(mimeApplicationJSON):
return mimeApplicationJSON
case string(mimeTextPlain):
return mimeTextPlain
}
}
return mimeApplicationJSON
}

22
proxy/api_test.go Normal file
View File

@ -0,0 +1,22 @@
package proxy
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseAcceptHeader(t *testing.T) {
var accept mime
accept = parseAcceptHeader("text/plain,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
assert.Equal(t, string(mimeTextPlain), string(accept))
accept = parseAcceptHeader("application/xhtml+xml,application/json;q=0.9,image/webp,image/apng,*/*;q=0.8")
assert.Equal(t, string(mimeApplicationJSON), string(accept))
accept = parseAcceptHeader("application/xhtml+xml")
assert.Equal(t, string(mimeApplicationJSON), string(accept))
}

View File

@ -9,6 +9,7 @@ import (
"github.com/foomo/neosproxy/client/cms"
"github.com/foomo/neosproxy/config"
"github.com/foomo/neosproxy/logging"
"github.com/foomo/neosproxy/model"
"github.com/foomo/neosproxy/notifier"
"github.com/gorilla/mux"
@ -28,6 +29,12 @@ func New(cfg *config.Config, contentLoader cms.ContentLoader, contentStore store
router: mux.NewRouter(),
proxyHandler: httputil.NewSingleHostReverseProxy(cfg.Neos.URL),
contentCache: content_cache.New(cacheLifetime, contentStore, contentLoader, broker),
status: &model.Status{
Workspaces: cfg.Neos.Workspaces,
ProviderReports: map[string]model.Report{},
ConsumerReports: map[string]model.Report{},
},
}
p.setupRoutes()
for _, workspace := range cfg.Neos.Workspaces {

View File

@ -8,13 +8,6 @@ import (
"github.com/foomo/neosproxy/logging"
)
//-----------------------------------------------------------------------------
// ~ Constants
//-----------------------------------------------------------------------------
const neosproxyPath = "/neosproxy"
const routeContentServerExport = "/contentserver/export"
//-----------------------------------------------------------------------------
// ~ Public methods
//-----------------------------------------------------------------------------
@ -24,38 +17,6 @@ func (p *Proxy) Run() error {
return http.ListenAndServe(p.config.Proxy.Address, p.router)
}
//-----------------------------------------------------------------------------
// ~ Private methods
//-----------------------------------------------------------------------------
func (p *Proxy) setupRoutes() {
// hijack content server export routes
p.router.HandleFunc(routeContentServerExport, p.streamCachedNeosContentServerExport)
p.router.HandleFunc(routeContentServerExport, p.streamCachedNeosContentServerExport).Queries("workspace", "{workspace}")
// /contentserver/export/de/571fd1ae-c8e4-4d91-a708-d97025fb015c?workspace=stage
p.router.HandleFunc(routeContentServerExport+"/{dimension}/{id}", p.getContent)
p.router.HandleFunc(routeContentServerExport+"/{dimension}/{id}", p.getContent).Queries("workspace", "{workspace}")
// api
// neosproxy/cache/%s?workspace=%s
neosproxyRouter := p.router.PathPrefix(neosproxyPath).Subrouter()
neosproxyRouter.Use(p.middlewareTokenAuth)
neosproxyRouter.HandleFunc("/cache/{id}", p.invalidateCache).Methods(http.MethodDelete)
neosproxyRouter.HandleFunc("/cache/{id}", p.invalidateCache).Methods(http.MethodDelete).Queries("workspace", "{workspace}").Name("api-delete-cache")
// middlewares
p.router.Use(p.middlewareServiceUnavailable)
// error handling
p.router.NotFoundHandler = http.HandlerFunc(p.notFound)
p.router.MethodNotAllowedHandler = http.HandlerFunc(p.methodNotAllowed)
// fallback to proxy
p.router.PathPrefix("/").Handler(p.proxyHandler)
}
//-----------------------------------------------------------------------------
// ~ Error handler
//-----------------------------------------------------------------------------

43
proxy/routes.go Normal file
View File

@ -0,0 +1,43 @@
package proxy
import "net/http"
//-----------------------------------------------------------------------------
// ~ Constants
//-----------------------------------------------------------------------------
const neosproxyPath = "/neosproxy"
const routeContentServerExport = "/contentserver/export"
//-----------------------------------------------------------------------------
// ~ Private methods
//-----------------------------------------------------------------------------
func (p *Proxy) setupRoutes() {
// hijack content server export routes
p.router.HandleFunc(routeContentServerExport, p.streamCachedNeosContentServerExport)
p.router.HandleFunc(routeContentServerExport, p.streamCachedNeosContentServerExport).Queries("workspace", "{workspace}")
// /contentserver/export/de/571fd1ae-c8e4-4d91-a708-d97025fb015c?workspace=stage
p.router.HandleFunc(routeContentServerExport+"/{dimension}/{id}", p.getContent)
p.router.HandleFunc(routeContentServerExport+"/{dimension}/{id}", p.getContent).Queries("workspace", "{workspace}")
// api
// neosproxy/cache/%s?workspace=%s
neosproxyRouter := p.router.PathPrefix(neosproxyPath).Subrouter()
neosproxyRouter.Use(p.middlewareTokenAuth)
neosproxyRouter.HandleFunc("/cache/{id}", p.invalidateCache).Methods(http.MethodDelete)
neosproxyRouter.HandleFunc("/cache/{id}", p.invalidateCache).Methods(http.MethodDelete).Queries("workspace", "{workspace}").Name("api-delete-cache")
neosproxyRouter.HandleFunc("/status", p.streamStatus).Methods(http.MethodGet)
// middlewares
p.router.Use(p.middlewareServiceUnavailable)
// error handling
p.router.NotFoundHandler = http.HandlerFunc(p.notFound)
p.router.MethodNotAllowedHandler = http.HandlerFunc(p.methodNotAllowed)
// fallback to proxy
p.router.PathPrefix("/").Handler(p.proxyHandler)
}

View File

@ -6,6 +6,7 @@ import (
"github.com/foomo/neosproxy/cache"
"github.com/foomo/neosproxy/config"
"github.com/foomo/neosproxy/logging"
"github.com/foomo/neosproxy/model"
"github.com/gorilla/mux"
content_cache "github.com/foomo/neosproxy/cache/content"
@ -22,6 +23,8 @@ type Proxy struct {
router *mux.Router
proxyHandler *httputil.ReverseProxy
contentCache *content_cache.Cache
status *model.Status
}
type basicAuth struct {