diff --git a/Dockerfile b/Dockerfile index 36e45588..efa4a22f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM golang:1.13-alpine AS build +FROM golang:1.16-alpine AS build -RUN apk add --update zstd-static zstd-dev make gcc musl-dev git +RUN apk add --no-cache --update zstd-static zstd-dev make gcc musl-dev git libc6-compat RUN go get golang.org/x/lint/golint RUN mkdir -p /go/src/github.com/Vertamedia/chproxy WORKDIR /go/src/github.com/Vertamedia/chproxy diff --git a/Makefile b/Makefile index 9617aace..a66b71fc 100644 --- a/Makefile +++ b/Makefile @@ -38,8 +38,8 @@ clean: release-build: @echo "Ver: $(BUILD_TAG), OPTS: $(BUILD_OPTS)" - GOOS=linux GOARCH=amd64 go build $(BUILD_OPTS) - rm chproxy-linux-amd64-*.tar.gz + @GOOS=linux GOARCH=amd64 go build $(BUILD_OPTS) + @if [ -f chproxy-linux-amd64-*.tar.gz ]; then rm chproxy-linux-amd64-*.tar.gz; fi tar czf chproxy-linux-amd64-$(BUILD_TAG).tar.gz chproxy release: format lint test clean release-build diff --git a/main_test.go b/main_test.go index d1c63b1b..77414cab 100644 --- a/main_test.go +++ b/main_test.go @@ -13,6 +13,7 @@ import ( "net/http/httptest" "net/url" "os" + "strconv" "strings" "sync" "testing" @@ -285,11 +286,13 @@ func TestServe(t *testing.T) { startHTTP, }, { - "http POST request with session id", + "http POST request with session_id and session_timeout", "testdata/http-session-id.yml", func(t *testing.T) { + sessionName := "name" + sessionTimeout := 900 req, err := http.NewRequest("POST", - "http://127.0.0.1:9090/?query_id=45395792-a432-4b92-8cc9-536c14e1e1a9&extremes=0&session_id=default-session-id233", + "http://127.0.0.1:9090/?query_id=45395792-a432-4b92-8cc9-536c14e1e1a9&extremes=0&session_id="+sessionName+"&session_timeout="+strconv.Itoa(sessionTimeout), bytes.NewBufferString("SELECT * FROM system.numbers LIMIT 10")) req.Header.Set("Content-Type", "application/x-www-form-urlencoded;") // This makes it work @@ -297,9 +300,22 @@ func TestServe(t *testing.T) { resp, err := http.DefaultClient.Do(req) checkErr(t, err) - if resp.StatusCode != http.StatusOK || resp.StatusCode != http.StatusOK && resp.Header.Get("X-Clickhouse-Server-Session-Id") == "" { + if resp.StatusCode != http.StatusOK { t.Fatalf("unexpected status code: %d; expected: %d", resp.StatusCode, http.StatusOK) } + + // verify correctness of session_id + _sessionName := resp.Header.Get("X-Clickhouse-Server-Session-Id") + if _sessionName != sessionName { + t.Fatalf("unexpected value of X-Clickhouse-Server-Session-Id: %s; expected: %s", _sessionName, sessionName) + } + + // verify correctness of session_id + _sessionTimeout, _ := strconv.Atoi(resp.Header.Get("X-Clickhouse-Server-Session-Timeout")) + if _sessionTimeout != sessionTimeout { + t.Fatalf("unexpected value of X-Clickhouse-Server-Session-Timeout: %d; expected: %d", _sessionTimeout, sessionTimeout) + } + resp.Body.Close() }, startHTTP, diff --git a/proxy.go b/proxy.go index 11684b6d..134dfe71 100644 --- a/proxy.go +++ b/proxy.go @@ -103,6 +103,11 @@ func (rp *reverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("X-ClickHouse-Server-Session-Id", s.sessionId) } + // publish session_timeout if needed + if s.sessionId != "" { + rw.Header().Set("X-ClickHouse-Server-Session-Timeout", strconv.Itoa(s.sessionTimeout)) + } + if s.user.cache == nil { rp.proxyRequest(s, srw, srw, req) } else { diff --git a/utils.go b/utils.go index c3de05fb..cd40e976 100644 --- a/utils.go +++ b/utils.go @@ -56,7 +56,7 @@ func getSessionId(req *http.Request) string { func getSessionTimeout(req *http.Request) int { params := req.URL.Query() sessionTimeout, err := strconv.Atoi(params.Get("session_timeout")) - if err != nil && sessionTimeout > 0 { + if err == nil && sessionTimeout > 0 { return sessionTimeout } return 60