diff --git a/.goreleaser.yml b/.goreleaser.yml index 899ac85..a32bb10 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,21 +1,48 @@ +env: + - GO111MODULE=on + - CGO_ENABLED=1 before: hooks: - make clean - - go mod download - - go generate ./... + - make embed builds: - - main: ./cmd/hetty + - id: hetty-darwin-amd64 + main: ./cmd/hetty + goarch: + - amd64 + goos: + - darwin env: - - CGO_ENABLED=0 + - CC=o64-clang + - CXX=o64-clang++ + flags: + - -mod=readonly + ldflags: + - id: hetty-linux-amd64 + main: ./cmd/hetty + goarch: + - amd64 goos: - linux + flags: + - -mod=readonly + ldflags: + - id: hetty-windows-amd64 + main: ./cmd/hetty + goarch: + - amd64 + goos: - windows - - darwin - hooks: - pre: make embed + env: + - CC=x86_64-w64-mingw32-gcc + - CXX=x86_64-w64-mingw32-g++ + flags: + - -mod=readonly + ldflags: + - -buildmode=exe archives: - replacements: - darwin: Darwin + darwin: macOS linux: Linux windows: Windows 386: i386 diff --git a/Dockerfile b/Dockerfile index fb5b435..83a7729 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,10 @@ ARG GO_VERSION=1.15 -ARG CGO_ENABLED=0 +ARG CGO_ENABLED=1 ARG NODE_VERSION=14.11 FROM golang:${GO_VERSION}-alpine AS go-builder WORKDIR /app +RUN apk add --no-cache build-base COPY go.mod go.sum ./ RUN go mod download COPY cmd ./cmd diff --git a/Makefile b/Makefile index 7455569..21e0c44 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +PACKAGE_NAME := github.com/dstotijn/hetty +GOLANG_CROSS_VERSION ?= v1.15.2 + setup: go mod download go generate ./... @@ -9,12 +12,34 @@ embed: .PHONY: embed build: embed - go build ./cmd/hetty + env CGO_ENABLED=1 go build ./cmd/hetty .PHONY: build clean: rm -rf cmd/hetty/rice-box.go .PHONY: clean +release-dry-run: + @docker run \ + --rm \ + -v `pwd`:/go/src/$(PACKAGE_NAME) \ + -v `pwd`/admin/dist:/go/src/$(PACKAGE_NAME)/admin/dist \ + -w /go/src/$(PACKAGE_NAME) \ + troian/golang-cross:${GOLANG_CROSS_VERSION} \ + --rm-dist --skip-validate --skip-publish +.PHONY: release-dry-run + release: - goreleaser -p 1 \ No newline at end of file + @if [ ! -f ".release-env" ]; then \ + echo "\033[91mFile \`.release-env\` is missing.\033[0m";\ + exit 1;\ + fi + @docker run \ + --rm \ + -v `pwd`:/go/src/$(PACKAGE_NAME) \ + -v `pwd`/admin/dist:/go/src/$(PACKAGE_NAME)/admin/dist \ + -w /go/src/$(PACKAGE_NAME) \ + --env-file .release-env \ + troian/golang-cross:${GOLANG_CROSS_VERSION} \ + release --rm-dist +.PHONY: release \ No newline at end of file diff --git a/README.md b/README.md index 2a40a98..600ff2e 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ on Docker Hub. $ docker run \ -v $HOME/.hetty/hetty_key.pem:/root/.hetty/hetty_key.pem \ -v $HOME/.hetty/hetty_cert.pem:/root/.hetty/hetty_cert.pem \ --v $HOME/.hetty/hetty.bolt:/root/.hetty/hetty.bolt \ +-v $HOME/.hetty/hetty.db:/root/.hetty/hetty.db \ -p 127.0.0.1:8080:8080 \ dstotijn/hetty ``` @@ -81,7 +81,7 @@ Usage of ./hetty: -cert string CA certificate filepath. Creates a new CA certificate is file doesn't exist (default "~/.hetty/hetty_cert.pem") -db string - Database file path (default "~/.hetty/hetty.bolt") + Database file path (default "~/.hetty/hetty.db") -key string CA private key filepath. Creates a new CA private key if file doesn't exist (default "~/.hetty/hetty_key.pem") ``` @@ -103,11 +103,6 @@ write-up on its mission and roadmap. A short summary/braindump: it as a CLI tool. - Pluggable architecture for the MITM proxy and future modules, making it possible for hook into the core engine. -- I’ve chosen [Cayley](https://cayley.io/) as the graph database (backed by - BoltDB storage on disk) for now (not sure if it will work in the long run). - The benefit is that Cayley (also written in Go) - is embedded as a library. Because of this, the complete application is self contained - in a single running binary. - Talk to the community, and focus on the features that the majority. Less features means less code to maintain. diff --git a/admin/src/components/Layout.tsx b/admin/src/components/Layout.tsx index f2c4975..69fe1b6 100644 --- a/admin/src/components/Layout.tsx +++ b/admin/src/components/Layout.tsx @@ -154,7 +154,7 @@ export function Layout({ title, page, children }: Props): JSX.Element { - + Hetty:// {title} diff --git a/admin/src/components/reqlog/LogDetail.tsx b/admin/src/components/reqlog/LogDetail.tsx index 8c787fe..03d06dc 100644 --- a/admin/src/components/reqlog/LogDetail.tsx +++ b/admin/src/components/reqlog/LogDetail.tsx @@ -32,7 +32,7 @@ const HTTP_REQUEST_LOG = gql` `; interface Props { - requestId: string; + requestId: number; } function LogDetail({ requestId: id }: Props): JSX.Element { diff --git a/admin/src/components/reqlog/LogsOverview.tsx b/admin/src/components/reqlog/LogsOverview.tsx index e7907dd..16a0992 100644 --- a/admin/src/components/reqlog/LogsOverview.tsx +++ b/admin/src/components/reqlog/LogsOverview.tsx @@ -25,14 +25,14 @@ const HTTP_REQUEST_LOGS = gql` function LogsOverview(): JSX.Element { const router = useRouter(); - const detailReqLogId = router.query.id as string; - console.log(detailReqLogId); + const detailReqLogId = + router.query.id && parseInt(router.query.id as string, 10); const { loading, error, data } = useQuery(HTTP_REQUEST_LOGS, { pollInterval: 1000, }); - const handleLogClick = (reqId: string) => { + const handleLogClick = (reqId: number) => { router.push("/proxy/logs?id=" + reqId, undefined, { shallow: false, }); diff --git a/admin/src/components/reqlog/RequestList.tsx b/admin/src/components/reqlog/RequestList.tsx index 6076b95..50c6181 100644 --- a/admin/src/components/reqlog/RequestList.tsx +++ b/admin/src/components/reqlog/RequestList.tsx @@ -31,8 +31,8 @@ const useStyles = makeStyles((theme: Theme) => interface Props { logs: Array; - selectedReqLogId?: string; - onLogClick(requestId: string): void; + selectedReqLogId?: number; + onLogClick(requestId: number): void; theme: Theme; } @@ -63,8 +63,8 @@ function RequestList({ interface RequestListTableProps { logs?: any; - selectedReqLogId?: string; - onLogClick(requestId: string): void; + selectedReqLogId?: number; + onLogClick(requestId: number): void; theme: Theme; } diff --git a/cmd/hetty/main.go b/cmd/hetty/main.go index ba70048..c4a476b 100644 --- a/cmd/hetty/main.go +++ b/cmd/hetty/main.go @@ -11,7 +11,7 @@ import ( rice "github.com/GeertJohan/go.rice" "github.com/dstotijn/hetty/pkg/api" - "github.com/dstotijn/hetty/pkg/db/cayley" + "github.com/dstotijn/hetty/pkg/db/sqlite" "github.com/dstotijn/hetty/pkg/proxy" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" @@ -33,7 +33,7 @@ var ( func main() { flag.StringVar(&caCertFile, "cert", "~/.hetty/hetty_cert.pem", "CA certificate filepath. Creates a new CA certificate is file doesn't exist") flag.StringVar(&caKeyFile, "key", "~/.hetty/hetty_key.pem", "CA private key filepath. Creates a new CA private key if file doesn't exist") - flag.StringVar(&dbFile, "db", "~/.hetty/hetty.bolt", "Database file path") + flag.StringVar(&dbFile, "db", "~/.hetty/hetty.db", "Database file path") flag.StringVar(&addr, "addr", ":8080", "TCP address to listen on, in the form \"host:port\"") flag.StringVar(&adminPath, "adminPath", "", "File path to admin build") flag.Parse() @@ -59,7 +59,7 @@ func main() { log.Fatalf("[FATAL] Could not create/load CA key pair: %v", err) } - db, err := cayley.NewDatabase(dbFile) + db, err := sqlite.New(dbFile) if err != nil { log.Fatalf("[FATAL] Could not initialize database: %v", err) } diff --git a/go.mod b/go.mod index 313597c..b33a920 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,11 @@ go 1.15 require ( github.com/99designs/gqlgen v0.11.3 github.com/GeertJohan/go.rice v1.0.0 - github.com/cayleygraph/cayley v0.7.7 - github.com/cayleygraph/quad v1.1.0 - github.com/google/uuid v1.1.2 github.com/gorilla/mux v1.7.4 - github.com/hidal-go/hidalgo v0.0.0-20190814174001-42e03f3b5eaa + github.com/gorilla/websocket v1.4.0 // indirect + github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/mattn/go-sqlite3 v1.14.4 github.com/mitchellh/go-homedir v1.1.0 + github.com/mitchellh/mapstructure v1.1.2 // indirect github.com/vektah/gqlparser/v2 v2.0.1 - golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 // indirect ) diff --git a/go.sum b/go.sum index 0ab7b9d..eb58cb3 100644 --- a/go.sum +++ b/go.sum @@ -1,320 +1,85 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4= github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/badgerodon/peg v0.0.0-20130729175151-9e5f7f4d07ca/go.mod h1:TWe0N2hv5qvpLHT+K16gYcGBllld4h65dQ/5CNuirmk= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/cayleygraph/cayley v0.7.7 h1:z+7xkAbg6bKiXJOtOkEG3zCm2K084sr/aGwFV7xcQNs= -github.com/cayleygraph/cayley v0.7.7/go.mod h1:VUd+PInYf94/VY41ePeFtFyP99BAs953kFT4N+6F7Ko= -github.com/cayleygraph/quad v1.1.0 h1:w1nXAmn+nz07+qlw89dke9LwWkYpeX+OcvfTvGQRBpM= -github.com/cayleygraph/quad v1.1.0/go.mod h1:maWODEekEhrO0mdc9h5n/oP7cH1h/OTgqQ2qWbuI9M4= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cznic/mathutil v0.0.0-20170313102836-1447ad269d64 h1:oad14P7M0/ZAPSMH1nl1vC8zdKVkA3kfHLO59z1l8Eg= -github.com/cznic/mathutil v0.0.0-20170313102836-1447ad269d64/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U= -github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= 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/dennwc/base v1.0.0 h1:xlBzvBNRvkQ1LFI/jom7rr0vZsvYDKtvMM6lIpjFb3M= -github.com/dennwc/base v1.0.0/go.mod h1:zaTDIiAcg2oKW9XhjIaRc1kJVteCFXSSW6jwmCedUaI= -github.com/dennwc/graphql v0.0.0-20180603144102-12cfed44bc5d/go.mod h1:lg9KQn0BgRCSCGNpcGvJp/0Ljf1Yxk8TZq9HSYc43fk= -github.com/dgraph-io/badger v1.5.4/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= -github.com/dgraph-io/badger v1.5.5/go.mod h1:QgCntgIUPsjnp7cMLhUybJHb7iIoQWAHT6tF8ngCjWk= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190416075124-e1214b5e05dc/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM= github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/dlclark/regexp2 v1.1.4 h1:1udHhhGkIMplSrLeMJpPN7BHz1Iq2wVBUcb+3fxzhQM= -github.com/dlclark/regexp2 v1.1.4/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/docker v0.7.3-0.20180412203414-a422774e593b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dop251/goja v0.0.0-20190105122144-6d5bf35058fa h1:cA2OMt2CQ2yq2WhQw16mHv6ej9YY07H4pzfR/z/y+1Q= -github.com/dop251/goja v0.0.0-20190105122144-6d5bf35058fa/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/flimzy/diff v0.1.5/go.mod h1:lFJtC7SPsK0EroDmGTSrdtWKAxOk3rO+q+e04LL05Hs= -github.com/flimzy/diff v0.1.6/go.mod h1:lFJtC7SPsK0EroDmGTSrdtWKAxOk3rO+q+e04LL05Hs= -github.com/flimzy/kivik v1.8.1/go.mod h1:S2aPycbG0eDFll4wgXt9uacSNkXISPufutnc9sv+mdA= -github.com/flimzy/testy v0.1.16/go.mod h1:3szguN8NXqgq9bt9Gu8TQVj698PJWmyx/VY1frwwKrM= -github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsouza/go-dockerclient v1.2.2/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kivik/couchdb v1.8.1/go.mod h1:5XJRkAMpBlEVA4q0ktIZjUPYBjoBmRoiWvwUBzP3BOQ= -github.com/go-kivik/kivik v1.8.1/go.mod h1:nIuJ8z4ikBrVUSk3Ua8NoDqYKULPNjuddjqRvlSUyyQ= -github.com/go-kivik/kiviktest v1.1.2/go.mod h1:JdhVyzixoYhoIDUt6hRf1yAfYyaDa5/u9SDOindDkfQ= -github.com/go-kivik/pouchdb v1.3.5/go.mod h1:U+siUrqLCVxeMU3QjQTYIC3/F/e6EUKm+o5buJb7vpw= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug= -github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= -github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= -github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= -github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= -github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= -github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= -github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o= -github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/jsbuiltin v0.0.0-20180426082241-50091555e127/go.mod h1:7X1acUyFRf+oVFTU6SWw9mnb57Vxn+Nbh8iPbKg95hs= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hidal-go/hidalgo v0.0.0-20190814174001-42e03f3b5eaa h1:hBE4LGxApbZiV/3YoEPv7uYlUMWOogG1hwtkpiU87zQ= -github.com/hidal-go/hidalgo v0.0.0-20190814174001-42e03f3b5eaa/go.mod h1:bPkrxDlroXxigw8BMWTEPTv4W5/rQwNgg2BECXsgyX0= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= -github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326 h1:YP3lfXXYiQV5MKeUqVnxRP5uuMQTLPx+PGYm1UBoU98= -github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326/go.mod h1:nfqkuSNlsk1bvti/oa7TThx4KmRMBmSxf3okHI9wp3E= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= +github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8= github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/selinux v1.0.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.5.0 h1:Usqs0/lDK/NqTkvrmKSwA/3XkZAs7ZAW/eLeQ2MVBTw= -github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tylertreat/BoomFilters v0.0.0-20181028192813-611b3dbe80e8 h1:7X4KYG3guI2mPQGxm/ZNNsiu4BjKnef0KG0TblMC+Z8= -github.com/tylertreat/BoomFilters v0.0.0-20181028192813-611b3dbe80e8/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -325,152 +90,34 @@ github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWp github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o= github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.mongodb.org/mongo-driver v1.0.4/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190614160838-b47fdc937951/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191009170203-06d7bd2c5f4f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw= golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM= golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 h1:hzJjkvxUIF3bSt+v8N5tBQNx/605vszZJ+3XsIamzZo= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/olivere/elastic.v5 v5.0.80/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0= -gopkg.in/olivere/elastic.v5 v5.0.81/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/gqlgen.yml b/gqlgen.yml index a711959..9324f28 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -42,13 +42,10 @@ omit_slice_element_pointers: true # The first line in each type will be used as defaults for resolver arguments and # modelgen, the others will be allowed when binding to fields. Configure them to # your liking -# models: -# ID: -# model: -# - github.com/99designs/gqlgen/graphql.ID -# - github.com/99designs/gqlgen/graphql.Int -# - github.com/99designs/gqlgen/graphql.Int64 -# - github.com/99designs/gqlgen/graphql.Int32 +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.Int64 # Int: # model: # - github.com/99designs/gqlgen/graphql.Int diff --git a/pkg/api/generated.go b/pkg/api/generated.go index 1ef5e1e..f5b72b4 100644 --- a/pkg/api/generated.go +++ b/pkg/api/generated.go @@ -68,13 +68,13 @@ type ComplexityRoot struct { } Query struct { - HTTPRequestLog func(childComplexity int, id string) int + HTTPRequestLog func(childComplexity int, id int64) int HTTPRequestLogs func(childComplexity int) int } } type QueryResolver interface { - HTTPRequestLog(ctx context.Context, id string) (*HTTPRequestLog, error) + HTTPRequestLog(ctx context.Context, id int64) (*HTTPRequestLog, error) HTTPRequestLogs(ctx context.Context) ([]HTTPRequestLog, error) } @@ -215,7 +215,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.HTTPRequestLog(childComplexity, args["id"].(string)), true + return e.complexity.Query.HTTPRequestLog(childComplexity, args["id"].(int64)), true case "Query.httpRequestLogs": if e.complexity.Query.HTTPRequestLogs == nil { @@ -342,9 +342,9 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs func (ec *executionContext) field_Query_httpRequestLog_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 string + var arg0 int64 if tmp, ok := rawArgs["id"]; ok { - arg0, err = ec.unmarshalNID2string(ctx, tmp) + arg0, err = ec.unmarshalNID2int64(ctx, tmp) if err != nil { return nil, err } @@ -486,9 +486,9 @@ func (ec *executionContext) _HttpRequestLog_id(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int64) fc.Result = res - return ec.marshalNID2string(ctx, field.Selections, res) + return ec.marshalNID2int64(ctx, field.Selections, res) } func (ec *executionContext) _HttpRequestLog_url(ctx context.Context, field graphql.CollectedField, obj *HTTPRequestLog) (ret graphql.Marshaler) { @@ -752,9 +752,9 @@ func (ec *executionContext) _HttpResponseLog_requestId(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int64) fc.Result = res - return ec.marshalNID2string(ctx, field.Selections, res) + return ec.marshalNID2int64(ctx, field.Selections, res) } func (ec *executionContext) _HttpResponseLog_proto(ctx context.Context, field graphql.CollectedField, obj *HTTPResponseLog) (ret graphql.Marshaler) { @@ -948,7 +948,7 @@ func (ec *executionContext) _Query_httpRequestLog(ctx context.Context, field gra fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().HTTPRequestLog(rctx, args["id"].(string)) + return ec.resolvers.Query().HTTPRequestLog(rctx, args["id"].(int64)) }) if err != nil { ec.Error(ctx, err) @@ -2670,12 +2670,12 @@ func (ec *executionContext) marshalNHttpRequestLog2ᚕgithubᚗcomᚋdstotijnᚋ return ret } -func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalID(v) +func (ec *executionContext) unmarshalNID2int64(ctx context.Context, v interface{}) (int64, error) { + return graphql.UnmarshalInt64(v) } -func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { - res := graphql.MarshalID(v) +func (ec *executionContext) marshalNID2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { + res := graphql.MarshalInt64(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") diff --git a/pkg/api/models_gen.go b/pkg/api/models_gen.go index abaf0ba..e10959e 100644 --- a/pkg/api/models_gen.go +++ b/pkg/api/models_gen.go @@ -15,7 +15,7 @@ type HTTPHeader struct { } type HTTPRequestLog struct { - ID string `json:"id"` + ID int64 `json:"id"` URL string `json:"url"` Method HTTPMethod `json:"method"` Proto string `json:"proto"` @@ -26,7 +26,7 @@ type HTTPRequestLog struct { } type HTTPResponseLog struct { - RequestID string `json:"requestId"` + RequestID int64 `json:"requestId"` Proto string `json:"proto"` Status string `json:"status"` StatusCode int `json:"statusCode"` diff --git a/pkg/api/resolvers.go b/pkg/api/resolvers.go index 5d66841..aa3855e 100644 --- a/pkg/api/resolvers.go +++ b/pkg/api/resolvers.go @@ -6,8 +6,6 @@ import ( "context" "fmt" - "github.com/google/uuid" - "github.com/dstotijn/hetty/pkg/reqlog" ) @@ -38,12 +36,8 @@ func (r *queryResolver) HTTPRequestLogs(ctx context.Context) ([]HTTPRequestLog, return logs, nil } -func (r *queryResolver) HTTPRequestLog(ctx context.Context, id string) (*HTTPRequestLog, error) { - reqLogID, err := uuid.Parse(id) - if err != nil { - return nil, fmt.Errorf("invalid id: %v", err) - } - log, err := r.RequestLogService.FindRequestLogByID(ctx, reqLogID) +func (r *queryResolver) HTTPRequestLog(ctx context.Context, id int64) (*HTTPRequestLog, error) { + log, err := r.RequestLogService.FindRequestLogByID(ctx, id) if err == reqlog.ErrRequestNotFound { return nil, nil } @@ -65,7 +59,7 @@ func parseRequestLog(req reqlog.Request) (HTTPRequestLog, error) { } log := HTTPRequestLog{ - ID: req.ID.String(), + ID: req.ID, URL: req.Request.URL.String(), Proto: req.Request.Proto, Method: method, @@ -91,7 +85,7 @@ func parseRequestLog(req reqlog.Request) (HTTPRequestLog, error) { if req.Response != nil { log.Response = &HTTPResponseLog{ - RequestID: req.ID.String(), + RequestID: req.ID, Proto: req.Response.Response.Proto, Status: req.Response.Response.Status, StatusCode: req.Response.Response.StatusCode, diff --git a/pkg/db/cayley/bolt.go b/pkg/db/cayley/bolt.go deleted file mode 100644 index ff94b47..0000000 --- a/pkg/db/cayley/bolt.go +++ /dev/null @@ -1,64 +0,0 @@ -package cayley - -import ( - "os" - "path/filepath" - - "github.com/cayleygraph/cayley/clog" - "github.com/cayleygraph/cayley/graph" - hkv "github.com/hidal-go/hidalgo/kv" - "github.com/hidal-go/hidalgo/kv/bolt" -) - -const Type = bolt.Name - -func boltFilePath(path, filename string) string { - return filepath.Join(path, filename) -} - -func boltCreate(path string, opt graph.Options) (hkv.KV, error) { - filename, err := opt.StringKey("filename", "indexes.bolt") - if err != nil { - return nil, err - } - - err = os.MkdirAll(path, 0700) - if err != nil { - return nil, err - } - - db, err := bolt.Open(boltFilePath(path, filename), nil) - if err != nil { - clog.Errorf("Error: couldn't create Bolt database: %v", err) - return nil, err - } - - return db, nil -} - -func boltOpen(path string, opt graph.Options) (hkv.KV, error) { - filename, err := opt.StringKey("filename", "indexes.bolt") - if err != nil { - return nil, err - } - - db, err := bolt.Open(boltFilePath(path, filename), nil) - if err != nil { - clog.Errorf("Error, couldn't open! %v", err) - return nil, err - } - - bdb := db.DB() - bdb.NoSync, err = opt.BoolKey("nosync", false) - if err != nil { - db.Close() - return nil, err - } - - bdb.NoGrowSync = bdb.NoSync - if bdb.NoSync { - clog.Infof("Running in nosync mode") - } - - return db, nil -} diff --git a/pkg/db/cayley/cayley.go b/pkg/db/cayley/cayley.go deleted file mode 100644 index 6814269..0000000 --- a/pkg/db/cayley/cayley.go +++ /dev/null @@ -1,325 +0,0 @@ -package cayley - -import ( - "context" - "fmt" - "log" - "net/http" - "net/url" - "path" - "strings" - "sync" - "time" - - "github.com/cayleygraph/cayley" - "github.com/cayleygraph/cayley/graph" - "github.com/cayleygraph/cayley/graph/kv" - cpath "github.com/cayleygraph/cayley/graph/path" - "github.com/cayleygraph/cayley/schema" - "github.com/cayleygraph/quad" - "github.com/cayleygraph/quad/voc" - "github.com/cayleygraph/quad/voc/rdf" - "github.com/google/uuid" - - "github.com/dstotijn/hetty/pkg/reqlog" - "github.com/dstotijn/hetty/pkg/scope" -) - -type HTTPRequest struct { - rdfType struct{} `quad:"@type > hy:HTTPRequest"` - ID quad.IRI `quad:"@id"` - Proto string `quad:"hy:proto"` - URL string `quad:"hy:url"` - Method string `quad:"hy:method"` - Body string `quad:"hy:body,optional"` - Headers []HTTPHeader `quad:"hy:header"` - Timestamp time.Time `quad:"hy:timestamp"` - Response *HTTPResponse `quad:"hy:request < *,optional"` -} - -type HTTPResponse struct { - rdfType struct{} `quad:"@type > hy:HTTPResponse"` - RequestID quad.IRI `quad:"hy:request"` - Proto string `quad:"hy:proto"` - Status string `quad:"hy:status"` - StatusCode int `quad:"hy:status_code"` - Headers []HTTPHeader `quad:"hy:header"` - Body string `quad:"hy:body,optional"` - Timestamp time.Time `quad:"hy:timestamp"` -} - -type HTTPHeader struct { - rdfType struct{} `quad:"@type > hy:HTTPHeader"` - Key string `quad:"hy:key"` - Value string `quad:"hy:value,optional"` -} - -type Database struct { - store *cayley.Handle - schema *schema.Config - mu sync.Mutex -} - -func init() { - voc.RegisterPrefix("hy:", "https://hetty.xyz/") - schema.RegisterType(quad.IRI("hy:HTTPRequest"), HTTPRequest{}) - schema.RegisterType(quad.IRI("hy:HTTPResponse"), HTTPResponse{}) - schema.RegisterType(quad.IRI("hy:HTTPHeader"), HTTPHeader{}) - - kv.Register(Type, kv.Registration{ - NewFunc: boltOpen, - InitFunc: boltCreate, - IsPersistent: true, - }) -} - -func NewDatabase(filename string) (*Database, error) { - dir, file := path.Split(filename) - if dir == "" { - dir = "." - } - opts := graph.Options{ - "filename": file, - } - - schemaCfg := schema.NewConfig() - schemaCfg.GenerateID = func(_ interface{}) quad.Value { - return quad.BNode(uuid.New().String()) - } - - // Initialize the database. - err := graph.InitQuadStore("bolt", dir, opts) - if err != nil && err != graph.ErrDatabaseExists { - return nil, fmt.Errorf("cayley: could not initialize database: %v", err) - } - - // Open the database. - store, err := cayley.NewGraph("bolt", dir, opts) - if err != nil { - return nil, fmt.Errorf("cayley: could not open database: %v", err) - } - - return &Database{ - store: store, - schema: schemaCfg, - }, nil -} - -func (db *Database) Close() error { - return db.store.Close() -} - -func (db *Database) FindRequestLogs(ctx context.Context, opts reqlog.FindRequestsOptions, scope *scope.Scope) ([]reqlog.Request, error) { - db.mu.Lock() - defer db.mu.Unlock() - - var reqLogs []reqlog.Request - var reqs []HTTPRequest - - reqPath := cayley.StartPath(db.store, quad.IRI("hy:HTTPRequest")).In(quad.IRI(rdf.Type)) - if opts.OmitOutOfScope { - var filterPath *cpath.Path - for _, rule := range scope.Rules() { - if rule.URL != nil { - if filterPath == nil { - filterPath = reqPath.Out(quad.IRI("hy:url")).Regex(rule.URL).In(quad.IRI("hy:url")) - } else { - filterPath = filterPath.Or(reqPath.Out(quad.IRI("hy:url")).Regex(rule.URL).In(quad.IRI("hy:url"))) - } - } - } - if filterPath != nil { - reqPath = filterPath - } - } - - err := reqPath.Iterate(ctx).EachValue(db.store, func(v quad.Value) { - var req HTTPRequest - if err := db.schema.LoadToDepth(ctx, db.store, &req, 0, v); err != nil { - log.Printf("[ERROR] Could not load sub-graph for http requests: %v", err) - return - } - reqs = append(reqs, req) - }) - if err != nil { - return nil, fmt.Errorf("cayley: could not iterate over http requests: %v", err) - } - - for _, req := range reqs { - reqLog, err := parseRequestQuads(req, nil) - if err != nil { - return nil, fmt.Errorf("cayley: could not parse request quads (id: %v): %v", req.ID, err) - } - reqLogs = append(reqLogs, reqLog) - } - - // By default, all retrieved requests are ordered chronologically, oldest first. - // Reverse the order, so newest logs are first. - for i := len(reqLogs)/2 - 1; i >= 0; i-- { - opp := len(reqLogs) - 1 - i - reqLogs[i], reqLogs[opp] = reqLogs[opp], reqLogs[i] - } - - return reqLogs, nil -} - -func (db *Database) FindRequestLogByID(ctx context.Context, id uuid.UUID) (reqlog.Request, error) { - db.mu.Lock() - defer db.mu.Unlock() - - var req HTTPRequest - err := db.schema.LoadTo(ctx, db.store, &req, iriFromUUID(id)) - if schema.IsNotFound(err) { - return reqlog.Request{}, reqlog.ErrRequestNotFound - } - if err != nil { - return reqlog.Request{}, fmt.Errorf("cayley: could not load value: %v", err) - } - - reqLog, err := parseRequestQuads(req, nil) - if err != nil { - return reqlog.Request{}, fmt.Errorf("cayley: could not parse request log (id: %v): %v", req.ID, err) - } - - return reqLog, nil -} - -func (db *Database) AddRequestLog(ctx context.Context, reqLog reqlog.Request) error { - db.mu.Lock() - defer db.mu.Unlock() - - httpReq := HTTPRequest{ - ID: iriFromUUID(reqLog.ID), - Proto: reqLog.Request.Proto, - Method: reqLog.Request.Method, - URL: reqLog.Request.URL.String(), - Headers: httpHeadersSliceFromMap(reqLog.Request.Header), - Body: string(reqLog.Body), - Timestamp: reqLog.Timestamp, - } - - tx := cayley.NewTransaction() - qw := graph.NewTxWriter(tx, graph.Add) - - _, err := db.schema.WriteAsQuads(qw, httpReq) - if err != nil { - return fmt.Errorf("cayley: could not write quads: %v", err) - } - - if err := db.store.ApplyTransaction(tx); err != nil { - return fmt.Errorf("cayley: could not apply transaction: %v", err) - } - - return nil -} - -func (db *Database) AddResponseLog(ctx context.Context, resLog reqlog.Response) error { - db.mu.Lock() - defer db.mu.Unlock() - - httpRes := HTTPResponse{ - RequestID: iriFromUUID(resLog.RequestID), - Proto: resLog.Response.Proto, - Status: resLog.Response.Status, - StatusCode: resLog.Response.StatusCode, - Headers: httpHeadersSliceFromMap(resLog.Response.Header), - Body: string(resLog.Body), - Timestamp: resLog.Timestamp, - } - - tx := cayley.NewTransaction() - qw := graph.NewTxWriter(tx, graph.Add) - - _, err := db.schema.WriteAsQuads(qw, httpRes) - if err != nil { - return fmt.Errorf("cayley: could not write response quads: %v", err) - } - - if err := db.store.ApplyTransaction(tx); err != nil { - return fmt.Errorf("cayley: could not apply transaction: %v", err) - } - - return nil -} - -func iriFromUUID(id uuid.UUID) quad.IRI { - return quad.IRI("hy:" + id.String()).Full().Short() -} - -func uuidFromIRI(iri quad.IRI) (uuid.UUID, error) { - iriString := iri.Short().String() - stripped := strings.TrimRight(strings.TrimLeft(iriString, "") - id, err := uuid.Parse(stripped) - if err != nil { - return uuid.Nil, err - } - - return id, nil -} - -func httpHeadersSliceFromMap(hm http.Header) []HTTPHeader { - if hm == nil { - return nil - } - var hs []HTTPHeader - for key, values := range hm { - for _, value := range values { - hs = append(hs, HTTPHeader{Key: key, Value: value}) - } - } - return hs -} - -func httpHeadersMapFromSlice(hs []HTTPHeader) http.Header { - if hs == nil { - return nil - } - hm := make(http.Header) - for _, header := range hs { - hm.Add(header.Key, header.Value) - } - return hm -} - -func parseRequestQuads(req HTTPRequest, _ *HTTPResponse) (reqlog.Request, error) { - reqID, err := uuidFromIRI(req.ID) - if err != nil { - return reqlog.Request{}, fmt.Errorf("cannot parse request id: %v", err) - } - - u, err := url.Parse(req.URL) - if err != nil { - return reqlog.Request{}, fmt.Errorf("cannot parse request url: %v", err) - } - - reqLog := reqlog.Request{ - ID: reqID, - Request: http.Request{ - Method: req.Method, - URL: u, - Proto: req.Proto, - Header: httpHeadersMapFromSlice(req.Headers), - }, - Timestamp: req.Timestamp, - } - if req.Body != "" { - reqLog.Body = []byte(reqLog.Body) - } - - if req.Response != nil { - reqLog.Response = &reqlog.Response{ - RequestID: reqID, - Response: http.Response{ - Proto: req.Response.Proto, - Status: req.Response.Status, - StatusCode: req.Response.StatusCode, - Header: httpHeadersMapFromSlice(req.Response.Headers), - }, - } - if req.Response.Body != "" { - reqLog.Response.Body = []byte(req.Response.Body) - } - } - - return reqLog, nil -} diff --git a/pkg/db/sqlite/dto.go b/pkg/db/sqlite/dto.go new file mode 100644 index 0000000..8518df4 --- /dev/null +++ b/pkg/db/sqlite/dto.go @@ -0,0 +1,11 @@ +package sqlite + +import "time" + +type httpResponse struct { + ID *int64 + Proto *string + StatusCode *int + Body *[]byte + Timestamp *time.Time +} diff --git a/pkg/db/sqlite/sqlite.go b/pkg/db/sqlite/sqlite.go new file mode 100644 index 0000000..9468b64 --- /dev/null +++ b/pkg/db/sqlite/sqlite.go @@ -0,0 +1,493 @@ +package sqlite + +import ( + "context" + "database/sql" + "fmt" + "net/http" + "net/url" + "os" + "path/filepath" + "strconv" + "time" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" + + // Register sqlite3 for use via database/sql. + _ "github.com/mattn/go-sqlite3" +) + +// Client implements reqlog.Repository. +type Client struct { + db *sql.DB +} + +// New returns a new Client. +func New(filename string) (*Client, error) { + // Create directory for DB if it doesn't exist yet. + if dbDir, _ := filepath.Split(filename); dbDir != "" { + if _, err := os.Stat(dbDir); os.IsNotExist(err) { + os.Mkdir(dbDir, 0755) + } + } + + opts := make(url.Values) + opts.Set("_foreign_keys", "1") + + dsn := fmt.Sprintf("file:%v?%v", filename, opts.Encode()) + db, err := sql.Open("sqlite3", dsn) + if err != nil { + return nil, err + } + + if err := db.Ping(); err != nil { + return nil, fmt.Errorf("sqlite: could not ping database: %v", err) + } + + c := &Client{db: db} + + if err := c.prepareSchema(); err != nil { + return nil, fmt.Errorf("sqlite: could not prepare schema: %v", err) + } + + return &Client{db: db}, nil +} + +func (c Client) prepareSchema() error { + _, err := c.db.Exec(`CREATE TABLE IF NOT EXISTS http_requests ( + id INTEGER PRIMARY KEY, + proto TEXT, + url TEXT, + method TEXT, + body BLOB, + timestamp DATETIME + )`) + if err != nil { + return fmt.Errorf("could not create http_requests table: %v", err) + } + + _, err = c.db.Exec(`CREATE TABLE IF NOT EXISTS http_responses ( + id INTEGER PRIMARY KEY, + req_id INTEGER REFERENCES http_requests(id) ON DELETE CASCADE, + proto TEXT, + status_code INTEGER, + status_reason TEXT, + body BLOB, + timestamp DATETIME + )`) + if err != nil { + return fmt.Errorf("could not create http_responses table: %v", err) + } + + _, err = c.db.Exec(`CREATE TABLE IF NOT EXISTS http_headers ( + id INTEGER PRIMARY KEY, + req_id INTEGER REFERENCES http_requests(id) ON DELETE CASCADE, + res_id INTEGER REFERENCES http_responses(id) ON DELETE CASCADE, + key TEXT, + value TEXT + )`) + if err != nil { + return fmt.Errorf("could not create http_headers table: %v", err) + } + + return nil +} + +// Close uses the underlying database. +func (c *Client) Close() error { + return c.db.Close() +} + +func (c *Client) FindRequestLogs( + ctx context.Context, + opts reqlog.FindRequestsOptions, + scope *scope.Scope, +) (reqLogs []reqlog.Request, err error) { + // TODO: Pass GraphQL field collections upstream, so we can query only + // requested fields. + // TODO: Use opts and scope to filter. + reqQuery := `SELECT + req.id, + req.proto, + req.url, + req.method, + req.body, + req.timestamp, + res.id, + res.proto, + res.status_code, + res.status_reason, + res.body, + res.timestamp + FROM http_requests req + LEFT JOIN http_responses res ON req.id = res.req_id + ORDER BY req.id DESC` + + rows, err := c.db.QueryContext(ctx, reqQuery) + if err != nil { + return nil, fmt.Errorf("sqlite: could not execute query: %v", err) + } + defer rows.Close() + + for rows.Next() { + var reqLog reqlog.Request + var resDTO httpResponse + var statusReason *string + var rawURL string + + err := rows.Scan( + &reqLog.ID, + &reqLog.Request.Proto, + &rawURL, + &reqLog.Request.Method, + &reqLog.Body, + &reqLog.Timestamp, + &resDTO.ID, + &resDTO.Proto, + &resDTO.StatusCode, + &statusReason, + &resDTO.Body, + &resDTO.Timestamp, + ) + if err != nil { + return nil, fmt.Errorf("sqlite: could not scan row: %v", err) + } + + u, err := url.Parse(rawURL) + if err != nil { + return nil, fmt.Errorf("sqlite: could not parse URL: %v", err) + } + reqLog.Request.URL = u + + if resDTO.ID != nil { + status := strconv.Itoa(*resDTO.StatusCode) + " " + *statusReason + reqLog.Response = &reqlog.Response{ + ID: *resDTO.ID, + RequestID: reqLog.ID, + Response: http.Response{ + Status: status, + StatusCode: *resDTO.StatusCode, + Proto: *resDTO.Proto, + }, + Body: *resDTO.Body, + Timestamp: *resDTO.Timestamp, + } + } + + reqLogs = append(reqLogs, reqLog) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("sqlite: could not iterate over rows: %v", err) + } + rows.Close() + + reqHeadersStmt, err := c.db.PrepareContext(ctx, `SELECT key, value FROM http_headers WHERE req_id = ?`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer reqHeadersStmt.Close() + resHeadersStmt, err := c.db.PrepareContext(ctx, `SELECT key, value FROM http_headers WHERE res_id = ?`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer resHeadersStmt.Close() + + for _, reqLog := range reqLogs { + headers, err := findHeaders(ctx, reqHeadersStmt, reqLog.ID) + if err != nil { + return nil, fmt.Errorf("sqlite: could not query request headers: %v", err) + } + reqLog.Request.Header = headers + + if reqLog.Response != nil { + headers, err := findHeaders(ctx, resHeadersStmt, reqLog.Response.ID) + if err != nil { + return nil, fmt.Errorf("sqlite: could not query response headers: %v", err) + } + reqLog.Response.Response.Header = headers + } + } + + return reqLogs, nil +} + +func (c *Client) FindRequestLogByID(ctx context.Context, id int64) (reqlog.Request, error) { + // TODO: Pass GraphQL field collections upstream, so we can query only + // requested fields. + reqQuery := `SELECT + req.id, + req.proto, + req.url, + req.method, + req.body, + req.timestamp, + res.id, + res.proto, + res.status_code, + res.status_reason, + res.body, + res.timestamp + FROM http_requests req + LEFT JOIN http_responses res ON req.id = res.req_id + WHERE req_id = ? + ORDER BY req.id DESC` + + var reqLog reqlog.Request + var resDTO httpResponse + var statusReason *string + var rawURL string + + err := c.db.QueryRowContext(ctx, reqQuery, id).Scan( + &reqLog.ID, + &reqLog.Request.Proto, + &rawURL, + &reqLog.Request.Method, + &reqLog.Body, + &reqLog.Timestamp, + &resDTO.ID, + &resDTO.Proto, + &resDTO.StatusCode, + &statusReason, + &resDTO.Body, + &resDTO.Timestamp, + ) + if err == sql.ErrNoRows { + return reqlog.Request{}, reqlog.ErrRequestNotFound + } + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not scan row: %v", err) + } + + u, err := url.Parse(rawURL) + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not parse URL: %v", err) + } + reqLog.Request.URL = u + + if resDTO.ID != nil { + status := strconv.Itoa(*resDTO.StatusCode) + " " + *statusReason + reqLog.Response = &reqlog.Response{ + ID: *resDTO.ID, + RequestID: reqLog.ID, + Response: http.Response{ + Status: status, + StatusCode: *resDTO.StatusCode, + Proto: *resDTO.Proto, + }, + Body: *resDTO.Body, + Timestamp: *resDTO.Timestamp, + } + } + + reqHeadersStmt, err := c.db.PrepareContext(ctx, `SELECT key, value FROM http_headers WHERE req_id = ?`) + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer reqHeadersStmt.Close() + resHeadersStmt, err := c.db.PrepareContext(ctx, `SELECT key, value FROM http_headers WHERE res_id = ?`) + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer resHeadersStmt.Close() + + headers, err := findHeaders(ctx, reqHeadersStmt, reqLog.ID) + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not query request headers: %v", err) + } + reqLog.Request.Header = headers + + if reqLog.Response != nil { + headers, err := findHeaders(ctx, resHeadersStmt, reqLog.Response.ID) + if err != nil { + return reqlog.Request{}, fmt.Errorf("sqlite: could not query response headers: %v", err) + } + reqLog.Response.Response.Header = headers + } + + return reqLog, nil +} + +func (c *Client) AddRequestLog( + ctx context.Context, + req http.Request, + body []byte, + timestamp time.Time, +) (*reqlog.Request, error) { + + reqLog := &reqlog.Request{ + Request: req, + Body: body, + Timestamp: timestamp, + } + + tx, err := c.db.BeginTx(ctx, nil) + if err != nil { + return nil, fmt.Errorf("sqlite: could not start transaction: %v", err) + } + defer tx.Rollback() + + reqStmt, err := tx.PrepareContext(ctx, `INSERT INTO http_requests ( + proto, + url, + method, + body, + timestamp + ) VALUES (?, ?, ?, ?, ?)`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer reqStmt.Close() + + result, err := reqStmt.ExecContext(ctx, + reqLog.Request.Proto, + reqLog.Request.URL.String(), + reqLog.Request.Method, + reqLog.Body, + reqLog.Timestamp, + ) + if err != nil { + return nil, fmt.Errorf("sqlite: could not execute statement: %v", err) + } + + reqID, err := result.LastInsertId() + if err != nil { + return nil, fmt.Errorf("sqlite: could not get last insert ID: %v", err) + } + reqLog.ID = reqID + + headerStmt, err := tx.PrepareContext(ctx, `INSERT INTO http_headers ( + req_id, + key, + value + ) VALUES (?, ?, ?)`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer headerStmt.Close() + + err = insertHeaders(ctx, headerStmt, reqID, reqLog.Request.Header) + if err != nil { + return nil, fmt.Errorf("sqlite: could not insert http headers: %v", err) + } + + if err := tx.Commit(); err != nil { + return nil, fmt.Errorf("sqlite: could not commit transaction: %v", err) + } + + return reqLog, nil +} + +func (c *Client) AddResponseLog( + ctx context.Context, + reqID int64, + res http.Response, + body []byte, + timestamp time.Time, +) (*reqlog.Response, error) { + resLog := &reqlog.Response{ + RequestID: reqID, + Response: res, + Body: body, + Timestamp: timestamp, + } + tx, err := c.db.BeginTx(ctx, nil) + if err != nil { + return nil, fmt.Errorf("sqlite: could not start transaction: %v", err) + } + defer tx.Rollback() + + resStmt, err := tx.PrepareContext(ctx, `INSERT INTO http_responses ( + req_id, + proto, + status_code, + status_reason, + body, + timestamp + ) VALUES (?, ?, ?, ?, ?, ?)`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer resStmt.Close() + + var statusReason string + if len(resLog.Response.Status) > 4 { + statusReason = resLog.Response.Status[4:] + } + + result, err := resStmt.ExecContext(ctx, + resLog.RequestID, + resLog.Response.Proto, + resLog.Response.StatusCode, + statusReason, + resLog.Body, + resLog.Timestamp, + ) + if err != nil { + return nil, fmt.Errorf("sqlite: could not execute statement: %v", err) + } + + resID, err := result.LastInsertId() + if err != nil { + return nil, fmt.Errorf("sqlite: could not get last insert ID: %v", err) + } + resLog.ID = resID + + headerStmt, err := tx.PrepareContext(ctx, `INSERT INTO http_headers ( + res_id, + key, + value + ) VALUES (?, ?, ?)`) + if err != nil { + return nil, fmt.Errorf("sqlite: could not prepare statement: %v", err) + } + defer headerStmt.Close() + + err = insertHeaders(ctx, headerStmt, resID, resLog.Response.Header) + if err != nil { + return nil, fmt.Errorf("sqlite: could not insert http headers: %v", err) + } + + if err := tx.Commit(); err != nil { + return nil, fmt.Errorf("sqlite: could not commit transaction: %v", err) + } + + return resLog, nil +} + +func insertHeaders(ctx context.Context, stmt *sql.Stmt, id int64, headers http.Header) error { + for key, values := range headers { + for _, value := range values { + if _, err := stmt.ExecContext(ctx, id, key, value); err != nil { + return fmt.Errorf("could not execute statement: %v", err) + } + } + } + return nil +} + +func findHeaders(ctx context.Context, stmt *sql.Stmt, id int64) (http.Header, error) { + headers := make(http.Header) + rows, err := stmt.QueryContext(ctx, id) + if err != nil { + return nil, fmt.Errorf("sqlite: could not execute query: %v", err) + } + defer rows.Close() + + for rows.Next() { + var key, value string + err := rows.Scan( + &key, + &value, + ) + if err != nil { + return nil, fmt.Errorf("sqlite: could not scan row: %v", err) + } + headers.Add(key, value) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("sqlite: could not iterate over rows: %v", err) + } + + return headers, nil +} diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index 2e51fae..8cec97a 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -12,8 +12,6 @@ import ( "net/http/httputil" "github.com/dstotijn/hetty/pkg/scope" - - "github.com/google/uuid" ) type contextKey int @@ -56,11 +54,6 @@ func NewProxy(ca *x509.Certificate, key crypto.PrivateKey) (*Proxy, error) { } func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // Add a unique request ID, to be used for correlating responses to requests. - reqID := uuid.New() - ctx := context.WithValue(r.Context(), ReqIDKey, reqID) - r = r.WithContext(ctx) - if r.Method == http.MethodConnect { p.handleConnect(w, r) return diff --git a/pkg/reqlog/repo.go b/pkg/reqlog/repo.go index 6185523..36264f1 100644 --- a/pkg/reqlog/repo.go +++ b/pkg/reqlog/repo.go @@ -2,14 +2,15 @@ package reqlog import ( "context" + "net/http" + "time" "github.com/dstotijn/hetty/pkg/scope" - "github.com/google/uuid" ) type Repository interface { FindRequestLogs(ctx context.Context, opts FindRequestsOptions, scope *scope.Scope) ([]Request, error) - FindRequestLogByID(ctx context.Context, id uuid.UUID) (Request, error) - AddRequestLog(ctx context.Context, reqLog Request) error - AddResponseLog(ctx context.Context, resLog Response) error + FindRequestLogByID(ctx context.Context, id int64) (Request, error) + AddRequestLog(ctx context.Context, req http.Request, body []byte, timestamp time.Time) (*Request, error) + AddResponseLog(ctx context.Context, reqID int64, res http.Response, body []byte, timestamp time.Time) (*Response, error) } diff --git a/pkg/reqlog/reqlog.go b/pkg/reqlog/reqlog.go index c024272..6240c51 100644 --- a/pkg/reqlog/reqlog.go +++ b/pkg/reqlog/reqlog.go @@ -13,8 +13,6 @@ import ( "github.com/dstotijn/hetty/pkg/proxy" "github.com/dstotijn/hetty/pkg/scope" - - "github.com/google/uuid" ) type contextKey int @@ -24,7 +22,7 @@ const LogBypassedKey contextKey = 0 var ErrRequestNotFound = errors.New("reqlog: request not found") type Request struct { - ID uuid.UUID + ID int64 Request http.Request Body []byte Timestamp time.Time @@ -32,7 +30,8 @@ type Request struct { } type Response struct { - RequestID uuid.UUID + ID int64 + RequestID int64 Response http.Response Body []byte Timestamp time.Time @@ -72,46 +71,44 @@ func (svc *Service) FindRequests(ctx context.Context, opts FindRequestsOptions) return svc.repo.FindRequestLogs(ctx, opts, scope) } -func (svc *Service) FindRequestLogByID(ctx context.Context, id uuid.UUID) (Request, error) { +func (svc *Service) FindRequestLogByID(ctx context.Context, id int64) (Request, error) { return svc.repo.FindRequestLogByID(ctx, id) } -func (svc *Service) addRequest(ctx context.Context, reqID uuid.UUID, req http.Request, body []byte) error { - reqLog := Request{ - ID: reqID, - Request: req, - Body: body, - Timestamp: time.Now(), - } - - return svc.repo.AddRequestLog(ctx, reqLog) +func (svc *Service) addRequest( + ctx context.Context, + req http.Request, + body []byte, + timestamp time.Time, +) (*Request, error) { + return svc.repo.AddRequestLog(ctx, req, body, timestamp) } -func (svc *Service) addResponse(ctx context.Context, reqID uuid.UUID, res http.Response, body []byte) error { +func (svc *Service) addResponse( + ctx context.Context, + reqID int64, + res http.Response, + body []byte, + timestamp time.Time, +) (*Response, error) { if res.Header.Get("Content-Encoding") == "gzip" { gzipReader, err := gzip.NewReader(bytes.NewBuffer(body)) if err != nil { - return fmt.Errorf("reqlog: could not create gzip reader: %v", err) + return nil, fmt.Errorf("reqlog: could not create gzip reader: %v", err) } defer gzipReader.Close() body, err = ioutil.ReadAll(gzipReader) if err != nil { - return fmt.Errorf("reqlog: could not read gzipped response body: %v", err) + return nil, fmt.Errorf("reqlog: could not read gzipped response body: %v", err) } } - resLog := Response{ - RequestID: reqID, - Response: res, - Body: body, - Timestamp: time.Now(), - } - - return svc.repo.AddResponseLog(ctx, resLog) + return svc.repo.AddResponseLog(ctx, reqID, res, body, timestamp) } func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc { return func(req *http.Request) { + now := time.Now() next(req) clone := req.Clone(req.Context()) @@ -131,26 +128,23 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM // doens't match any rules of the scope. if svc.BypassOutOfScopeRequests && !svc.scope.Match(clone, body) { ctx := context.WithValue(req.Context(), LogBypassedKey, true) - req = req.WithContext(ctx) + *req = *req.WithContext(ctx) return } - reqID, _ := req.Context().Value(proxy.ReqIDKey).(uuid.UUID) - if reqID == uuid.Nil { - log.Println("[ERROR] Request is missing a related request ID") + reqLog, err := svc.addRequest(req.Context(), *clone, body, now) + if err != nil { + log.Printf("[ERROR] Could not store request log: %v", err) return } - - go func() { - if err := svc.addRequest(context.Background(), reqID, *clone, body); err != nil { - log.Printf("[ERROR] Could not store request log: %v", err) - } - }() + ctx := context.WithValue(req.Context(), proxy.ReqIDKey, reqLog.ID) + *req = *req.WithContext(ctx) } } func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc { return func(res *http.Response) error { + now := time.Now() if err := next(res); err != nil { return err } @@ -159,8 +153,8 @@ func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.Respon return nil } - reqID, _ := res.Request.Context().Value(proxy.ReqIDKey).(uuid.UUID) - if reqID == uuid.Nil { + reqID, _ := res.Request.Context().Value(proxy.ReqIDKey).(int64) + if reqID == 0 { return errors.New("reqlog: request is missing ID") } @@ -174,7 +168,7 @@ func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.Respon res.Body = ioutil.NopCloser(bytes.NewBuffer(body)) go func() { - if err := svc.addResponse(res.Request.Context(), reqID, clone, body); err != nil { + if _, err := svc.addResponse(context.Background(), reqID, clone, body, now); err != nil { log.Printf("[ERROR] Could not store response log: %v", err) } }()