Skip to content

Commit

Permalink
feat: api support zstd
Browse files Browse the repository at this point in the history
  • Loading branch information
SevereCloud committed Jan 24, 2022
1 parent c58c2c9 commit 15a6084
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Version API 5.131.
- 500+ methods
- Ability to modify HTTP client
- Request Limiter
- Support [MessagePack](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.EnableMessagePack)
- Support [zstd](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.EnableZstd)
and [MessagePack](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.EnableMessagePack)
- Token pool
- [OAuth](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api/oauth)
- [Callback API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/callback)
Expand Down
27 changes: 20 additions & 7 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,28 @@ if errors.As(err, &e) {

Для Execute существует отдельная ошибка `ExecuteErrors`

### Поддержка MessagePack
### Поддержка MessagePack и zstd

ВНИМАНИЕ, ЭТО ЭКСПЕРИМЕНТАЛЬНАЯ ФУНКЦИЯ. Некоторые методы могут возвращать
сломанную кодировку.
> Результат перехода с gzip (JSON) на zstd (msgpack):
>
> - в 7 раз быстрее сжатие (–1 мкс);
> - на 10% меньше размер данных (8 Кбайт вместо 9 Кбайт);
> - продуктовый эффект не статзначимый :(
>
> [Как мы отказались от JPEG, JSON, TCP и ускорили ВКонтакте в два раза](https://habr.com/ru/company/vk/blog/594633/)
VK API способно возвращать ответ в виде [MessagePack](https://msgpack.org/).
Это эффективный формат двоичной сериализации, похожий на JSON, только быстрее
и меньше по размеру.

ВНИМАНИЕ, C MessagePack НЕКОТОРЫЕ МЕТОДЫ МОГУТ ВОЗВРАЩАТЬ
СЛОМАННУЮ КОДИРОВКУ.

Для сжатия, вместо классического gzip, можно использовать
[zstd](https://github.com/facebook/zstd). Сейчас vksdk поддерживает zstd без
словаря. Если кто знает как получать словарь,
[отпишитесь сюда](https://github.com/SevereCloud/vksdk/issues/180).

```go
vk := api.NewVK(os.Getenv("USER_TOKEN"))

Expand All @@ -99,16 +112,16 @@ params := api.Params{
"need_stickers": true,
}

r, err := vk.Request(method, params)
r, err := vk.Request(method, params) // Content-Length: 44758
if err != nil {
log.Fatal(err)
}
log.Println("json:", len(r)) // json: 814231

// Включаем поддержку MessagePack
vk.EnableMessagePack(true)
vk.EnableMessagePack() // Включаем поддержку MessagePack
vk.EnableZstd() // Включаем поддержку zstd

r, err = vk.Request(method, params)
r, err = vk.Request(method, params) // Content-Length: 35755
if err != nil {
log.Fatal(err)
}
Expand Down
33 changes: 31 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ package api // import "github.com/SevereCloud/vksdk/v2/api"

import (
"bytes"
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io"
"mime"
"net/http"
"net/url"
Expand All @@ -21,6 +23,7 @@ import (
"github.com/SevereCloud/vksdk/v2"
"github.com/SevereCloud/vksdk/v2/internal"
"github.com/SevereCloud/vksdk/v2/object"
"github.com/klauspost/compress/zstd"
"github.com/vmihailenco/msgpack/v5"
)

Expand Down Expand Up @@ -93,6 +96,7 @@ type VK struct {
Handler func(method string, params ...Params) (Response, error)

msgpack bool
zstd bool

mux sync.Mutex
lastTime time.Time
Expand Down Expand Up @@ -246,24 +250,42 @@ func (vk *VK) DefaultHandler(method string, sliceParams ...Params) (Response, er
return response, err
}

acceptEncoding := "gzip"
if vk.zstd {
acceptEncoding = "zstd"
}

req.Header.Set("User-Agent", vk.UserAgent)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

req.Header.Set("Accept-Encoding", acceptEncoding)

var reader io.Reader

resp, err := vk.Client.Do(req)
if err != nil {
return response, err
}

switch resp.Header.Get("Content-Encoding") {
case "zstd":
reader, _ = zstd.NewReader(resp.Body)
case "gzip":
reader, _ = gzip.NewReader(resp.Body)
default:
reader = resp.Body
}

mediatype, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
switch mediatype {
case "application/json":
err = json.NewDecoder(resp.Body).Decode(&response)
err = json.NewDecoder(reader).Decode(&response)
if err != nil {
_ = resp.Body.Close()
return response, err
}
case "application/x-msgpack":
dec := msgpack.NewDecoder(resp.Body)
dec := msgpack.NewDecoder(reader)
dec.SetCustomStructTag("json")

err = dec.Decode(&response)
Expand Down Expand Up @@ -341,6 +363,13 @@ func (vk *VK) EnableMessagePack() {
vk.msgpack = true
}

// EnableZstd enable using zstd instead of gzip.
//
// This not use dict.
func (vk *VK) EnableZstd() {
vk.zstd = true
}

func fmtReflectValue(value reflect.Value, depth int) string {
switch f := value; value.Kind() {
case reflect.Invalid:
Expand Down
20 changes: 20 additions & 0 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,23 @@ func TestContext(t *testing.T) {
_, err := vkUser.UsersGet(p)
assert.EqualError(t, err, "Post \"https://api.vk.com/method/users.get\": context deadline exceeded")
}

func TestVK_EnableMessagePack(t *testing.T) {
t.Parallel()

vk := api.NewVK("")
vk.EnableMessagePack()

_, err := vk.UsersGet(nil)
assert.ErrorIs(t, err, api.ErrAuth)
}

func TestVK_EnableZstd(t *testing.T) {
t.Parallel()

vk := api.NewVK("")
vk.EnableZstd()

_, err := vk.UsersGet(nil)
assert.ErrorIs(t, err, api.ErrAuth)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.16
require (
github.com/gorilla/schema v1.2.0
github.com/gorilla/websocket v1.4.2
github.com/klauspost/compress v1.14.1
github.com/stretchr/testify v1.7.0
github.com/vmihailenco/msgpack/v5 v5.3.5
golang.org/x/text v0.3.7
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/klauspost/compress v1.14.1 h1:hLQYb23E8/fO+1u53d02A97a8UnsddcvYzq4ERRU4ds=
github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down

0 comments on commit 15a6084

Please sign in to comment.