mirror of
https://github.com/safing/portbase
synced 2025-09-04 11:40:23 +00:00
Use gorilla/mux for endpoint paths
This commit is contained in:
parent
8814d279bd
commit
400f4c12ed
3 changed files with 49 additions and 25 deletions
|
@ -13,7 +13,6 @@ import (
|
||||||
"github.com/safing/portbase/database"
|
"github.com/safing/portbase/database"
|
||||||
"github.com/safing/portbase/database/record"
|
"github.com/safing/portbase/database/record"
|
||||||
"github.com/safing/portbase/database/storage"
|
"github.com/safing/portbase/database/storage"
|
||||||
"github.com/safing/portbase/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -59,8 +58,6 @@ type EndpointBridgeResponse struct {
|
||||||
|
|
||||||
// Get returns a database record.
|
// Get returns a database record.
|
||||||
func (ebs *endpointBridgeStorage) Get(key string) (record.Record, error) {
|
func (ebs *endpointBridgeStorage) Get(key string) (record.Record, error) {
|
||||||
log.Errorf("api bridge: getting %s", key)
|
|
||||||
|
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return nil, database.ErrNotFound
|
return nil, database.ErrNotFound
|
||||||
}
|
}
|
||||||
|
@ -81,8 +78,6 @@ func (ebs *endpointBridgeStorage) GetMeta(key string) (*record.Meta, error) {
|
||||||
|
|
||||||
// Put stores a record in the database.
|
// Put stores a record in the database.
|
||||||
func (ebs *endpointBridgeStorage) Put(r record.Record) (record.Record, error) {
|
func (ebs *endpointBridgeStorage) Put(r record.Record) (record.Record, error) {
|
||||||
log.Errorf("api bridge: putting %s", r.Key())
|
|
||||||
|
|
||||||
if r.DatabaseKey() == "" {
|
if r.DatabaseKey() == "" {
|
||||||
return nil, database.ErrNotFound
|
return nil, database.ErrNotFound
|
||||||
}
|
}
|
||||||
|
@ -103,7 +98,6 @@ func (ebs *endpointBridgeStorage) Put(r record.Record) (record.Record, error) {
|
||||||
return nil, fmt.Errorf("record not of type *EndpointBridgeRequest, but %T", r)
|
return nil, fmt.Errorf("record not of type *EndpointBridgeRequest, but %T", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Errorf("api bridge: putting %+v", ebr)
|
|
||||||
|
|
||||||
// Override path with key to mitigate sneaky stuff.
|
// Override path with key to mitigate sneaky stuff.
|
||||||
ebr.Path = r.DatabaseKey()
|
ebr.Path = r.DatabaseKey()
|
||||||
|
@ -145,7 +139,6 @@ func callAPI(ebr *EndpointBridgeRequest) (record.Record, error) {
|
||||||
}
|
}
|
||||||
u.RawQuery = query.Encode()
|
u.RawQuery = query.Encode()
|
||||||
}
|
}
|
||||||
log.Errorf("api bridge: calling %s", u.String())
|
|
||||||
|
|
||||||
// Create request and response objects.
|
// Create request and response objects.
|
||||||
r := httptest.NewRequest(ebr.Method, u.String(), bytes.NewBuffer(ebr.Data))
|
r := httptest.NewRequest(ebr.Method, u.String(), bytes.NewBuffer(ebr.Data))
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/safing/portbase/database/record"
|
"github.com/safing/portbase/database/record"
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
)
|
)
|
||||||
|
@ -84,6 +86,7 @@ func init() {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
endpoints = make(map[string]*Endpoint)
|
endpoints = make(map[string]*Endpoint)
|
||||||
|
endpointsMux = mux.NewRouter()
|
||||||
endpointsLock sync.RWMutex
|
endpointsLock sync.RWMutex
|
||||||
|
|
||||||
// ErrInvalidEndpoint is returned when an invalid endpoint is registered.
|
// ErrInvalidEndpoint is returned when an invalid endpoint is registered.
|
||||||
|
@ -106,16 +109,28 @@ func getAPIContext(r *http.Request) (apiEndpoint *Endpoint, apiRequest *Request)
|
||||||
return apiEndpoint, apiRequest
|
return apiEndpoint, apiRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not, get the action from the registry.
|
|
||||||
endpointPath, ok := apiRequest.URLVars["endpointPath"]
|
|
||||||
if !ok {
|
|
||||||
return nil, apiRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
endpointsLock.RLock()
|
endpointsLock.RLock()
|
||||||
defer endpointsLock.RUnlock()
|
defer endpointsLock.RUnlock()
|
||||||
|
|
||||||
apiEndpoint, ok = endpoints[endpointPath]
|
// Get handler for request.
|
||||||
|
// Gorilla does not support handling this on our own very well.
|
||||||
|
// See github.com/gorilla/mux.ServeHTTP for reference.
|
||||||
|
var match mux.RouteMatch
|
||||||
|
var handler http.Handler
|
||||||
|
if endpointsMux.Match(r, &match) {
|
||||||
|
handler = match.Handler
|
||||||
|
apiRequest.Route = match.Route
|
||||||
|
// Add/Override variables instead of replacing.
|
||||||
|
for k, v := range match.Vars {
|
||||||
|
apiRequest.URLVars[k] = v
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, apiRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Errorf("handler: %+v", handler)
|
||||||
|
apiEndpoint, ok = handler.(*Endpoint)
|
||||||
|
log.Errorf("apiEndpoint: %+v", apiEndpoint)
|
||||||
if ok {
|
if ok {
|
||||||
// Cache for next operation.
|
// Cache for next operation.
|
||||||
apiRequest.HandlerCache = apiEndpoint
|
apiRequest.HandlerCache = apiEndpoint
|
||||||
|
@ -139,6 +154,7 @@ func RegisterEndpoint(e Endpoint) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints[e.Path] = &e
|
endpoints[e.Path] = &e
|
||||||
|
endpointsMux.Handle(apiV1Path+e.Path, &e)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +259,17 @@ func (eh *endpointHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiEndpoint.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP handles the http request.
|
||||||
|
func (e *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, apiRequest := getAPIContext(r)
|
||||||
|
if apiRequest == nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodHead:
|
case http.MethodHead:
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
@ -269,32 +296,32 @@ func (eh *endpointHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case apiEndpoint.ActionFunc != nil:
|
case e.ActionFunc != nil:
|
||||||
var msg string
|
var msg string
|
||||||
msg, err = apiEndpoint.ActionFunc(apiRequest)
|
msg, err = e.ActionFunc(apiRequest)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
responseData = []byte(msg)
|
responseData = []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case apiEndpoint.DataFunc != nil:
|
case e.DataFunc != nil:
|
||||||
responseData, err = apiEndpoint.DataFunc(apiRequest)
|
responseData, err = e.DataFunc(apiRequest)
|
||||||
|
|
||||||
case apiEndpoint.StructFunc != nil:
|
case e.StructFunc != nil:
|
||||||
var v interface{}
|
var v interface{}
|
||||||
v, err = apiEndpoint.StructFunc(apiRequest)
|
v, err = e.StructFunc(apiRequest)
|
||||||
if err == nil && v != nil {
|
if err == nil && v != nil {
|
||||||
responseData, err = json.Marshal(v)
|
responseData, err = json.Marshal(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
case apiEndpoint.RecordFunc != nil:
|
case e.RecordFunc != nil:
|
||||||
var rec record.Record
|
var rec record.Record
|
||||||
rec, err = apiEndpoint.RecordFunc(apiRequest)
|
rec, err = e.RecordFunc(apiRequest)
|
||||||
if err == nil && r != nil {
|
if err == nil && r != nil {
|
||||||
responseData, err = marshalRecord(rec, false)
|
responseData, err = marshalRecord(rec, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
case apiEndpoint.HandlerFunc != nil:
|
case e.HandlerFunc != nil:
|
||||||
apiEndpoint.HandlerFunc(w, r)
|
e.HandlerFunc(w, r)
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -309,7 +336,7 @@ func (eh *endpointHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write response.
|
// Write response.
|
||||||
w.Header().Set("Content-Type", apiEndpoint.MimeType+"; charset=utf-8")
|
w.Header().Set("Content-Type", e.MimeType+"; charset=utf-8")
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(len(responseData)))
|
w.Header().Set("Content-Length", strconv.Itoa(len(responseData)))
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
_, err = w.Write(responseData)
|
_, err = w.Write(responseData)
|
||||||
|
|
|
@ -50,6 +50,10 @@ func prep() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := registerModulesEndpoints(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return registerMetaEndpoints()
|
return registerMetaEndpoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue