github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/types.go (about)

     1  // Copyright 2017-present Kirill Danshin and Gramework contributors
     2  // Copyright 2019-present Highload LTD (UK CN: 11893420)
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  
    11  package gramework
    12  
    13  import (
    14  	"fmt"
    15  	"sync"
    16  	"time"
    17  
    18  	"github.com/microcosm-cc/bluemonday"
    19  
    20  	"github.com/apex/log"
    21  	"github.com/gramework/utils/nocopy"
    22  	"github.com/valyala/fasthttp"
    23  )
    24  
    25  type (
    26  	ipList struct {
    27  		list map[string]struct{}
    28  		mu   *sync.RWMutex
    29  	}
    30  
    31  	suspect struct {
    32  		hackAttempts int32
    33  	}
    34  
    35  	suspectsList struct {
    36  		list map[string]*suspect
    37  		mu   *sync.RWMutex
    38  	}
    39  
    40  	// App represents a gramework app
    41  	App struct {
    42  		defaultRouter             *Router
    43  		domains                   map[string]*Router
    44  		_                         [8]byte // callback
    45  		firewall                  *firewall
    46  		firewallInit              *sync.Once
    47  		Flags                     *Flags
    48  		flagsQueue                []Flag
    49  		Logger                    log.Interface
    50  		name                      string
    51  		Settings                  Settings
    52  		TLSEmails                 []string
    53  		TLSPort                   uint16
    54  		middlewares               []func(*Context)
    55  		middlewaresAfterRequest   []func(*Context)
    56  		preMiddlewares            []func(*Context)
    57  		domainListLock            *sync.RWMutex
    58  		middlewaresAfterRequestMu *sync.RWMutex
    59  		middlewaresMu             *sync.RWMutex
    60  		preMiddlewaresMu          *sync.RWMutex
    61  		EnableFirewall            bool
    62  		flagsRegistered           bool
    63  		HandleUnknownDomains      bool
    64  		seed                      uintptr
    65  		cookieDomain              string
    66  		cookiePath                string
    67  		NoDefaultPanicHandler     bool
    68  		PanicHandlerNoPoweredBy   bool
    69  		PanicHandlerCustomLayout  string
    70  		internalLog               *log.Entry
    71  
    72  		cookieExpire time.Duration
    73  
    74  		// Gramework Protection's max detections of suspect before ban
    75  		maxHackAttempts *int32
    76  		// Gramework Protection's protected endpoint prefixes
    77  		protectedPrefixes map[string]struct{}
    78  		// Gramework Protection's protected paths of endpoints
    79  		protectedEndpoints map[string]struct{}
    80  		// Gramework Protection's trusted ip list
    81  		trustedIP *ipList
    82  		// Gramework Protection's untrusted (banned) ip list
    83  		untrustedIP *ipList
    84  		// Gramework Protection's suspects ip list
    85  		suspectedIP *suspectsList
    86  
    87  		serverBase       *fasthttp.Server
    88  		runningServers   []runningServerInfo
    89  		runningServersMu *sync.Mutex
    90  
    91  		behind Behind
    92  
    93  		sanitizerPolicy *bluemonday.Policy
    94  
    95  		DefaultCacheOptions *CacheOptions
    96  	}
    97  
    98  	// CacheOptions is a handler cache configuration structure.
    99  	CacheOptions struct {
   100  		// TTL is the time that cached response is valid
   101  		TTL time.Duration
   102  		// Cacheable function returns if current request is cacheable.
   103  		// By deafult, any request with Authentication header or any Cookies will not be cached for security reasons.
   104  		// If you want to cache responses for authorized users, please replace both Cacheable and CacheKey functions
   105  		// to make sure that CacheKey includes something like session id.
   106  		Cacheable func(ctx *Context) bool
   107  		// CacheKey function returns the cache key for current request
   108  		CacheKey func(ctx *Context) []byte
   109  
   110  		// ReadCache allows for cache engine replacement. By default, gramework uses github.com/VictoriaMetrics/fastcache.
   111  		// ReadCache returns the value and boolean if the value was found and still valid.
   112  		ReadCache func(ctx *Context, key []byte) ([]byte, bool)
   113  		// StoreCache allows for cache engine replacement. By default, gramework uses github.com/VictoriaMetrics/fastcache.
   114  		StoreCache func(ctx *Context, key, value []byte, ttl time.Duration)
   115  
   116  		// CacheableHeaders is a list of headers that gramework can cache.
   117  		// Note, that if X-ABC is present both in cacheable and noncacheable header lists,
   118  		// it will not be cached.
   119  		CacheableHeaders []string // slice of canonical header names
   120  		// NonCacheableHeaders is a list of headers that gramework can not cache.
   121  		// Note, that if X-ABC is present both in cacheable and noncacheable header lists,
   122  		// it will not be cached.
   123  		NonCacheableHeaders []string
   124  	}
   125  
   126  	runningServerInfo struct {
   127  		bind string
   128  		srv  *fasthttp.Server
   129  	}
   130  
   131  	contextKey string
   132  
   133  	// Context is a gramework request context
   134  	Context struct {
   135  		*fasthttp.RequestCtx
   136  		nocopy    nocopy.NoCopy
   137  		Logger    log.Interface
   138  		App       *App
   139  		auth      *Auth
   140  		Cookies   Cookies
   141  		requestID string
   142  
   143  		middlewaresShouldStopProcessing bool
   144  		subPrefixes                     []string
   145  		middlewareKilledReq             bool
   146  		writer                          func(p []byte) (int, error)
   147  	}
   148  
   149  	// GQLRequest is a GraphQL request structure
   150  	GQLRequest struct {
   151  		Query         string                 `json:"query"`
   152  		OperationName string                 `json:"operationName"`
   153  		Variables     map[string]interface{} `json:"variables"`
   154  	}
   155  
   156  	// Cookies handles a typical cookie storage
   157  	Cookies struct {
   158  		Storage map[string]string
   159  		Mu      sync.RWMutex
   160  	}
   161  
   162  	// Settings for an App instance
   163  	Settings struct {
   164  		Firewall FirewallSettings
   165  	}
   166  
   167  	// FirewallSettings represents a new firewall settings.
   168  	// Internal firewall representation copies this settings
   169  	// atomically.
   170  	FirewallSettings struct {
   171  		// MaxReqPerMin is a max request per minute count
   172  		MaxReqPerMin int64
   173  		// BlockTimeout in seconds
   174  		BlockTimeout int64
   175  	}
   176  
   177  	firewall struct {
   178  		// Store a copy of current settings
   179  		MaxReqPerMin        *int64
   180  		BlockTimeout        *int64
   181  		blockListMutex      sync.Mutex
   182  		requestCounterMutex sync.Mutex
   183  		blockList           map[string]int64
   184  		requestCounter      map[string]int64
   185  	}
   186  
   187  	// Flags is a flags storage
   188  	Flags struct {
   189  		values map[string]Flag
   190  	}
   191  
   192  	// Flag is a flag representation
   193  	Flag struct {
   194  		Name        string
   195  		Description string
   196  		Default     string
   197  		Value       *string
   198  	}
   199  
   200  	// Router handles internal handler conversion etc.
   201  	Router struct {
   202  		router      *router
   203  		httprouter  *Router
   204  		httpsrouter *Router
   205  		root        *Router
   206  		app         *App
   207  		mu          sync.RWMutex
   208  
   209  		rootHandler []staticHandler
   210  	}
   211  
   212  	// SubRouter handles subs registration
   213  	// like app.Sub("v1").GET("someRoute", "hi")
   214  	SubRouter struct {
   215  		parent   routerable
   216  		prefix   string
   217  		prefixes []string
   218  	}
   219  
   220  	routerable interface {
   221  		handleReg(method, route string, handler interface{}, prefixes []string)
   222  		determineHandler(handler interface{}) func(*Context)
   223  	}
   224  
   225  	// RequestHandler describes a standard request handler type
   226  	RequestHandler func(*Context)
   227  
   228  	// RequestHandlerErr describes a standard request handler with error returned type
   229  	RequestHandlerErr func(*Context) error
   230  
   231  	// Auth is a struct that handles
   232  	// context's basic auth features
   233  	Auth struct {
   234  		login string
   235  		pass  string
   236  
   237  		parsed bool
   238  		// if error occurred during parsing,
   239  		// it will be always returned for current
   240  		// context
   241  		err error
   242  
   243  		ctx *Context
   244  	}
   245  
   246  	// HTML type used to determine prerendered strings
   247  	// as an HTML and give proper content-type
   248  	HTML string
   249  
   250  	// JSON type used to determine prerendered strings
   251  	// as an JSON and give proper content-type
   252  	JSON string
   253  )
   254  
   255  // crazy hack to solve nocopy false positive
   256  var _ = fmt.Sprintf("%v", func() interface{} {
   257  	ctx := Context{}
   258  	return &ctx.nocopy
   259  }())