2017-05-23 11:43:05 -05:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2017-07-17 11:20:57 -05:00
|
|
|
"net/http"
|
2017-09-04 07:14:01 -05:00
|
|
|
"time"
|
2017-07-17 11:20:57 -05:00
|
|
|
|
2017-08-03 09:10:39 -05:00
|
|
|
"github.com/gorilla/mux"
|
2017-05-23 11:43:05 -05:00
|
|
|
"github.com/matrix-org/dendrite/clientapi/auth"
|
|
|
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
2017-09-04 07:14:01 -05:00
|
|
|
"github.com/matrix-org/gomatrixserverlib"
|
2017-05-23 11:43:05 -05:00
|
|
|
"github.com/matrix-org/util"
|
2017-09-28 08:50:40 -05:00
|
|
|
opentracing "github.com/opentracing/opentracing-go"
|
|
|
|
"github.com/opentracing/opentracing-go/ext"
|
2017-05-23 11:43:05 -05:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MakeAuthAPI turns a util.JSONRequestHandler function into an http.Handler which checks the access token in the request.
|
2017-07-17 11:20:57 -05:00
|
|
|
func MakeAuthAPI(metricsName string, deviceDB auth.DeviceDatabase, f func(*http.Request, *authtypes.Device) util.JSONResponse) http.Handler {
|
2017-09-04 07:14:01 -05:00
|
|
|
h := func(req *http.Request) util.JSONResponse {
|
2017-05-23 11:43:05 -05:00
|
|
|
device, resErr := auth.VerifyAccessToken(req, deviceDB)
|
|
|
|
if resErr != nil {
|
|
|
|
return *resErr
|
|
|
|
}
|
|
|
|
return f(req, device)
|
2017-09-04 07:14:01 -05:00
|
|
|
}
|
2017-09-28 08:50:40 -05:00
|
|
|
return MakeExternalAPI(metricsName, h)
|
2017-05-23 11:43:05 -05:00
|
|
|
}
|
|
|
|
|
2017-09-28 08:50:40 -05:00
|
|
|
// MakeExternalAPI turns a util.JSONRequestHandler function into an http.Handler.
|
|
|
|
// This is used for APIs that are called from the internet.
|
|
|
|
func MakeExternalAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler {
|
|
|
|
h := util.MakeJSONAPI(util.NewJSONRequestHandler(f))
|
|
|
|
withSpan := func(w http.ResponseWriter, req *http.Request) {
|
|
|
|
span := opentracing.StartSpan(metricsName)
|
|
|
|
defer span.Finish()
|
|
|
|
req = req.WithContext(opentracing.ContextWithSpan(req.Context(), span))
|
|
|
|
h.ServeHTTP(w, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
return prometheus.InstrumentHandler(metricsName, http.HandlerFunc(withSpan))
|
|
|
|
}
|
|
|
|
|
|
|
|
// MakeInternalAPI turns a util.JSONRequestHandler function into an http.Handler.
|
|
|
|
// This is used for APIs that are internal to dendrite.
|
|
|
|
// If we are passed a tracing context in the request headers then we use that
|
|
|
|
// as the parent of any tracing spans we create.
|
|
|
|
func MakeInternalAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler {
|
|
|
|
h := util.MakeJSONAPI(util.NewJSONRequestHandler(f))
|
|
|
|
withSpan := func(w http.ResponseWriter, req *http.Request) {
|
|
|
|
carrier := opentracing.HTTPHeadersCarrier(req.Header)
|
|
|
|
tracer := opentracing.GlobalTracer()
|
|
|
|
clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier)
|
|
|
|
var span opentracing.Span
|
|
|
|
if err == nil {
|
|
|
|
// Default to a span without RPC context.
|
|
|
|
span = tracer.StartSpan(metricsName)
|
|
|
|
} else {
|
|
|
|
// Set the RPC context.
|
|
|
|
span = tracer.StartSpan(metricsName, ext.RPCServerOption(clientContext))
|
|
|
|
}
|
|
|
|
defer span.Finish()
|
|
|
|
req = req.WithContext(opentracing.ContextWithSpan(req.Context(), span))
|
|
|
|
h.ServeHTTP(w, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
return prometheus.InstrumentHandler(metricsName, http.HandlerFunc(withSpan))
|
2017-05-23 11:43:05 -05:00
|
|
|
}
|
2017-08-03 09:10:39 -05:00
|
|
|
|
2017-09-04 07:14:01 -05:00
|
|
|
// MakeFedAPI makes an http.Handler that checks matrix federation authentication.
|
|
|
|
func MakeFedAPI(
|
|
|
|
metricsName string,
|
|
|
|
serverName gomatrixserverlib.ServerName,
|
|
|
|
keyRing gomatrixserverlib.KeyRing,
|
|
|
|
f func(*http.Request, *gomatrixserverlib.FederationRequest) util.JSONResponse,
|
|
|
|
) http.Handler {
|
|
|
|
h := func(req *http.Request) util.JSONResponse {
|
|
|
|
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
|
|
|
|
req, time.Now(), serverName, keyRing,
|
|
|
|
)
|
|
|
|
if fedReq == nil {
|
|
|
|
return errResp
|
|
|
|
}
|
|
|
|
return f(req, fedReq)
|
|
|
|
}
|
2017-09-28 08:50:40 -05:00
|
|
|
return MakeExternalAPI(metricsName, h)
|
2017-09-04 07:14:01 -05:00
|
|
|
}
|
|
|
|
|
2017-08-03 09:10:39 -05:00
|
|
|
// SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics
|
|
|
|
// listener.
|
|
|
|
func SetupHTTPAPI(servMux *http.ServeMux, apiMux *mux.Router) {
|
2017-09-20 08:54:17 -05:00
|
|
|
// This is deprecated.
|
|
|
|
servMux.Handle("/metrics", prometheus.Handler()) // nolint: megacheck, staticcheck
|
2017-08-03 09:10:39 -05:00
|
|
|
servMux.Handle("/api/", http.StripPrefix("/api", apiMux))
|
|
|
|
}
|