diff --git a/backends/redis_test.go b/backends/redis_test.go index 124a011..7812e9f 100644 --- a/backends/redis_test.go +++ b/backends/redis_test.go @@ -52,7 +52,8 @@ func (suite *RedisBackendTestSuite) TestWriteCacheInRedis() { suite.Equal(len(content), backend.Length()) - backend.Close() + err = backend.Close() + suite.Nil(err) reader, err := backend.GetReader() suite.Nil(err) diff --git a/cache_test.go b/cache_test.go index 8499541..cf1c65c 100644 --- a/cache_test.go +++ b/cache_test.go @@ -1,11 +1,13 @@ package httpcache import ( + "io/ioutil" "net/http" "net/http/httptest" "testing" "time" + "github.com/sillygod/cdp-cache/backends" "github.com/stretchr/testify/suite" ) @@ -16,10 +18,10 @@ func makeRequest(url string, headers http.Header) *http.Request { } func makeResponse(code int, headers http.Header) *Response { - return &Response{ - Code: code, - snapHeader: headers, - } + response := NewResponse() + response.Code = code + response.snapHeader = headers + return response } func makeHeader(key string, value string) http.Header { @@ -142,7 +144,81 @@ func (suite *RuleMatcherTestSuite) TestHeaderNotMatched() { suite.False(match) } +type EntryTestSuite struct { + suite.Suite + config *Config +} + +func (suite *EntryTestSuite) SetupSuite() { + err := backends.InitGroupCacheRes(50 * 1024 * 1024) + suite.Nil(err) + suite.config = getDefaultConfig() +} + +func (suite *EntryTestSuite) TestEntryWritePublicResponse() { + + req := makeRequest("/", http.Header{}) + res := makeResponse(200, makeHeader("Cache-Control", "max-age=43200")) + entry := NewEntry("unique_key", req, res, suite.config) + + suite.Equal("unique_key", entry.Key()) + rw := httptest.NewRecorder() + + suite.config.Type = inMemory + input := []byte(`rain cats and dogs`) + + go func() { + entry.Response.Write(input) + entry.Response.Close() // we can write the entry's body to rw after closing upstream response + }() + + entry.setBackend(req.Context(), suite.config) + + entry.WriteBodyTo(rw) + result, err := ioutil.ReadAll(rw.Result().Body) + suite.Nil(err) + suite.Equal(input, result) +} + +func (suite *EntryTestSuite) TestEntryWritePrivateResponse() { + req := makeRequest("/", http.Header{}) + res := makeResponse(502, http.Header{}) + entry := NewEntry("unique_key2", req, res, suite.config) + + go func() { + entry.Response.Close() + }() + + rw := httptest.NewRecorder() + entry.WriteBodyTo(rw) + suite.Equal(502, rw.Code) +} + +func (suite *EntryTestSuite) TearDownSuite() { + err := backends.ReleaseGroupCacheRes() + suite.Nil(err) +} + +type HTTPCacheTestSuite struct { + suite.Suite + config *Config +} + +func (suite *HTTPCacheTestSuite) SetupSuite() { + err := backends.InitGroupCacheRes(50 * 1024 * 1024) + suite.Nil(err) + suite.config = getDefaultConfig() +} + +// TODO: add http cache test + +func (suite *HTTPCacheTestSuite) TearDownSuite() { + err := backends.ReleaseGroupCacheRes() + suite.Nil(err) +} + func TestCacheStatusTestSuite(t *testing.T) { suite.Run(t, new(CacheStatusTestSuite)) suite.Run(t, new(RuleMatcherTestSuite)) + suite.Run(t, new(EntryTestSuite)) } diff --git a/caddyfile.go b/caddyfile.go index 80eef86..dd8f47d 100644 --- a/caddyfile.go +++ b/caddyfile.go @@ -43,7 +43,7 @@ var ( defaultcacheBucketsNum = 256 defaultCacheMaxMemorySize = GB // default is 1 GB defaultRedisConnectionSetting = "localhost:6379 0" - defaultCacheKeyTemplate = "{http.request.method} {http.request.host}{http.request.uri.path} {http.request.uri.query}" + defaultCacheKeyTemplate = "{http.request.method} {http.request.host}{http.request.uri.path}?{http.request.uri.query}" // Note: prevent character space in the key // the key is refereced from github.com/caddyserver/caddy/v2/modules/caddyhttp.addHTTPVarsToReplacer ) @@ -63,7 +63,9 @@ const ( // format: addr db password or addr db or addr // ex. // localhost:6789 0 => connect without password. only index and host:port provided + // the following are keys for extensions keyDistributed = "distributed" + keyInfluxLog = "influxlog" ) func init() { @@ -190,11 +192,11 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } cacheRule := &HeaderRuleMatcher{Header: args[0], Value: args[1:]} - d, _ := json.Marshal(cacheRule) + data, _ := json.Marshal(cacheRule) config.RuleMatchersRaws = append(config.RuleMatchersRaws, RuleMatcherRawWithType{ Type: MatcherTypeHeader, - Data: d, + Data: data, }) case keyMatchPath: @@ -202,11 +204,11 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return d.Err("Invalid usage of match_path in cache config.") } cacheRule := &PathRuleMatcher{Path: args[0]} - d, _ := json.Marshal(cacheRule) + data, _ := json.Marshal(cacheRule) config.RuleMatchersRaws = append(config.RuleMatchersRaws, RuleMatcherRawWithType{ Type: MatcherTypePath, - Data: d, + Data: data, }) case keyCacheKey: @@ -238,7 +240,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { unm, ok := mod.New().(caddyfile.Unmarshaler) if !ok { - return d.Errf("distributed module '%s' is not a Caddfile unmarshaler", mod) + return d.Errf("distributed module '%s' is not a Caddyfile unmarshaler", mod) } err = unm.UnmarshalCaddyfile(d.NewFromNextSegment()) @@ -248,6 +250,13 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { h.DistributedRaw = caddyconfig.JSONModuleObject(unm, "distributed", "consul", nil) + // case keyInfluxLog: + // raw, err := setupInfluxLog(keyInfluxLog, d, args) + // if err != nil { + // return err + // } + // h.InfluxLogRaw = raw + default: return d.Err("Unknown cache parameter: " + parameter) } @@ -259,6 +268,28 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return nil } +func setupInfluxLog(key string, d *caddyfile.Dispenser, args []string) (json.RawMessage, error) { + + mod, err := caddy.GetModule("caddy.logging.writers." + key) + if err != nil { + return nil, d.Errf("getting influxlog module '%s': '%v'", mod, err) + } + + unm, ok := mod.New().(caddyfile.Unmarshaler) + if !ok { + return nil, d.Errf("influxlog module '%s' is not a Caddyfile unmarshaler", mod) + } + + err = unm.UnmarshalCaddyfile(d.NewFromNextSegment()) + if err != nil { + return nil, err + } + + raw := caddyconfig.JSONModuleObject(unm, "mylog", "influxlog", nil) + + return raw, nil +} + // Interface guards var ( _ caddyfile.Unmarshaler = (*Handler)(nil) diff --git a/caddyfile_test.go b/caddyfile_test.go index 5dc98f0..59e1c48 100644 --- a/caddyfile_test.go +++ b/caddyfile_test.go @@ -63,6 +63,19 @@ func (suite *CaddyfileTestSuite) TestInvalidParameter() { suite.Error(err, "invalid parameter") } +func (suite *CaddyfileTestSuite) TestRedisConnectionSetting() { + h := httpcaddyfile.Helper{ + Dispenser: caddyfile.NewTestDispenser(` + http_cache { + redis_connection_setting localhost:6379 2 pass 5 + } + `), + } + + _, err := parseCaddyfile(h) + suite.Error(err, "invalid usage of redis_connection_setting in cache config.") +} + func (suite *CaddyfileTestSuite) TestDistributedCacheConfig() { h := httpcaddyfile.Helper{ Dispenser: caddyfile.NewTestDispenser(` diff --git a/cmd/main.go b/cmd/main.go index 5571385..7febce9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -31,6 +31,7 @@ import ( // plug in Caddy modules here _ "github.com/sillygod/cdp-cache" + _ "github.com/sillygod/cdp-cache/extends/influxlog" _ "github.com/caddyserver/caddy/v2/modules/standard" ) diff --git a/example/influxdb_monitor/Caddyfile b/example/influxdb_monitor/Caddyfile new file mode 100644 index 0000000..bdb3def --- /dev/null +++ b/example/influxdb_monitor/Caddyfile @@ -0,0 +1,41 @@ +{ + order http_cache before reverse_proxy + admin 0.0.0.0:7777 + debug +} + +:9991 { + reverse_proxy { + to localhost:9995 + } + + http_cache { + cache_type in_memory + match_path / + + } + + log { + output influxlog { + addr http://localhost:8086 + token "user:pass1234" + organization "" + bucket telegraf + # For influxDB 1.8 the token should follow the rule below + # https://github.com/influxdata/influxdb-client-go#influxdb-18-api-compatibility + } + level debug + } + + +} + +:9995 { + header Cache-control "public" + root * /tmp/caddy-benchmark + file_server + + log { + level info + } +} \ No newline at end of file diff --git a/example/influxdb_monitor/docker-compose.yml b/example/influxdb_monitor/docker-compose.yml new file mode 100644 index 0000000..7552de3 --- /dev/null +++ b/example/influxdb_monitor/docker-compose.yml @@ -0,0 +1,88 @@ +version: "3.7" + +services: + influxdb: + image: influxdb:1.8.1 + volumes: + - influxdb:/var/lib/influxdb + - ./example/influxdb_monitor/influxdb.conf:/etc/influxdb/influxdb.conf + environment: + - INFLUXDB_ADMIN_USER=admin + - INFLUXDB_ADMIN_PASSWORD=pass1234 + - INFLUXDB_USER=user + - INFLUXDB_USER_PASSWORD=pass1234 + + restart: always + networks: + - influxdata + + + ports: + - "8086:8086" + - "8082:8082" + + # telegraf to collects the syslog + telegraf: + image: telegraf:1.15.1 + environment: + - HOSTNAME=songa-telegraf + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./example/influxdb_monitor/telegraf.conf:/etc/telegraf/telegraf.conf + + restart: always + + networks: + - influxdata + + depends_on: + - influxdb + + chronograf: + image: chronograf:1.8.4 + environment: + - RESOURCES_PATH=/usr/share/chronograf/resources + volumes: + - chronograf:/var/lib/chronograf + ports: + - "8888:8888" + + restart: always + + networks: + - influxdata + + depends_on: + - influxdb + - telegraf + + # in the future add the grafana log panel + + # cdp to write the log as syslog + cdp: &cdp-source + image: golang:1.14.2 + container_name: cdp + volumes: + - cdp:/go/ + - go-build-cache:/root/.cache/go-build + - .:${PROJECT_PATH} + + command: > + sh -c "echo 'spin up caddy proxy cache...' && + cd ${PROJECT_PATH} && + go run $PROJECT_PATH/cmd/main.go run --config example/influxdb_monitor/Caddyfile" + + ports: + - "9991:9991" + environment: + - PROJECT_PATH=${PROJECT_PATH} + + +volumes: + cdp: + go-build-cache: + influxdb: + chronograf: + +networks: + influxdata: diff --git a/example/influxdb_monitor/influxdb.conf b/example/influxdb_monitor/influxdb.conf new file mode 100644 index 0000000..29d5bab --- /dev/null +++ b/example/influxdb_monitor/influxdb.conf @@ -0,0 +1,124 @@ +reporting-disabled = false +bind-address = ":8088" + +[meta] + dir = "/var/lib/influxdb/meta" + retention-autocreate = true + logging-enabled = true + +[data] + dir = "/var/lib/influxdb/data" + wal-dir = "/var/lib/influxdb/wal" + query-log-enabled = true + cache-max-memory-size = 1073741824 + cache-snapshot-memory-size = 26214400 + cache-snapshot-write-cold-duration = "10m0s" + compact-full-write-cold-duration = "4h0m0s" + max-series-per-database = 1000000 + max-values-per-tag = 100000 + index-version = "tsi1" + trace-logging-enabled = false + +[coordinator] + write-timeout = "10s" + max-concurrent-queries = 0 + query-timeout = "0s" + log-queries-after = "0s" + max-select-point = 0 + max-select-series = 0 + max-select-buckets = 0 + +[retention] + enabled = true + check-interval = "30m0s" + +[shard-precreation] + enabled = true + check-interval = "10m0s" + advance-period = "30m0s" + +[monitor] + store-enabled = true + store-database = "_internal" + store-interval = "10s" + +[subscriber] + enabled = true + http-timeout = "30s" + insecure-skip-verify = false + ca-certs = "" + write-concurrency = 40 + write-buffer-size = 1000 + +[http] + enabled = true + flux-enabled = true + bind-address = ":8086" + auth-enabled = false + log-enabled = true + write-tracing = false + pprof-enabled = true + https-enabled = false + https-certificate = "/etc/ssl/influxdb.pem" + https-private-key = "" + max-row-limit = 0 + max-connection-limit = 0 + shared-secret = "" + realm = "InfluxDB" + unix-socket-enabled = false + bind-socket = "/var/run/influxdb.sock" + +[[graphite]] + enabled = false + bind-address = ":2003" + database = "graphite" + retention-policy = "" + protocol = "tcp" + batch-size = 5000 + batch-pending = 10 + batch-timeout = "1s" + consistency-level = "one" + separator = "." + udp-read-buffer = 0 + +[[collectd]] + enabled = false + bind-address = ":25826" + database = "collectd" + retention-policy = "" + batch-size = 5000 + batch-pending = 10 + batch-timeout = "10s" + read-buffer = 0 + typesdb = "/usr/share/collectd/types.db" + security-level = "none" + auth-file = "/etc/collectd/auth_file" + +[[opentsdb]] + enabled = false + bind-address = ":4242" + database = "opentsdb" + retention-policy = "" + consistency-level = "one" + tls-enabled = false + certificate = "/etc/ssl/influxdb.pem" + batch-size = 1000 + batch-pending = 5 + batch-timeout = "1s" + log-point-errors = true + +[[udp]] + enabled = true + bind-address = ":8089" + database = "udp" + retention-policy = "" + batch-size = 5000 + batch-pending = 10 + read-buffer = 0 + batch-timeout = "1s" + precision = "" + +[continuous_queries] + log-enabled = true + enabled = true + run-interval = "1s" diff --git a/example/influxdb_monitor/readme.org b/example/influxdb_monitor/readme.org new file mode 100644 index 0000000..e4d6571 --- /dev/null +++ b/example/influxdb_monitor/readme.org @@ -0,0 +1,7 @@ +* Influxdb Monitor Example + +Let's try to monitor our cache server with influxdb + +#+begin_src sh +PROJECT_PATH=/app docker-compose --project-directory=./ -f example/influxdb_monitor/docker-compose.yml up +#+end_src diff --git a/example/influxdb_monitor/telegraf.conf b/example/influxdb_monitor/telegraf.conf new file mode 100644 index 0000000..219241d --- /dev/null +++ b/example/influxdb_monitor/telegraf.conf @@ -0,0 +1,45 @@ +[agent] + interval = "5s" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "0s" + flush_interval = "5s" + flush_jitter = "0s" + precision = "" + debug = false + quiet = false + logfile = "" + hostname = "$HOSTNAME" + omit_hostname = false + +[[outputs.influxdb]] + urls = ["http://influxdb:8086"] + database = "telegraf" + username = "" + password = "" + retention_policy = "" + write_consistency = "any" + timeout = "5s" + +[[inputs.docker]] + endpoint = "unix:///var/run/docker.sock" + container_names = [] + timeout = "5s" + perdevice = true + total = false + +[[inputs.cpu]] +[[inputs.system]] +[[inputs.influxdb]] + urls = ["http://influxdb:8086/debug/vars"] +[[inputs.syslog]] +# ## Specify an ip or hostname with port - eg., tcp://localhost:6514, tcp://10.0.0.1:6514 +# ## Protocol, address and port to host the syslog receiver. +# ## If no host is specified, then localhost is used. +# ## If no port is specified, 6514 is used (RFC5425#section-4.1). + server = "tcp://localhost:6514" + +# [[inputs.docker_log]] +# endpoint = "unix:///var/run/docker.sock" +# timeout = "5s" \ No newline at end of file diff --git a/extends/distributed/caddyfile.go b/extends/distributed/caddyfile.go index 3df4ab3..9314ac5 100644 --- a/extends/distributed/caddyfile.go +++ b/extends/distributed/caddyfile.go @@ -26,10 +26,12 @@ func getDefaultConfig() *Config { } } -// UnmarshalCaddyfile deserializes Caddyfile tokens into caddy cache's Handler +// UnmarshalCaddyfile deserializes Caddyfile tokens into consulservice's config // distributed consul { // service_name // addr +// token +// health_url // } func (c *ConsulService) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { config := getDefaultConfig() diff --git a/extends/influxlog/Caddyfile.go b/extends/influxlog/Caddyfile.go new file mode 100644 index 0000000..1799188 --- /dev/null +++ b/extends/influxlog/Caddyfile.go @@ -0,0 +1,71 @@ +package influxlog + +import "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + +const ( + keyAddr = "addr" + keyToken = "token" + keyOrganization = "organization" + keyBucket = "bucket" +) + +// Config is the configuration for the influxLogWriter +type Config struct { + Addr string `json:"addr"` + Token string `json:"token"` + Organization string `json:"organization"` + Bucket string `json:"bucket"` +} + +func getDefaultConfig() *Config { + return &Config{ + Addr: "localhost:9999", + Token: "", + } +} + +// UnmarshalCaddyfile deserializes Caddyfile tokens into influxlog config +// influxlog { +// addr +// token +// organization +// bucket +// } +func (s *Writer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { + config := getDefaultConfig() + + for d.Next() { + for d.NextBlock(0) { + + parameter := d.Val() + args := d.RemainingArgs() + + switch parameter { + + case keyAddr: + config.Addr = args[0] + + case keyToken: + config.Token = args[0] + + case keyOrganization: + config.Organization = args[0] + + case keyBucket: + config.Bucket = args[0] + + default: + return d.Errf("unrecognized subdirective %s", parameter) + + } + + } + } + + s.Config = config + return nil +} + +var ( + _ caddyfile.Unmarshaler = (*Writer)(nil) +) diff --git a/extends/influxlog/influx.go b/extends/influxlog/influx.go new file mode 100644 index 0000000..15da14d --- /dev/null +++ b/extends/influxlog/influx.go @@ -0,0 +1,98 @@ +package influxlog + +import ( + "fmt" + "io" + "time" + + "github.com/caddyserver/caddy/v2" + influxdb2 "github.com/influxdata/influxdb-client-go" + influxdb2api "github.com/influxdata/influxdb-client-go/api" +) + +func init() { + caddy.RegisterModule(Writer{}) +} + +type influxWriteCloser struct { + api influxdb2api.WriteAPI +} + +func (i *influxWriteCloser) Write(b []byte) (int, error) { + n := len(b) + content := string(b) + // TODO: parse the content {time} {level} {module} {messages} + // Remember to rewrite the function below in next PR. + fmt.Println(content) + tags := map[string]string{"ip": "135.22.5.3"} + fields := map[string]interface{}{"Country": "HI"} + p := influxdb2.NewPoint("syslog", tags, fields, time.Now()) + i.api.WritePoint(p) + return n, nil +} + +func (i *influxWriteCloser) Close() error { + i.api.Flush() + i.api.Close() + return nil +} + +// Writer is a influxdb client to write time series data +type Writer struct { + Client influxdb2.Client + Config *Config +} + +// CaddyModule returns the Caddy module information +func (Writer) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "caddy.logging.writers.influxlog", + New: func() caddy.Module { return new(Writer) }, + } +} + +// Validate currently do nothing +func (s *Writer) Validate() error { + return nil +} + +// Cleanup currently do nothing +func (s *Writer) Cleanup() error { + s.Client.Close() + return nil +} + +// Provision currently do nothing +func (s *Writer) Provision(ctx caddy.Context) error { + return nil +} + +// String returns the expression of this struct +func (s *Writer) String() string { + return "influxlog" + s.Config.Addr +} + +// WriterKey returns a unique key representing this influxLogWriter +func (s *Writer) WriterKey() string { + return "influxlog" + s.Config.Addr +} + +// OpenWriter opens a new influxdb client with connection +func (s *Writer) OpenWriter() (io.WriteCloser, error) { + // This is will be called at the StandardLibLog's provision + client := influxdb2.NewClientWithOptions( + s.Config.Addr, s.Config.Token, influxdb2.DefaultOptions()) + + // set up the options here + s.Client = client + api := client.WriteAPI(s.Config.Organization, s.Config.Bucket) + + return &influxWriteCloser{api: api}, nil +} + +var ( + _ caddy.Provisioner = (*Writer)(nil) + _ caddy.WriterOpener = (*Writer)(nil) + _ caddy.CleanerUpper = (*Writer)(nil) + _ caddy.Validator = (*Writer)(nil) +) diff --git a/go.mod b/go.mod index bcf7d0b..cfbc3bf 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.9.2 // indirect + github.com/influxdata/influxdb-client-go v1.4.0 github.com/mitchellh/go-testing-interface v1.0.3 // indirect github.com/mitchellh/mapstructure v1.3.1 // indirect github.com/mitchellh/reflectwalk v1.0.1 // indirect diff --git a/go.sum b/go.sum index 3a658d5..1b7985f 100644 --- a/go.sum +++ b/go.sum @@ -197,12 +197,15 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deepmap/oapi-codegen v1.3.6 h1:Wj44p9A0V0PJ+AUg0BWdyGcsS1LY18U+0rCuPQgK0+o= +github.com/deepmap/oapi-codegen v1.3.6/go.mod h1:aBozjEveG+33xPiP55Iw/XbVkhtZHEGLq3nxlX0+hfU= github.com/dgraph-io/badger v1.5.3 h1:5oWIuRvwn93cie+OSt1zSnkaIQ1JFQM8bGlIv6O6Sts= github.com/dgraph-io/badger v1.5.3/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= github.com/dgraph-io/badger/v2 v2.0.1-rc1.0.20200413122845-09dd2e1a4195 h1:n8KbImHW5qZCXv1y3tHjz5yz418/eTxeRJZ2ZuDm1ZU= @@ -246,6 +249,7 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= 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= +github.com/getkin/kin-openapi v0.2.0/go.mod h1:V1z9xl9oF5Wt7v32ne4FmiF1alpS4dM6mNzoywPOXlk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -342,6 +346,7 @@ github.com/golangci/golangci-lint v1.17.2-0.20190910081718-bad04bb7378f/go.mod h github.com/golangci/golangci-lint v1.22.2/go.mod h1:2Bj42k6hPQFTRxkDb7S3TQ+EsnumZXOmIYNqlQrp0FI= github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= @@ -478,6 +483,10 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb-client-go v1.4.0 h1:+KavOkwhLClHFfYcJMHHnTL5CZQhXJzOm5IKHI9BqJk= +github.com/influxdata/influxdb-client-go v1.4.0/go.mod h1:S+oZsPivqbcP1S9ur+T+QqXvrYS3NCZeMQtBoH4D1dw= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= @@ -534,6 +543,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= +github.com/labstack/echo/v4 v4.1.11 h1:z0BZoArY4FqdpUEl+wlHp4hnr/oSR6MTmQmv8OHSoww= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= +github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/letsencrypt/pkcs11key v2.0.1-0.20170608213348-396559074696+incompatible/go.mod h1:iGYXKqDXt0cpBthCHdr9ZdsQwyGlYFh/+8xa4WzIQ34= github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -560,7 +573,9 @@ github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGD github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ= github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk= github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= @@ -568,6 +583,7 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= @@ -881,9 +897,12 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= +github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= @@ -952,9 +971,11 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1025,6 +1046,7 @@ golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1081,11 +1103,13 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/handler.go b/handler.go index 9233b68..7efb30b 100644 --- a/handler.go +++ b/handler.go @@ -208,6 +208,14 @@ func (h *Handler) Provision(ctx caddy.Context) error { } + // if h.InfluxLogRaw != nil { + // val, err := ctx.LoadModule(h, "InfluxLogRaw") + // if err != nil { + // return fmt.Errorf("loading influxlog module: %s", err.Error()) + // } + // h.InfluxLog = val.(*influxlog.InfluxLogWriter) + // } + config = h.Config return nil diff --git a/handler_test.go b/handler_test.go index 2a6fbfb..58e02a0 100644 --- a/handler_test.go +++ b/handler_test.go @@ -26,8 +26,7 @@ func (suite *CacheKeyTemplatingTestSuite) TestKeyReplacer() { repl := caddyhttp.NewTestReplacer(r) result := repl.ReplaceKnown(defaultCacheKeyTemplate, "") - suite.Equal("GET example.com/songa age=20&class=A", result) - + suite.Equal("GET example.com/songa?age=20&class=A", result) } type DetermineShouldCacheTestSuite struct { diff --git a/readme.org b/readme.org index 15a29ef..7638e15 100644 --- a/readme.org +++ b/readme.org @@ -39,21 +39,23 @@ *** first you can list the current caches + Given that you specify the port 7777 to serve caddy admin, you can get the list of cache by the api below. + #+begin_src restclient - GET http://example.com/caches + GET http://example.com:7777/caches #+end_src *** purge the cache with http DELETE request It supports the regular expression. #+begin_src restclient - DELETE http://:host/caches/purge + DELETE http://example.com:7777/caches/purge Content-Type: application/json { - "method": "GET" , - "host": "localhost", - "uri": ".*\\.txt" + "method": "GET", + "host": "localhost", + "uri": ".*\\.txt" } #+end_src ** Support cluster with consul