Skip to content

Commit

Permalink
Merge c8d40d3 into 31f70e4
Browse files Browse the repository at this point in the history
  • Loading branch information
buger committed Sep 9, 2018
2 parents 31f70e4 + c8d40d3 commit abc8617
Show file tree
Hide file tree
Showing 40 changed files with 540 additions and 510 deletions.
8 changes: 8 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1742,3 +1742,11 @@ func ctxSetLoopLimit(r *http.Request, limit int) {
setCtxValue(r, LoopLevelLimit, limit)
}
}

func ctxTraceEnabled(r *http.Request) bool {
return r.Context().Value(Trace) != nil
}

func ctxSetTrace(r *http.Request) {
setCtxValue(r, Trace, true)
}
31 changes: 19 additions & 12 deletions api_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"text/template"
"time"

"github.com/Sirupsen/logrus"
"github.com/rubyist/circuitbreaker"

"github.com/TykTechnologies/gojsonschema"
Expand Down Expand Up @@ -167,17 +168,21 @@ var ServiceNonce string

// MakeSpec will generate a flattened URLSpec from and APIDefinitions' VersionInfo data. paths are
// keyed to the Api version name, which is determined during routing to speed up lookups
func (a APIDefinitionLoader) MakeSpec(def *apidef.APIDefinition) *APISpec {
func (a APIDefinitionLoader) MakeSpec(def *apidef.APIDefinition, logger *logrus.Entry) *APISpec {
spec := &APISpec{}

if logger == nil {
logger = logrus.NewEntry(log)
}

// parse version expiration time stamps
for key, ver := range def.VersionData.Versions {
if ver.Expires == "" || ver.Expires == "-1" {
continue
}
// calculate the time
if t, err := time.Parse("2006-01-02 15:04", ver.Expires); err != nil {
log.WithError(err).WithField("Expires", ver.Expires).Error("Could not parse expiry date for API")
logger.WithError(err).WithField("Expires", ver.Expires).Error("Could not parse expiry date for API")
} else {
ver.ExpiresTs = t
def.VersionData.Versions[key] = ver
Expand All @@ -201,22 +206,24 @@ func (a APIDefinitionLoader) MakeSpec(def *apidef.APIDefinition) *APISpec {

// Create and init the virtual Machine
if config.Global().EnableJSVM {
spec.JSVM.Init(spec)
spec.JSVM.Init(spec, logger)
}

// Set up Event Handlers
log.Debug("INITIALISING EVENT HANDLERS")
if len(def.EventHandlers.Events) > 0 {
logger.Debug("Initializing event handlers")
}
spec.EventPaths = make(map[apidef.TykEvent][]config.TykEventHandler)
for eventName, eventHandlerConfs := range def.EventHandlers.Events {
log.Debug("FOUND EVENTS TO INIT")
logger.Debug("FOUND EVENTS TO INIT")
for _, handlerConf := range eventHandlerConfs {
log.Debug("CREATING EVENT HANDLERS")
logger.Debug("CREATING EVENT HANDLERS")
eventHandlerInstance, err := EventHandlerByName(handlerConf, spec)

if err != nil {
log.Error("Failed to init event handler: ", err)
logger.Error("Failed to init event handler: ", err)
} else {
log.Debug("Init Event Handler: ", eventName)
logger.Debug("Init Event Handler: ", eventName)
spec.EventPaths[eventName] = append(spec.EventPaths[eventName], eventHandlerInstance)
}

Expand All @@ -234,7 +241,7 @@ func (a APIDefinitionLoader) MakeSpec(def *apidef.APIDefinition) *APISpec {
pathSpecs, whiteListSpecs = a.getExtendedPathSpecs(v, spec)

} else {
log.Warning("Legacy path detected! Upgrade to extended.")
logger.Warning("Legacy path detected! Upgrade to extended.")
pathSpecs, whiteListSpecs = a.getPathSpecs(v)
}
spec.RxPaths[v.Name] = pathSpecs
Expand Down Expand Up @@ -321,7 +328,7 @@ func (a APIDefinitionLoader) FromDashboardService(endpoint, secret string) ([]*A
// Process
var specs []*APISpec
for _, def := range apiDefs {
spec := a.MakeSpec(def)
spec := a.MakeSpec(def, nil)
specs = append(specs, spec)
}

Expand Down Expand Up @@ -383,7 +390,7 @@ func (a APIDefinitionLoader) processRPCDefinitions(apiCollection string) []*APIS
def.Proxy.ListenPath = newListenPath
}

spec := a.MakeSpec(def)
spec := a.MakeSpec(def, nil)
specs = append(specs, spec)
}

Expand Down Expand Up @@ -413,7 +420,7 @@ func (a APIDefinitionLoader) FromDir(dir string) []*APISpec {
}
def := a.ParseDefinition(f)
f.Close()
spec := a.MakeSpec(def)
spec := a.MakeSpec(def, nil)
specs = append(specs, spec)
}
return specs
Expand Down
2 changes: 1 addition & 1 deletion api_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
func createDefinitionFromString(defStr string) *APISpec {
loader := APIDefinitionLoader{}
def := loader.ParseDefinition(strings.NewReader(defStr))
spec := loader.MakeSpec(def)
spec := loader.MakeSpec(def, nil)
return spec
}

Expand Down
111 changes: 43 additions & 68 deletions api_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,21 @@ func prepareStorage() (storage.RedisCluster, storage.RedisCluster, storage.Redis
return redisStore, redisOrgStore, healthStore, &rpcAuthStore, &rpcOrgStore
}

func skipSpecBecauseInvalid(spec *APISpec) bool {
func skipSpecBecauseInvalid(spec *APISpec, logger *logrus.Entry) bool {

if spec.Proxy.ListenPath == "" {
mainLog.WithFields(logrus.Fields{
"org_id": spec.OrgID,
"api_id": spec.APIID,
}).Error("Listen path is empty, skipping API ID: ", spec.APIID)
logger.Error("Listen path is empty")
return true
}

if strings.Contains(spec.Proxy.ListenPath, " ") {
mainLog.WithFields(logrus.Fields{
"org_id": spec.OrgID,
"api_id": spec.APIID,
}).Error("Listen path contains spaces, is invalid, skipping API ID: ", spec.APIID)
logger.Error("Listen path contains spaces, is invalid")
return true
}

_, err := url.Parse(spec.Proxy.TargetURL)
if err != nil {
mainLog.WithFields(logrus.Fields{
"org_id": spec.OrgID,
"api_id": spec.APIID,
}).Error("couldn't parse target URL: ", err)
logger.Error("couldn't parse target URL: ", err)
return true
}

Expand Down Expand Up @@ -102,19 +93,22 @@ func countApisByListenHash(specs []*APISpec) map[string]int {

func processSpec(spec *APISpec, apisByListen map[string]int,
redisStore, redisOrgStore, healthStore, rpcAuthStore, rpcOrgStore storage.Handler,
subrouter *mux.Router) *ChainObject {
subrouter *mux.Router, logger *logrus.Entry) *ChainObject {

var chainDef ChainObject
chainDef.Subrouter = subrouter

var coprocessLog = log.WithFields(logrus.Fields{
"prefix": "coprocess",
logger = logger.WithFields(logrus.Fields{
"org_id": spec.OrgID,
"api_id": spec.APIID,
"api_name": spec.Name,
})

mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Info("Loading API")
var coprocessLog = logger.WithFields(logrus.Fields{
"prefix": "coprocess",
})

logger.Info("Loading API")

if len(spec.TagHeaders) > 0 {
// Ensure all headers marked for tagging are lowercase
Expand All @@ -126,10 +120,8 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
spec.TagHeaders = lowerCaseHeaders
}

if skipSpecBecauseInvalid(spec) {
mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Warning("Skipped!")
if skipSpecBecauseInvalid(spec, logger) {
logger.Warning("Spec not valid, skipped!")
chainDef.Skip = true
return &chainDef
}
Expand All @@ -156,10 +148,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
}
}
if pathModified {
mainLog.WithFields(logrus.Fields{
"org_id": spec.OrgID,
"api_id": spec.APIID,
}).Error("Listen path collision, changed to ", spec.Proxy.ListenPath)
logger.Error("Listen path collision, changed to ", spec.Proxy.ListenPath)
}

// Set up LB targets:
Expand Down Expand Up @@ -205,9 +194,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
var prefix string
if spec.CustomMiddlewareBundle != "" {
if err := loadBundle(spec); err != nil {
mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Error("Couldn't load bundle")
logger.Error("Couldn't load bundle")
}
tykBundlePath := filepath.Join(config.Global().MiddlewarePath, "bundles")
bundleNameHash := md5.New()
Expand All @@ -216,9 +203,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
prefix = filepath.Join(tykBundlePath, bundlePath)
}

mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Debug("Loading Middleware")
logger.Debug("Initializing API")
var mwPaths []string

mwPaths, mwAuthCheckFunc, mwPreFuncs, mwPostFuncs, mwPostAuthCheckFuncs, mwDriver = loadCustomMiddleware(spec)
Expand All @@ -232,12 +217,12 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
}

if spec.UseOauth2 {
log.Debug("Loading OAuth Manager")
logger.Debug("Loading OAuth Manager")
oauthManager := addOAuthHandlers(spec, subrouter)
log.Debug("-- Added OAuth Handlers")
logger.Debug("-- Added OAuth Handlers")

spec.OAuthManager = oauthManager
log.Debug("Done loading OAuth Manager")
logger.Debug("Done loading OAuth Manager")
}

enableVersionOverrides := false
Expand All @@ -253,9 +238,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

var proxy ReturningHttpHandler
if enableVersionOverrides {
mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Info("Multi target enabled")
logger.Info("Multi target enabled")
proxy = NewMultiTargetProxy(spec)
} else {
proxy = TykNewSingleHostReverseProxy(spec.target, spec)
Expand All @@ -264,7 +247,8 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
// Create the response processors
createResponseMiddlewareChain(spec)

baseMid := BaseMiddleware{spec, proxy}
baseMid := BaseMiddleware{Spec: spec, Proxy: proxy, logger: logger}

for _, v := range baseMid.Spec.VersionData.Versions {
if len(v.ExtendedPaths.CircuitBreaker) > 0 {
baseMid.Spec.CircuitBreakerEnabled = true
Expand All @@ -282,9 +266,7 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

if spec.UseKeylessAccess {
chainDef.Open = true
mainLog.WithFields(logrus.Fields{
"api_name": spec.Name,
}).Info("Checking security policy: Open")
logger.Info("Checking security policy: Open")

// Add pre-process MW
chainArray := []alice.Constructor{}
Expand Down Expand Up @@ -362,23 +344,23 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

// Select the keying method to use for setting session states
if mwAppendEnabled(&authArray, &Oauth2KeyExists{baseMid}) {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: OAuth")
logger.Info("Checking security policy: OAuth")
}

if mwAppendEnabled(&authArray, &BasicAuthKeyIsValid{baseMid, cache.New(60*time.Second, 60*time.Minute)}) {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: Basic")
logger.Info("Checking security policy: Basic")
}

if mwAppendEnabled(&authArray, &HMACMiddleware{BaseMiddleware: baseMid}) {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: HMAC")
logger.Info("Checking security policy: HMAC")
}

if mwAppendEnabled(&authArray, &JWTMiddleware{baseMid}) {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: JWT")
logger.Info("Checking security policy: JWT")
}

if mwAppendEnabled(&authArray, &OpenIDMW{BaseMiddleware: baseMid}) {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: OpenID")
logger.Info("Checking security policy: OpenID")
}

coprocessAuth := EnableCoProcess && mwDriver != apidef.OttoDriver && spec.EnableCoProcessAuth
Expand All @@ -394,13 +376,13 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

if ottoAuth {

mainLog.Info("----> Checking security policy: JS Plugin")
logger.Info("----> Checking security policy: JS Plugin")

authArray = append(authArray, createDynamicMiddleware(mwAuthCheckFunc.Name, true, false, baseMid))
}

if spec.UseStandardAuth || len(authArray) == 0 {
mainLog.WithField("api_name", spec.Name).Info("Checking security policy: Token")
logger.Info("Checking security policy: Token")
authArray = append(authArray, createMiddleware(&AuthKey{baseMid}))
}

Expand Down Expand Up @@ -437,13 +419,9 @@ func processSpec(spec *APISpec, apisByListen map[string]int,
}
}

mainLog.WithField("api_name", spec.Name).Debug("Custom middleware completed processing")

// Use createMiddleware(&ModifiedMiddleware{baseMid}) to run custom middleware
chain = alice.New(chainArray...).Then(&DummyProxyHandler{SH: SuccessHandler{baseMid}})

log.Debug("Chain completed")

var simpleArray []alice.Constructor
mwAppendEnabled(&simpleArray, &IPWhiteListMiddleware{baseMid})
mwAppendEnabled(&simpleArray, &IPBlackListMiddleware{BaseMiddleware: baseMid})
Expand All @@ -455,28 +433,24 @@ func processSpec(spec *APISpec, apisByListen map[string]int,

rateLimitPath := spec.Proxy.ListenPath + "tyk/rate-limits/"

mainLog.WithField("api_name", spec.Name).Debug("Rate limit endpoint is: ", rateLimitPath)
logger.Debug("Rate limit endpoint is: ", rateLimitPath)

chainDef.RateLimitPath = rateLimitPath
chainDef.RateLimitChain = alice.New(simpleArray...).
Then(http.HandlerFunc(userRatesCheck))
}

mainLog.WithField("api_name", spec.Name).Debug("Setting Listen Path: ", spec.Proxy.ListenPath)
logger.Debug("Setting Listen Path: ", spec.Proxy.ListenPath)

chainDef.ThisHandler = chain
chainDef.ListenOn = spec.Proxy.ListenPath + "{rest:.*}"

if config.Global().UseRedisLog {
log.WithFields(logrus.Fields{
"prefix": "gateway",
"user_ip": "--",
"server_name": "--",
"user_id": "--",
"org_id": spec.OrgID,
"api_id": spec.APIID,
}).Info("Loaded: ", spec.Name)
}
logger.WithFields(logrus.Fields{
"prefix": "gateway",
"user_ip": "--",
"server_name": "--",
"user_id": "--",
}).Info("API Loaded")

return &chainDef
}
Expand Down Expand Up @@ -508,7 +482,7 @@ type DummyProxyHandler struct {
func (d *DummyProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if found, err := isLoop(r); found {
if err != nil {
handler := ErrorHandler{d.SH.Base()}
handler := ErrorHandler{*d.SH.Base()}
handler.HandleError(w, r, err.Error(), http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -618,7 +592,8 @@ func loadApps(specs []*APISpec, muxer *mux.Router) {
subrouter = muxer
}

chainObj := processSpec(spec, apisByListen, redisStore, redisOrgStore, healthStore, rpcAuthStore, rpcOrgStore, subrouter)
chainObj := processSpec(spec, apisByListen, redisStore, redisOrgStore, healthStore, rpcAuthStore, rpcOrgStore, subrouter, logrus.NewEntry(log))

chainObj.Index = i
chainChannel <- chainObj
apisMu.Lock()
Expand Down

0 comments on commit abc8617

Please sign in to comment.