Skip to content

Commit a680b16

Browse files
committed
Support requests with gzip and deflate content encodings.
1 parent b203729 commit a680b16

File tree

3 files changed

+125
-12
lines changed

3 files changed

+125
-12
lines changed

params.go

+33-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package rapidrows
1818

1919
import (
20+
"compress/flate"
21+
"compress/gzip"
2022
"encoding/json"
2123
"errors"
2224
"fmt"
@@ -401,16 +403,38 @@ func (a *APIServer) getParams(req *http.Request, ep *Endpoint,
401403
)
402404
if req.Method == "GET" {
403405
urlData = req.URL.Query()
404-
} else if ct := getCT(req); ct == "application/json" {
405-
if err := getJSON(req, &jsonData); err != nil {
406-
logger.Warn().Err(err).Msg("failed to decode json object in request body")
407-
jsonData = nil
406+
} else {
407+
var wrapped bool
408+
if ce := req.Header.Get("Content-Encoding"); ce == "gzip" {
409+
if r, err := gzip.NewReader(req.Body); err != nil {
410+
logger.Error().Err(err).Msg("failed to initialize gzip reader")
411+
return nil, fmt.Errorf("failed to initialize gzip reader: %v", err)
412+
} else {
413+
wrapped = true
414+
req.Body = r
415+
}
416+
} else if ce == "deflate" {
417+
wrapped = true
418+
req.Body = flate.NewReader(req.Body)
408419
}
409-
} else if ct == "application/x-www-form-urlencoded" {
410-
if err := req.ParseForm(); err != nil {
411-
logger.Warn().Err(err).Msg("failed to parse form data in request body")
412-
} else {
413-
formData = req.PostForm
420+
if ct := getCT(req); ct == "application/json" {
421+
if err := getJSON(req, &jsonData); err != nil {
422+
logger.Warn().Err(err).Msg("failed to decode json object in request body")
423+
jsonData = nil
424+
}
425+
} else if ct == "application/x-www-form-urlencoded" {
426+
if err := req.ParseForm(); err != nil {
427+
logger.Warn().Err(err).Msg("failed to parse form data in request body")
428+
} else {
429+
formData = req.PostForm
430+
}
431+
}
432+
if wrapped {
433+
if rc, ok := req.Body.(io.Closer); ok {
434+
if err := rc.Close(); err != nil {
435+
logger.Warn().Err(err).Msg("failed to close gzip/deflate reader")
436+
}
437+
}
414438
}
415439
}
416440

params_test.go

+89
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ package rapidrows_test
1818

1919
import (
2020
"bytes"
21+
"compress/flate"
22+
"compress/gzip"
2123
"encoding/json"
2224
"io"
2325
"net/http"
2426
"net/url"
27+
"strings"
2528
"testing"
2629
"time"
2730

@@ -1091,3 +1094,89 @@ func TestParamsInvalidPost(t *testing.T) {
10911094
r.Equal(400, resp.StatusCode)
10921095
s.Stop(time.Second * 5)
10931096
}
1097+
1098+
const cfgTestParamsCompr = `{
1099+
"version": "1",
1100+
"listen": "127.0.0.1:60000",
1101+
"endpoints": [
1102+
{
1103+
"uri": "/",
1104+
"implType": "static-text",
1105+
"params": [
1106+
{
1107+
"name": "p",
1108+
"in": "body",
1109+
"type": "string",
1110+
"pattern": "a+",
1111+
"required": true
1112+
}
1113+
],
1114+
"script": "success"
1115+
}
1116+
]
1117+
}`
1118+
1119+
func TestParamsComprGzip(t *testing.T) {
1120+
r := require.New(t)
1121+
1122+
cfg := loadCfg(r, cfgTestParamsCompr)
1123+
s := startServer(r, cfg)
1124+
time.Sleep(500 * time.Millisecond)
1125+
1126+
sbody := "p=" + strings.Repeat("a", 1000)
1127+
zbody := &bytes.Buffer{}
1128+
zw := gzip.NewWriter(zbody)
1129+
_, err := io.Copy(zw, strings.NewReader(sbody))
1130+
r.Nil(err)
1131+
r.Nil(zw.Close())
1132+
1133+
req, err := http.NewRequest("POST", "http://127.0.0.1:60000/",
1134+
bytes.NewReader(zbody.Bytes()))
1135+
r.Nil(err)
1136+
r.NotNil(req)
1137+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
1138+
req.Header.Set("Content-Encoding", "gzip")
1139+
1140+
resp, err := http.DefaultClient.Do(req)
1141+
r.Nil(err, "error was %v", err)
1142+
r.NotNil(resp)
1143+
data, err := io.ReadAll(resp.Body)
1144+
r.Nil(err)
1145+
resp.Body.Close()
1146+
r.Equal(200, resp.StatusCode)
1147+
r.Equal([]byte("success"), data)
1148+
s.Stop(time.Second * 5)
1149+
}
1150+
1151+
func TestParamsComprDeflate(t *testing.T) {
1152+
r := require.New(t)
1153+
1154+
cfg := loadCfg(r, cfgTestParamsCompr)
1155+
s := startServer(r, cfg)
1156+
time.Sleep(500 * time.Millisecond)
1157+
1158+
sbody := "p=" + strings.Repeat("a", 1000)
1159+
zbody := &bytes.Buffer{}
1160+
zw, err := flate.NewWriter(zbody, -1)
1161+
r.Nil(err)
1162+
_, err = io.Copy(zw, strings.NewReader(sbody))
1163+
r.Nil(err)
1164+
r.Nil(zw.Close())
1165+
1166+
req, err := http.NewRequest("POST", "http://127.0.0.1:60000/",
1167+
bytes.NewReader(zbody.Bytes()))
1168+
r.Nil(err)
1169+
r.NotNil(req)
1170+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
1171+
req.Header.Set("Content-Encoding", "deflate")
1172+
1173+
resp, err := http.DefaultClient.Do(req)
1174+
r.Nil(err, "error was %v", err)
1175+
r.NotNil(resp)
1176+
data, err := io.ReadAll(resp.Body)
1177+
r.Nil(err)
1178+
resp.Body.Close()
1179+
r.Equal(200, resp.StatusCode)
1180+
r.Equal([]byte("success"), data)
1181+
s.Stop(time.Second * 5)
1182+
}

validate_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ func TestValidateConfigWarn(t *testing.T) {
7171
}
7272
count := 0
7373
for _, vr := range cfg.Validate() {
74-
r.True(vr.Warn, vr.Msg)
75-
r.Greater(len(vr.Msg), 0)
76-
t.Logf("warning (expected): %s", vr.Msg)
74+
r.True(vr.Warn, vr.Message)
75+
r.Greater(len(vr.Message), 0)
76+
t.Logf("warning (expected): %s", vr.Message)
7777
count++
7878
}
7979
r.Greater(count, 0, "at least 1 warning was expected")

0 commit comments

Comments
 (0)