-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(compressor): added gzip/deflate compression support on request (#12
- Loading branch information
Showing
14 changed files
with
460 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
version = 1 | ||
|
||
[[analyzers]] | ||
name = "go" | ||
|
||
[analyzers.meta] | ||
import_root = "github.com/yaitoo/xun" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
### Changes | ||
- | ||
|
||
### Fixes | ||
- | ||
|
||
### Tests | ||
Tasks to complete before merging PR: | ||
- [ ] Ensure unit tests are passing. If not run `make unit-test` to check for any regressions :clipboard: | ||
- [ ] Ensure lint tests are passing. if not run `make lint` to check for any issues | ||
- [ ] Ensure codecov/patch is passing for changes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package xun | ||
|
||
import "net/http" | ||
|
||
// Compressor is an interface that defines methods for handling HTTP response compression. | ||
// Implementations of this interface should provide the specific encoding type they support | ||
// and a method to create a new ResponseWriter that applies the compression. | ||
// | ||
// AcceptEncoding returns the encoding type that the compressor supports. | ||
// | ||
// New takes an http.ResponseWriter and returns a ResponseWriter that applies the compression. | ||
type Compressor interface { | ||
AcceptEncoding() string | ||
New(rw http.ResponseWriter) ResponseWriter | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package xun | ||
|
||
import ( | ||
"compress/flate" | ||
"net/http" | ||
) | ||
|
||
// DeflateCompressor is a struct that provides functionality for compressing data using the DEFLATE algorithm. | ||
type DeflateCompressor struct { | ||
} | ||
|
||
// AcceptEncoding returns the encoding type that the DeflateCompressor supports. | ||
// In this case, it returns the string "deflate". | ||
func (c *DeflateCompressor) AcceptEncoding() string { | ||
return "deflate" | ||
} | ||
|
||
// New creates a new deflateResponseWriter that wraps the provided http.ResponseWriter. | ||
// It sets the "Content-Encoding" header to "deflate" and initializes a flate.Writer | ||
// with the default compression level. | ||
func (c *DeflateCompressor) New(rw http.ResponseWriter) ResponseWriter { | ||
rw.Header().Set("Content-Encoding", "deflate") | ||
w, _ := flate.NewWriter(rw, flate.DefaultCompression) //nolint: errcheck because flate.DefaultCompression is a valid compression level | ||
|
||
return &deflateResponseWriter{ | ||
w: w, | ||
ResponseWriter: rw, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package xun | ||
|
||
import ( | ||
"compress/flate" | ||
"io" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
"testing/fstest" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestDeflateCompressor(t *testing.T) { | ||
fsys := fstest.MapFS{ | ||
"public/skin.css": { | ||
Data: []byte("body { color: red; }"), | ||
}, | ||
"pages/index.html": { | ||
Data: []byte("<html><head><title>index</title></head><body></body></html>"), | ||
}, | ||
} | ||
|
||
m := http.NewServeMux() | ||
srv := httptest.NewServer(m) | ||
defer srv.Close() | ||
|
||
app := New(WithMux(m), WithFsys(fsys), WithCompressor(&DeflateCompressor{})) | ||
defer app.Close() | ||
|
||
app.Get("/json", func(c *Context) error { | ||
return c.View(map[string]string{"message": "hello"}) | ||
}) | ||
|
||
go app.Start() | ||
|
||
var tests = []struct { | ||
name string | ||
acceptEncoding string | ||
contentEncoding string | ||
createReader func(r io.Reader) io.Reader | ||
}{ | ||
{ | ||
name: "deflate", | ||
acceptEncoding: "deflate", | ||
contentEncoding: "deflate", | ||
createReader: func(r io.Reader) io.Reader { | ||
return flate.NewReader(r) | ||
}, | ||
}, | ||
{ | ||
name: "any", | ||
acceptEncoding: "*", | ||
contentEncoding: "deflate", | ||
createReader: func(r io.Reader) io.Reader { | ||
return flate.NewReader(r) | ||
}, | ||
}, | ||
{ | ||
name: "plain", | ||
acceptEncoding: "", | ||
contentEncoding: "", | ||
createReader: func(r io.Reader) io.Reader { | ||
return r | ||
}, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
req, err := http.NewRequest(http.MethodGet, srv.URL+"/skin.css", nil) | ||
require.NoError(t, err) | ||
req.Header.Set("Accept-Encoding", test.acceptEncoding) | ||
|
||
resp, err := client.Do(req) | ||
require.NoError(t, err) | ||
require.Equal(t, test.contentEncoding, resp.Header.Get("Content-Encoding")) | ||
|
||
buf, err := io.ReadAll(test.createReader(resp.Body)) | ||
require.NoError(t, err) | ||
require.Equal(t, fsys["public/skin.css"].Data, buf) | ||
|
||
req, err = http.NewRequest(http.MethodGet, srv.URL+"/", nil) | ||
require.NoError(t, err) | ||
req.Header.Set("Accept-Encoding", test.acceptEncoding) | ||
|
||
resp, err = client.Do(req) | ||
require.NoError(t, err) | ||
require.Equal(t, test.contentEncoding, resp.Header.Get("Content-Encoding")) | ||
|
||
buf, err = io.ReadAll(test.createReader(resp.Body)) | ||
require.NoError(t, err) | ||
require.Equal(t, fsys["pages/index.html"].Data, buf) | ||
|
||
req, err = http.NewRequest(http.MethodGet, srv.URL+"/json", nil) | ||
require.NoError(t, err) | ||
req.Header.Set("Accept-Encoding", test.acceptEncoding) | ||
|
||
resp, err = client.Do(req) | ||
require.NoError(t, err) | ||
require.Equal(t, test.contentEncoding, resp.Header.Get("Content-Encoding")) | ||
|
||
data := make(map[string]string) | ||
err = json.NewDecoder(test.createReader(resp.Body)).Decode(&data) | ||
require.NoError(t, err) | ||
require.Equal(t, "hello", data["message"]) | ||
}) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package xun | ||
|
||
import ( | ||
"compress/gzip" | ||
"net/http" | ||
) | ||
|
||
// GzipCompressor is a struct that provides methods for compressing and decompressing data using the Gzip algorithm. | ||
type GzipCompressor struct { | ||
} | ||
|
||
// AcceptEncoding returns the encoding type that the GzipCompressor supports. | ||
// In this case, it returns "gzip". | ||
func (c *GzipCompressor) AcceptEncoding() string { | ||
return "gzip" | ||
} | ||
|
||
// New creates a new gzipResponseWriter that wraps the provided http.ResponseWriter. | ||
// It sets the "Content-Encoding" header to "gzip" and returns the wrapped writer. | ||
func (c *GzipCompressor) New(rw http.ResponseWriter) ResponseWriter { | ||
rw.Header().Set("Content-Encoding", "gzip") | ||
|
||
return &gzipResponseWriter{ | ||
w: gzip.NewWriter(rw), | ||
ResponseWriter: rw, | ||
} | ||
|
||
} |
Oops, something went wrong.