mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-16 16:17:38 +03:00
c9f43eaa1b
* Response.ContentEncoding(): store as field The CE is not so often used for plain APIs responses and even not so often used for static files and on the fly compression. But still it should be checked each time. Also having a dedicated field getter and setter simplifies code * header.go Use shorter Response.setNonSpecial() and Request.setNonSpecial() methods instead of SetCanonical() The change should improve performance because the setSpecialHeader() call is omitted. As a downside on adding a new basic header field all putHeader() must be replaced with a direct getter and setter.
178 lines
4.5 KiB
Go
178 lines
4.5 KiB
Go
package fasthttp
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"testing"
|
|
)
|
|
|
|
func TestBrotliBytesSerial(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := testBrotliBytes(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestBrotliBytesConcurrent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := testConcurrent(10, testBrotliBytes); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func testBrotliBytes() error {
|
|
for _, s := range compressTestcases {
|
|
if err := testBrotliBytesSingleCase(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func testBrotliBytesSingleCase(s string) error {
|
|
prefix := []byte("foobar")
|
|
brotlipedS := AppendBrotliBytes(prefix, []byte(s))
|
|
if !bytes.Equal(brotlipedS[:len(prefix)], prefix) {
|
|
return fmt.Errorf("unexpected prefix when compressing %q: %q. Expecting %q", s, brotlipedS[:len(prefix)], prefix)
|
|
}
|
|
|
|
unbrotliedS, err := AppendUnbrotliBytes(prefix, brotlipedS[len(prefix):])
|
|
if err != nil {
|
|
return fmt.Errorf("unexpected error when uncompressing %q: %w", s, err)
|
|
}
|
|
if !bytes.Equal(unbrotliedS[:len(prefix)], prefix) {
|
|
return fmt.Errorf("unexpected prefix when uncompressing %q: %q. Expecting %q", s, unbrotliedS[:len(prefix)], prefix)
|
|
}
|
|
unbrotliedS = unbrotliedS[len(prefix):]
|
|
if string(unbrotliedS) != s {
|
|
return fmt.Errorf("unexpected uncompressed string %q. Expecting %q", unbrotliedS, s)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestBrotliCompressSerial(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := testBrotliCompress(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestBrotliCompressConcurrent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := testConcurrent(10, testBrotliCompress); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func testBrotliCompress() error {
|
|
for _, s := range compressTestcases {
|
|
if err := testBrotliCompressSingleCase(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func testBrotliCompressSingleCase(s string) error {
|
|
var buf bytes.Buffer
|
|
zw := acquireStacklessBrotliWriter(&buf, CompressDefaultCompression)
|
|
if _, err := zw.Write([]byte(s)); err != nil {
|
|
return fmt.Errorf("unexpected error: %w. s=%q", err, s)
|
|
}
|
|
releaseStacklessBrotliWriter(zw, CompressDefaultCompression)
|
|
|
|
zr, err := acquireBrotliReader(&buf)
|
|
if err != nil {
|
|
return fmt.Errorf("unexpected error: %w. s=%q", err, s)
|
|
}
|
|
body, err := ioutil.ReadAll(zr)
|
|
if err != nil {
|
|
return fmt.Errorf("unexpected error: %w. s=%q", err, s)
|
|
}
|
|
if string(body) != s {
|
|
return fmt.Errorf("unexpected string after decompression: %q. Expecting %q", body, s)
|
|
}
|
|
releaseBrotliReader(zr)
|
|
return nil
|
|
}
|
|
|
|
func TestCompressHandlerBrotliLevel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
expectedBody := string(createFixedBody(2e4))
|
|
h := CompressHandlerBrotliLevel(func(ctx *RequestCtx) {
|
|
ctx.Write([]byte(expectedBody)) //nolint:errcheck
|
|
}, CompressBrotliDefaultCompression, CompressDefaultCompression)
|
|
|
|
var ctx RequestCtx
|
|
var resp Response
|
|
|
|
// verify uncompressed response
|
|
h(&ctx)
|
|
s := ctx.Response.String()
|
|
br := bufio.NewReader(bytes.NewBufferString(s))
|
|
if err := resp.Read(br); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
ce := resp.Header.ContentEncoding()
|
|
if string(ce) != "" {
|
|
t.Fatalf("unexpected Content-Encoding: %q. Expecting %q", ce, "")
|
|
}
|
|
body := resp.Body()
|
|
if string(body) != expectedBody {
|
|
t.Fatalf("unexpected body %q. Expecting %q", body, expectedBody)
|
|
}
|
|
|
|
// verify gzip-compressed response
|
|
ctx.Request.Reset()
|
|
ctx.Response.Reset()
|
|
ctx.Request.Header.Set("Accept-Encoding", "gzip, deflate, sdhc")
|
|
|
|
h(&ctx)
|
|
s = ctx.Response.String()
|
|
br = bufio.NewReader(bytes.NewBufferString(s))
|
|
if err := resp.Read(br); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
ce = resp.Header.ContentEncoding()
|
|
if string(ce) != "gzip" {
|
|
t.Fatalf("unexpected Content-Encoding: %q. Expecting %q", ce, "gzip")
|
|
}
|
|
body, err := resp.BodyGunzip()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if string(body) != expectedBody {
|
|
t.Fatalf("unexpected body %q. Expecting %q", body, expectedBody)
|
|
}
|
|
|
|
// verify brotli-compressed response
|
|
ctx.Request.Reset()
|
|
ctx.Response.Reset()
|
|
ctx.Request.Header.Set("Accept-Encoding", "gzip, deflate, sdhc, br")
|
|
|
|
h(&ctx)
|
|
s = ctx.Response.String()
|
|
br = bufio.NewReader(bytes.NewBufferString(s))
|
|
if err := resp.Read(br); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
ce = resp.Header.ContentEncoding()
|
|
if string(ce) != "br" {
|
|
t.Fatalf("unexpected Content-Encoding: %q. Expecting %q", ce, "br")
|
|
}
|
|
body, err = resp.BodyUnbrotli()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if string(body) != expectedBody {
|
|
t.Fatalf("unexpected body %q. Expecting %q", body, expectedBody)
|
|
}
|
|
}
|