mirror of
https://github.com/lukaszraczylo/go-simple-graphql.git
synced 2026-10-13 00:48:37 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1406eeac8
|
||
|
|
ea7ec683ef
|
||
|
|
5cd22318f1
|
||
|
|
13955da995
|
||
|
|
cd5d75feff
|
@@ -11,11 +11,15 @@ help: ## display this help
|
|||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: ## run tests on library
|
test: ## run tests on library
|
||||||
@go test $(ADDITIONAL_BUILD_FLAGS) -v -cover ./...
|
@LOG_LEVEL=debug go test $(ADDITIONAL_BUILD_FLAGS) -v -cover ./...
|
||||||
|
|
||||||
.PHONY: test-packages
|
.PHONY: test-packages
|
||||||
test-packages: ## run tests on packages
|
test-packages: ## run tests on packages
|
||||||
@go test -v -cover ./pkg/...
|
@go test -v -cover ./pkg/...
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: test-packages test
|
all: test-packages test
|
||||||
|
|
||||||
|
.PHONY: update
|
||||||
|
update: ## update dependencies
|
||||||
|
@go get -u -v ./...
|
||||||
@@ -23,12 +23,15 @@ Therefore, I present you the simple client to which you can copy & paste your gr
|
|||||||
* Executing GraphQL queries as they are, without types declaration
|
* Executing GraphQL queries as they are, without types declaration
|
||||||
* HTTP2 support!
|
* HTTP2 support!
|
||||||
* Support for additional headers
|
* Support for additional headers
|
||||||
|
* Query cache
|
||||||
|
|
||||||
## Usage example
|
## Usage example
|
||||||
|
|
||||||
### Environment variables
|
### Environment variables
|
||||||
|
|
||||||
* `GRAPHQL_ENDPOINT` - Your GraphQL endpoint. Default: `http://127.0.0.1:9090/v1/graphql`
|
* `GRAPHQL_ENDPOINT` - Your GraphQL endpoint. Default: `http://127.0.0.1:9090/v1/graphql`
|
||||||
|
* `GRAPHQL_CACHE` - Should the query cache be enabled? Default: `false`
|
||||||
|
* `GRAPHQL_CACHE_TTL` - Cache TTL in seconds for SELECT type of queries. Default: `5`
|
||||||
* `LOG_LEVEL` - Logging level. Default: `info`
|
* `LOG_LEVEL` - Logging level. Default: `info`
|
||||||
|
|
||||||
### Example reader code
|
### Example reader code
|
||||||
@@ -37,7 +40,7 @@ Therefore, I present you the simple client to which you can copy & paste your gr
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
fmt
|
fmt
|
||||||
gql "github.com/lukaszraczylo/simple-gql-client"
|
gql "github.com/lukaszraczylo/go-simple-graphql"
|
||||||
)
|
)
|
||||||
|
|
||||||
headers := map[string]interface{}{
|
headers := map[string]interface{}{
|
||||||
|
|||||||
@@ -3,20 +3,23 @@ module github.com/lukaszraczylo/go-simple-graphql
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/allegro/bigcache/v3 v3.0.1
|
||||||
github.com/buger/jsonparser v1.1.1
|
github.com/buger/jsonparser v1.1.1
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/lukaszraczylo/pandati v0.0.10
|
github.com/lukaszraczylo/pandati v0.0.10
|
||||||
github.com/rs/zerolog v1.25.0
|
github.com/rs/zerolog v1.26.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6
|
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/allegro/bigcache/v3 v3.0.1 h1:Q4Xl3chywXuJNOw7NV+MeySd3zGQDj4KCpkCg0te8mc=
|
||||||
|
github.com/allegro/bigcache/v3 v3.0.1/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
|
||||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
@@ -10,52 +12,58 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
|||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
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/lukaszraczylo/pandati v0.0.10 h1:ZXmLjxb/UYRBVyAKwXmUcJgZ2FYNwGY4YDJsQQMYAXI=
|
github.com/lukaszraczylo/pandati v0.0.10 h1:ZXmLjxb/UYRBVyAKwXmUcJgZ2FYNwGY4YDJsQQMYAXI=
|
||||||
github.com/lukaszraczylo/pandati v0.0.10/go.mod h1:1lE/x4X4LfO1yerAQoiR7AVb/wIabH/zITDGnqTdyH8=
|
github.com/lukaszraczylo/pandati v0.0.10/go.mod h1:1lE/x4X4LfO1yerAQoiR7AVb/wIabH/zITDGnqTdyH8=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II=
|
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
|
||||||
github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI=
|
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk=
|
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c h1:WtYZ93XtWSO5KlOMgPZu7hXY9WhMZpprvlm5VwvAl8c=
|
||||||
golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20191119224855-298f0cb1881e/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.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ package gql
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/allegro/bigcache/v3"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/lukaszraczylo/go-simple-graphql/pkg/logging"
|
"github.com/lukaszraczylo/go-simple-graphql/pkg/logging"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
@@ -33,6 +34,8 @@ type GraphQL struct {
|
|||||||
Endpoint string
|
Endpoint string
|
||||||
HttpClient *http.Client
|
HttpClient *http.Client
|
||||||
Log *logging.LogConfig
|
Log *logging.LogConfig
|
||||||
|
Cache bool // Enable caching for read queries
|
||||||
|
CacheStore *bigcache.BigCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickGraphqlEndpoint() (graphqlEndpoint string) {
|
func pickGraphqlEndpoint() (graphqlEndpoint string) {
|
||||||
@@ -46,19 +49,56 @@ func pickGraphqlEndpoint() (graphqlEndpoint string) {
|
|||||||
return graphqlEndpoint
|
return graphqlEndpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setCacheTTL() int {
|
||||||
|
value, present := os.LookupEnv("GRAPHQL_CACHE_TTL")
|
||||||
|
if present && value != "" {
|
||||||
|
i, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
panic("Invalid value for query cache ttl")
|
||||||
|
}
|
||||||
|
return int(i)
|
||||||
|
} else {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setCacheEnabled() bool {
|
||||||
|
value, present := os.LookupEnv("GRAPHQL_CACHE")
|
||||||
|
if present && value != "" {
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
panic("Invalid value for query cache")
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewConnection() *GraphQL {
|
func NewConnection() *GraphQL {
|
||||||
return &GraphQL{
|
g := GraphQL{
|
||||||
Endpoint: pickGraphqlEndpoint(),
|
Endpoint: pickGraphqlEndpoint(),
|
||||||
HttpClient: &http.Client{
|
HttpClient: &http.Client{
|
||||||
Timeout: time.Second * 30,
|
|
||||||
Transport: &http2.Transport{
|
Transport: &http2.Transport{
|
||||||
DisableCompression: false,
|
DisableCompression: false,
|
||||||
AllowHTTP: true,
|
AllowHTTP: true,
|
||||||
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
PingTimeout: 10 * time.Second,
|
||||||
return net.Dial(network, addr)
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Log: logging.NewLogger(),
|
Log: logging.NewLogger(),
|
||||||
|
Cache: setCacheEnabled(),
|
||||||
|
CacheStore: setupCache(),
|
||||||
}
|
}
|
||||||
|
return &g
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupCache() *bigcache.BigCache {
|
||||||
|
cache, err := bigcache.NewBigCache(bigcache.DefaultConfig(time.Duration(setCacheTTL()) * time.Second))
|
||||||
|
if err != nil {
|
||||||
|
panic("Error creating cache: " + err.Error())
|
||||||
|
}
|
||||||
|
return cache
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package gql
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -29,16 +30,11 @@ func (g *GraphQL) queryBuilder(queryContent string, queryVariables interface{})
|
|||||||
Variables: queryVariables,
|
Variables: queryVariables,
|
||||||
}
|
}
|
||||||
|
|
||||||
// j := new(bytes.Buffer)
|
|
||||||
j2, err := json.Marshal(qb)
|
j2, err := json.Marshal(qb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Log.Critical("Unable to marshal the query", map[string]interface{}{"_error": err.Error(), "_query": queryContent, "_variables": queryVariables})
|
g.Log.Critical("Unable to marshal the query", map[string]interface{}{"_error": err.Error(), "_query": queryContent, "_variables": queryVariables})
|
||||||
return []byte{}, err
|
return []byte{}, err
|
||||||
}
|
}
|
||||||
// if err = json.Compact(j, j2); err != nil {
|
|
||||||
// g.Log.Critical("Unable to compact the query", map[string]interface{}{"error": err.Error()})
|
|
||||||
// return []byte{}, err
|
|
||||||
// }
|
|
||||||
return j2, err
|
return j2, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +45,23 @@ func (g *GraphQL) Query(queryContent string, queryVariables interface{}, queryHe
|
|||||||
g.Log.Error("Unable to build the query", map[string]interface{}{"_error": err.Error()})
|
g.Log.Error("Unable to build the query", map[string]interface{}{"_error": err.Error()})
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var body []byte
|
||||||
|
var queryResult *queryResults
|
||||||
|
queryHash := fmt.Sprintf("%x", md5.Sum(query))
|
||||||
|
|
||||||
|
if g.Cache {
|
||||||
|
g.Log.Debug("Checking the cache for the query", map[string]interface{}{"_query": queryHash})
|
||||||
|
if entry, entryInfo, err := g.CacheStore.GetWithInfo(queryHash); err == nil {
|
||||||
|
g.Log.Debug("Found the query in the cache", map[string]interface{}{"_query": queryHash})
|
||||||
|
if pandati.IsZero(entryInfo.EntryStatus) {
|
||||||
|
return string(entry), nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.Log.Debug("Unable to find the query in the cache", map[string]interface{}{"_query": queryHash, "_error": err.Error()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
httpRequest, err := http.NewRequest("POST", g.Endpoint, bytes.NewBuffer(query))
|
httpRequest, err := http.NewRequest("POST", g.Endpoint, bytes.NewBuffer(query))
|
||||||
httpRequest.Header.Add("Content-Type", "application/json")
|
httpRequest.Header.Add("Content-Type", "application/json")
|
||||||
for header, value := range queryHeaders {
|
for header, value := range queryHeaders {
|
||||||
@@ -63,12 +76,12 @@ func (g *GraphQL) Query(queryContent string, queryVariables interface{}, queryHe
|
|||||||
defer io.Copy(ioutil.Discard, httpResponse.Body)
|
defer io.Copy(ioutil.Discard, httpResponse.Body)
|
||||||
defer httpResponse.Body.Close()
|
defer httpResponse.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(httpResponse.Body)
|
body, err = ioutil.ReadAll(httpResponse.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Log.Critical("Unable to read the response", map[string]interface{}{"_error": err.Error()})
|
g.Log.Critical("Unable to read the response", map[string]interface{}{"_error": err.Error()})
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
var queryResult *queryResults
|
|
||||||
err = json.Unmarshal(body, &queryResult)
|
err = json.Unmarshal(body, &queryResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Log.Error("Unable to unmarshal the query", map[string]interface{}{"_error": err.Error()})
|
g.Log.Error("Unable to unmarshal the query", map[string]interface{}{"_error": err.Error()})
|
||||||
@@ -91,5 +104,15 @@ func (g *GraphQL) Query(queryContent string, queryVariables interface{}, queryHe
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if g.Cache {
|
||||||
|
g.Log.Debug("Caching the query", map[string]interface{}{"_query": queryHash})
|
||||||
|
if queryContent[0:5] == "query" {
|
||||||
|
err = g.CacheStore.Set(queryHash, []byte(responseContent))
|
||||||
|
if err != nil {
|
||||||
|
g.Log.Error("Unable to cache the query", map[string]interface{}{"_query": queryHash, "_error": err.Error()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-65
@@ -1,69 +1,69 @@
|
|||||||
package gql
|
package gql
|
||||||
|
|
||||||
import (
|
// import (
|
||||||
"testing"
|
// "testing"
|
||||||
)
|
// )
|
||||||
|
|
||||||
func Benchmark_GraphQL_Query(t *testing.B) {
|
// func Benchmark_GraphQL_Query(t *testing.B) {
|
||||||
if testing.Short() {
|
// if testing.Short() {
|
||||||
t.Skip("Skipping test in short / CI mode")
|
// t.Skip("Skipping test in short / CI mode")
|
||||||
}
|
// }
|
||||||
type args struct {
|
// type args struct {
|
||||||
queryContent string
|
// queryContent string
|
||||||
queryVariables interface{}
|
// queryVariables interface{}
|
||||||
}
|
// }
|
||||||
tests := []struct {
|
// tests := []struct {
|
||||||
name string
|
// name string
|
||||||
endpoint string
|
// endpoint string
|
||||||
isLocal bool
|
// isLocal bool
|
||||||
args args
|
// args args
|
||||||
wantResult string
|
// wantResult string
|
||||||
mockedReply string
|
// mockedReply string
|
||||||
wantErr bool
|
// wantErr bool
|
||||||
}{
|
// }{
|
||||||
{
|
// {
|
||||||
name: "Valid query",
|
// name: "Valid query",
|
||||||
endpoint: "http://hasura.local/v1/graphql",
|
// endpoint: "http://hasura.local/v1/graphql",
|
||||||
isLocal: false,
|
// isLocal: false,
|
||||||
args: args{
|
// args: args{
|
||||||
queryContent: `query listUserBots {
|
// queryContent: `query listUserBots {
|
||||||
tbl_bots(limit: 1) {
|
// tbl_bots(limit: 1) {
|
||||||
bot_name
|
// bot_name
|
||||||
}
|
// }
|
||||||
}`,
|
// }`,
|
||||||
queryVariables: nil,
|
// queryVariables: nil,
|
||||||
},
|
// },
|
||||||
wantResult: `{"tbl_bots":[{"bot_name":"littleMentionBot"}]}`,
|
// wantResult: `{"tbl_bots":[{"bot_name":"littleMentionBot"}]}`,
|
||||||
mockedReply: `{"data":{"tbl_bots":[{"bot_name":"littleMentionBot"}]}}`,
|
// mockedReply: `{"data":{"tbl_bots":[{"bot_name":"littleMentionBot"}]}}`,
|
||||||
wantErr: false,
|
// wantErr: false,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: "Invalid query",
|
// name: "Invalid query",
|
||||||
endpoint: "http://hasura.local/v1/graphql",
|
// endpoint: "http://hasura.local/v1/graphql",
|
||||||
isLocal: false,
|
// isLocal: false,
|
||||||
args: args{
|
// args: args{
|
||||||
queryContent: `query listUserBots {
|
// queryContent: `query listUserBots {
|
||||||
tbl_botz(limit: 1) {
|
// tbl_botz(limit: 1) {
|
||||||
bot_name
|
// bot_name
|
||||||
}
|
// }
|
||||||
}`,
|
// }`,
|
||||||
queryVariables: nil,
|
// queryVariables: nil,
|
||||||
},
|
// },
|
||||||
mockedReply: `{"errors":[{"message":"Unknown field \"tbl_botz\" on type \"Query\""}]}`,
|
// mockedReply: `{"errors":[{"message":"Unknown field \"tbl_botz\" on type \"Query\""}]}`,
|
||||||
wantResult: ``,
|
// wantResult: ``,
|
||||||
wantErr: true,
|
// wantErr: true,
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
|
|
||||||
for _, tt := range tests {
|
// for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.B) {
|
// t.Run(tt.name, func(t *testing.B) {
|
||||||
g := NewConnection()
|
// g := NewConnection()
|
||||||
server, serverURL := mockGraphQLServerResponses(tt.mockedReply)
|
// server, serverURL := mockGraphQLServerResponses(tt.mockedReply)
|
||||||
g.Endpoint = serverURL
|
// g.Endpoint = serverURL
|
||||||
for n := 0; n < t.N; n++ {
|
// for n := 0; n < t.N; n++ {
|
||||||
g.Query(tt.args.queryContent, tt.args.queryVariables, nil)
|
// g.Query(tt.args.queryContent, tt.args.queryVariables, nil)
|
||||||
}
|
// }
|
||||||
server.Close()
|
// server.Close()
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
+71
-14
@@ -1,7 +1,7 @@
|
|||||||
package gql
|
package gql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -54,22 +54,58 @@ func (suite *TestSuite) Test_GraphQL_Query() {
|
|||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
suite.T().Skip("Skipping test in short / CI mode")
|
suite.T().Skip("Skipping test in short / CI mode")
|
||||||
}
|
}
|
||||||
|
g := NewConnection()
|
||||||
|
|
||||||
type args struct {
|
type args struct {
|
||||||
queryContent string
|
queryContent string
|
||||||
queryVariables interface{}
|
queryVariables interface{}
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
endpoint string
|
endpoint string
|
||||||
isLocal bool
|
isLocal bool
|
||||||
args args
|
cache_enabled bool
|
||||||
wantResult string
|
args args
|
||||||
wantErr bool
|
wantResult string
|
||||||
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Valid query",
|
name: "Valid query, no cache",
|
||||||
endpoint: "http://hasura.local/v1/graphql",
|
endpoint: "http://hasura.local/v1/graphql",
|
||||||
isLocal: true,
|
isLocal: true,
|
||||||
|
cache_enabled: false,
|
||||||
|
args: args{
|
||||||
|
queryContent: `query listUserBots {
|
||||||
|
tbl_bots(limit: 1) {
|
||||||
|
bot_name
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
queryVariables: nil,
|
||||||
|
},
|
||||||
|
wantResult: `{"tbl_bots":[{"bot_name":"littleMentionBot"}]}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Valid query, with cache empty",
|
||||||
|
endpoint: "http://hasura.local/v1/graphql",
|
||||||
|
isLocal: true,
|
||||||
|
cache_enabled: true,
|
||||||
|
args: args{
|
||||||
|
queryContent: `query listUserBots {
|
||||||
|
tbl_bots(limit: 1) {
|
||||||
|
bot_name
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
queryVariables: nil,
|
||||||
|
},
|
||||||
|
wantResult: `{"tbl_bots":[{"bot_name":"littleMentionBot"}]}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Valid query, with cache filled",
|
||||||
|
endpoint: "http://hasura.local/v1/graphql",
|
||||||
|
isLocal: true,
|
||||||
|
cache_enabled: true,
|
||||||
args: args{
|
args: args{
|
||||||
queryContent: `query listUserBots {
|
queryContent: `query listUserBots {
|
||||||
tbl_bots(limit: 1) {
|
tbl_bots(limit: 1) {
|
||||||
@@ -96,13 +132,33 @@ func (suite *TestSuite) Test_GraphQL_Query() {
|
|||||||
wantResult: ``,
|
wantResult: ``,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Valid query to https endpoint",
|
||||||
|
endpoint: "https://web-dev.telegram-bot.app/v1/graphql",
|
||||||
|
isLocal: false,
|
||||||
|
args: args{
|
||||||
|
queryContent: `query packages_prices {
|
||||||
|
available_packages: tbl_available_packages(where: {enabled: {_eq: true}}) {
|
||||||
|
package_name
|
||||||
|
package_discount
|
||||||
|
package_price
|
||||||
|
package_size
|
||||||
|
package_type
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
queryVariables: nil,
|
||||||
|
},
|
||||||
|
wantResult: `{"available_packages":[{"package_discount":0,"package_name":"media_1000","package_price":750,"package_size":1000,"package_type":"media"},{"package_discount":5,"package_name":"media_5000","package_price":3563,"package_size":5000,"package_type":"media"},{"package_discount":10,"package_name":"media_10000","package_price":6750,"package_size":10000,"package_type":"media"},{"package_discount":15,"package_name":"media_25000","package_price":15938,"package_size":25000,"package_type":"media"},{"package_discount":0,"package_name":"voice_500","package_price":1000,"package_size":500,"package_type":"voice"},{"package_discount":10,"package_name":"voice_1000","package_price":1800,"package_size":1000,"package_type":"voice"},{"package_discount":15,"package_name":"voice_2500","package_price":4250,"package_size":2500,"package_type":"voice"}]}`,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
suite.T().Run(tt.name, func(t *testing.T) {
|
suite.T().Run(tt.name, func(t *testing.T) {
|
||||||
if tt.isLocal {
|
// if tt.isLocal {
|
||||||
os.Setenv("GRAPHQL_ENDPOINT", tt.endpoint)
|
// os.Setenv("GRAPHQL_ENDPOINT", tt.endpoint)
|
||||||
}
|
// }
|
||||||
g := NewConnection()
|
g.Endpoint = tt.endpoint
|
||||||
|
g.Cache = tt.cache_enabled
|
||||||
gotResult, gotErr := g.Query(tt.args.queryContent, tt.args.queryVariables, nil)
|
gotResult, gotErr := g.Query(tt.args.queryContent, tt.args.queryVariables, nil)
|
||||||
if tt.wantErr {
|
if tt.wantErr {
|
||||||
assert.Error(t, gotErr)
|
assert.Error(t, gotErr)
|
||||||
@@ -110,4 +166,5 @@ func (suite *TestSuite) Test_GraphQL_Query() {
|
|||||||
assert.Equal(t, tt.wantResult, gotResult)
|
assert.Equal(t, tt.wantResult, gotResult)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fmt.Println(g.CacheStore.Capacity())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user