diff --git a/config/dev.yml b/config/dev.yml index 8013e38..ae8c982 100644 --- a/config/dev.yml +++ b/config/dev.yml @@ -45,6 +45,13 @@ cors_allowed_origins: ["*"] # Debug Cross Origin Resource Sharing requests cors_debug: true +# Default API path prefix is /api you can change it if you like +# api_path: "/data" + +# Cache-Control header can help cache queries if your CDN supports cache-control +# on POST requests (does not work with not mutations) +# cache_control: "public, max-age=300, s-maxage=600" + # Postgres related environment Variables # SG_DATABASE_HOST # SG_DATABASE_PORT diff --git a/core/core.go b/core/core.go index afe9553..0cd72ed 100644 --- a/core/core.go +++ b/core/core.go @@ -14,6 +14,11 @@ import ( "github.com/valyala/fasttemplate" ) +const ( + OpQuery int = iota + OpMutation +) + type extensions struct { Tracing *trace `json:"tracing,omitempty"` } @@ -329,7 +334,20 @@ func (c *scontext) executeRoleQuery(tx *sql.Tx) (string, error) { return role, nil } -func (r *Result) Operation() string { +func (r *Result) Operation() int { + switch r.op { + case qcode.QTQuery: + return OpQuery + + case qcode.QTMutation, qcode.QTInsert, qcode.QTUpdate, qcode.QTUpsert, qcode.QTDelete: + return OpMutation + + default: + return -1 + } +} + +func (r *Result) OperationName() string { return r.op.String() } diff --git a/go.mod b/go.mod index de4cad1..0208881 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/daaku/go.zipexe v1.0.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dlclark/regexp2 v1.2.0 // indirect - github.com/dop251/goja v0.0.0-20200414142002-77e84ffb8c65 + github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0 github.com/fsnotify/fsnotify v1.4.9 github.com/garyburd/redigo v1.6.0 github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect diff --git a/go.sum b/go.sum index 323b23c..a85d515 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dop251/goja v0.0.0-20200414142002-77e84ffb8c65 h1:Nud597JuGCF/MScrb6NNVDRgmuk8X7w3pFc5GvSsm5E= -github.com/dop251/goja v0.0.0-20200414142002-77e84ffb8c65/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0 h1:EfFAcaAwGai/wlDCWwIObHBm3T2C2CCPX/SaS0fpOJ4= +github.com/dop251/goja v0.0.0-20200424152103-d0b8fda54cd0/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/friendsofgo/graphiql v0.2.2/go.mod h1:8Y2kZ36AoTGWs78+VRpvATyt3LJBx0SZXmay80ZTRWo= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/internal/serv/api.go b/internal/serv/api.go index aafdd36..09c1b22 100644 --- a/internal/serv/api.go +++ b/internal/serv/api.go @@ -46,6 +46,7 @@ type Serv struct { AllowedOrigins []string `mapstructure:"cors_allowed_origins"` DebugCORS bool `mapstructure:"cors_debug"` APIPath string `mapstructure:"api_path"` + CacheControl string `mapstructure:"cache_control"` Auth auth.Auth Auths []auth.Auth diff --git a/internal/serv/http.go b/internal/serv/http.go index 8a512b8..812285b 100644 --- a/internal/serv/http.go +++ b/internal/serv/http.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "net/http" + "github.com/dosco/super-graph/core" "github.com/dosco/super-graph/internal/serv/internal/auth" "github.com/rs/cors" "go.uber.org/zap" @@ -84,15 +85,19 @@ func apiV1(w http.ResponseWriter, r *http.Request) { log.Printf("DBG query %s: %s", res.QueryName(), res.SQL()) } - if err != nil { - renderErr(w, err) - } else { + if err == nil { + if len(conf.CacheControl) != 0 && res.Operation() == core.OpQuery { + w.Header().Set("Cache-Control", conf.CacheControl) + } json.NewEncoder(w).Encode(res) + + } else { + renderErr(w, err) } if doLog && logLevel >= LogLevelInfo { zlog.Info("success", - zap.String("op", res.Operation()), + zap.String("op", res.OperationName()), zap.String("name", res.QueryName()), zap.String("role", res.Role()), ) diff --git a/internal/serv/tmpl/dev.yml b/internal/serv/tmpl/dev.yml index a4ed871..ea0b938 100644 --- a/internal/serv/tmpl/dev.yml +++ b/internal/serv/tmpl/dev.yml @@ -46,6 +46,13 @@ cors_allowed_origins: ["*"] # Debug Cross Origin Resource Sharing requests cors_debug: false +# Default API path prefix is /api you can change it if you like +# api_path: "/data" + +# Cache-Control header can help cache queries if your CDN supports cache-control +# on POST requests (does not work with not mutations) +# cache_control: "public, max-age=300, s-maxage=600" + # Postgres related environment Variables # SG_DATABASE_HOST # SG_DATABASE_PORT diff --git a/internal/serv/tmpl/prod.yml b/internal/serv/tmpl/prod.yml index a40fa57..e7b675a 100644 --- a/internal/serv/tmpl/prod.yml +++ b/internal/serv/tmpl/prod.yml @@ -49,6 +49,13 @@ reload_on_config_change: false # Debug Cross Origin Resource Sharing requests # cors_debug: false +# Default API path prefix is /api you can change it if you like +# api_path: "/data" + +# Cache-Control header can help cache queries if your CDN supports cache-control +# on POST requests (does not work with not mutations) +# cache_control: "public, max-age=300, s-maxage=600" + # Postgres related environment Variables # SG_DATABASE_HOST # SG_DATABASE_PORT