ytsaurus / ytsaurus/ytsaurus

bug(sdk/go): http client generates invalid header values

Open
#42 0 comments 0 reactions 1 assignee Claimed by @verytable View on GitHub
Bug go SDK
Dominant language
C++
Stars
2.2k
Forks
219
PR merge metrics
No merged PRs in 30d

Description

Sending a `select_rows` command with a placeholder with a binary value leads to a `net/http: invalid header field value for "X-Yt-Parameters"` error.

It seems YSON text encoder does not escape some characters considered by HTTP as control.

Reproducer

```go
package internal_test

import (
"context"
"fmt"
"testing"

"go.uber.org/zap/zaptest"
ytzap "go.ytsaurus.tech/library/go/core/log/zap"
"go.ytsaurus.tech/yt/go/yson"
"go.ytsaurus.tech/yt/go/yt"
"go.ytsaurus.tech/yt/go/yt/ythttp"
)

// placeholderSet is a simple wrapper to encode placeholder values.
//
// See https://github.com/ytsaurus/ytsaurus/blob/bbaedcf016db5e599563bb3f3b5ba87b047b4faa/yt/yt/library/query/base/query_preparer.cpp#L2461.
type placeholderSet struct {
values []any
}

func (p placeholderSet) MarshalYSON(w *yson.Writer) error {
w.BeginMap()
for i, v := range p.values {
w.MapKeyString(fmt.Sprintf("placeholder%d", i))
w.Any(v)
}
w.EndMap()
return nil
}

func TestPlaceholders(t *testing.T) {
ctx := context.Background()

log := zaptest.NewLogger(t)
yc, err := ythttp.NewClient(&yt.Config{
Logger: &ytzap.Logger{L: log},
})
if err != nil {
t.Fatal(err)
}

var (
id = [16]byte{
0x1f, 0x1f, 0x1f, 0x1f, // <- 0x1f is a control character (unit separator)
0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x1f,
}
// Table schema does not matter, since query does not actually reach the proxy.
query = "* from [//table] where uuid = {placeholder0}"
placeholders = placeholderSet{
values: []any{id[:]},
}
)

r, err := yc.SelectRows(ctx, query, &yt.SelectRowsOptions{
PlaceholderValues: placeholders,
})
if err != nil {
t.Fatal(err)
}
defer r.Close()
}
```

Logs

```
2023-06-01T21:28:18.836+0300 DEBUG request started {"call_id": "f4d2888d-b94c52bc-7541d52f-5e7febcf", "method": "select_rows", "query": "* from [//table] where uuid = {placeholder0}"}
2023-06-01T21:28:18.836+0300 DEBUG sending HTTP request {"call_id": "f4d2888d-b94c52bc-7541d52f-5e7febcf", "proxy": "localhost:8000"}
2023-06-01T21:28:18.836+0300 WARN retrying heavy read request {"call_id": "f4d2888d-b94c52bc-7541d52f-5e7febcf", "backoff": "2.012342203s", "error": "Get \"http://localhost:8000/api/v4/select_rows\": net/http: invalid header field value for \"X-Yt-Parameters\""}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.