diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 5707ed1..d23a7ad --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ .vscode/ /notes -# Created by https://www.toptal.com/developers/gitignore/api/go,visualstudiocode,macos,linux -# Edit at https://www.toptal.com/developers/gitignore?templates=go,visualstudiocode,macos,linux +# Created by https://www.toptal.com/developers/gitignore/api/go,macos,linux,visualstudiocode,intellij+all +# Edit at https://www.toptal.com/developers/gitignore?templates=go,macos,linux,visualstudiocode,intellij+all ### Go ### # If you prefer the allow list template instead of the deny list, see community template: @@ -31,6 +31,94 @@ go.work /vendor/ /Godeps/ +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + ### Linux ### *~ @@ -75,6 +163,10 @@ Network Trash Folder Temporary Items .apdisk +### macOS Patch ### +# iCloud generated files +*.icloud + ### VisualStudioCode ### .vscode/* !.vscode/settings.json @@ -95,5 +187,9 @@ Temporary Items .ionide # Support for Project snippet scope +.vscode/*.code-snippets + +# Ignore code-workspaces +*.code-workspace -# End of https://www.toptal.com/developers/gitignore/api/go,visualstudiocode,macos,linux \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/go,macos,linux,visualstudiocode,intellij+all diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index a0d73d9..d776ade --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ This is an implementation of a client for [ws4sqlite](https://github.com/proofro Each client's minor release is guaranteed to be compatible with the matching minor release of ws4sqlite. So, for ws4sqlite's version `0.11.0`, use any of the client's `0.11.x` versions. +In addition, versions `0.11.x` of this package are also compatible with versions `0.12.x` of ws4sqlite. + The library requires Go 1.17 or higher. ## Import @@ -61,7 +63,7 @@ if err != nil { } // Call ws4sqlite, obtaining a response and the status code (and a possible error) -// Status code is !=0 if the method got a response from ws4sqlite, regardless of error. +// Status code is !=0 if the method got a response from ws4sqlite, regardless of errors. res, code, err := cli.Send(req) // Code is 200? diff --git a/client.go b/client.go old mode 100644 new mode 100755 index b9e525a..e64a919 --- a/client.go +++ b/client.go @@ -16,10 +16,11 @@ package ws4sqlite_client -// 0.11.0 +// 0.11.1 import ( "bytes" + "context" "encoding/json" "errors" "fmt" @@ -54,14 +55,12 @@ const ( // // Example: // -// cli, err := ws4.NewClientBuilder(). -// WithURL("http://localhost:12321/db2"). -// WithInlineAuth("myUser1", "myHotPassword"). -// Build() -// -// cli.Send(...) -// +// cli, err := ws4.NewClientBuilder(). +// WithURL("http://localhost:12321/db2"). +// WithInlineAuth("myUser1", "myHotPassword"). +// Build() // +// cli.Send(...) type ClientBuilder struct { url string authMode AuthMode @@ -75,12 +74,12 @@ type ClientBuilder struct { // // Example: // -// cli, err := ws4.NewClientBuilder(). -// WithURL("http://localhost:12321/db2"). -// WithInlineAuth("myUser1", "myHotPassword"). -// Build() +// cli, err := ws4.NewClientBuilder(). +// WithURL("http://localhost:12321/db2"). +// WithInlineAuth("myUser1", "myHotPassword"). +// Build() // -// cli.Send(...) +// cli.Send(...) type Client struct { ClientBuilder } @@ -144,6 +143,15 @@ func (cb *ClientBuilder) Build() (*Client, error) { // Returns a WsError if the remote service returns a processing error. If the // communication fails, it returns the "naked" error, so check for cast-ability. func (c *Client) Send(req *Request) (*Response, int, error) { + return c.SendWithContext(context.Background(), req) +} + +// SendWithContext sends a set of requests to the remote with context, wrapped in a Request. +// Returns a matching set of responses, wrapped in a Response struct. +// +// Returns a WsError if the remote service returns a processing error. If the +// communication fails, it returns the "naked" error, so check for cast-ability. +func (c *Client) SendWithContext(ctx context.Context, req *Request) (*Response, int, error) { if c.authMode == AUTH_MODE_INLINE { req.req.Credentials = &credentials{ User: c.user, @@ -157,7 +165,7 @@ func (c *Client) Send(req *Request) (*Response, int, error) { } client := &http.Client{} - post, err := http.NewRequest("POST", c.url, bytes.NewBuffer(jsonData)) + post, err := http.NewRequestWithContext(ctx, "POST", c.url, bytes.NewBuffer(jsonData)) if err != nil { return nil, 0, err } diff --git a/errors.go b/errors.go old mode 100644 new mode 100755 diff --git a/go.mod b/go.mod old mode 100644 new mode 100755 index f952774..a36edc8 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/proofrock/ws4sqlite-client-go -go 1.17 +go 1.19 diff --git a/request.go b/request.go old mode 100644 new mode 100755 diff --git a/response.go b/response.go old mode 100644 new mode 100755 diff --git a/test/mydb.yaml b/test/mydb.yaml old mode 100644 new mode 100755 diff --git a/test/mydb2.yaml b/test/mydb2.yaml old mode 100644 new mode 100755 diff --git a/test/ws4sqlite-0.11.0 b/test/ws4sqlite-0.11.0 deleted file mode 100755 index 154c817..0000000 Binary files a/test/ws4sqlite-0.11.0 and /dev/null differ diff --git a/test/ws4sqlite b/test/ws4sqlite-0.12.2 similarity index 63% rename from test/ws4sqlite rename to test/ws4sqlite-0.12.2 index 2f19de6..7dc1feb 100755 Binary files a/test/ws4sqlite and b/test/ws4sqlite-0.12.2 differ diff --git a/ws4sqlite_client_test.go b/ws4sqlite_client_test.go old mode 100644 new mode 100755 index 54fedce..8da5d73 --- a/ws4sqlite_client_test.go +++ b/ws4sqlite_client_test.go @@ -17,6 +17,8 @@ package ws4sqlite_client_test import ( + "context" + "errors" "os" "os/exec" "syscall" @@ -34,7 +36,7 @@ func kill(cmd *exec.Cmd) { } func TestMain(m *testing.M) { - cmd := exec.Command("test/ws4sqlite-0.11.0", "--mem-db", "mydb:test/mydb.yaml", "--mem-db", "mydb2:test/mydb2.yaml") + cmd := exec.Command("test/ws4sqlite-0.12.2", "--mem-db", "mydb:test/mydb.yaml", "--mem-db", "mydb2:test/mydb2.yaml") err := cmd.Start() if err != nil { @@ -244,3 +246,39 @@ func TestError(t *testing.T) { t.Error("error is not 500") } } + +func TestCancel(t *testing.T) { + client, err := ws4.NewClientBuilder(). + WithURLComponents(ws4.PROTOCOL_HTTP, "localhost", 12321, "mydb2"). + WithInlineAuth("myUser1", "myHotPassword"). + Build() + + if err != nil { + t.Error(err) + } + + request, err := ws4.NewRequestBuilder(). + AddQuery("SELENCT * FROM TEMP"). + Build() + + if err != nil { + t.Error(err) + } + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + _, code, err := client.SendWithContext(ctx, request) + + if err == nil { + t.Error("did not fail, but should have") + } + + if code == 200 { + t.Error("did return 200, but shouldn't have") + } + + if !errors.Is(err, context.Canceled) { + t.Error("err is not a Context Cancelled") + } +}