Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
1cedsoda committed Mar 2, 2024
1 parent b335275 commit 6ab7d21
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 30 deletions.
2 changes: 1 addition & 1 deletion demo/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ http:
middlewares:
- plain-to-html-header
- plain-to-html-body
- compress
# - compress
10 changes: 7 additions & 3 deletions encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ func GetSupportedEncodings(q float64) *Encodings {
return &Encodings{encodings: result}
}

func ParseEncoding(encoding string) (*Encoding, error) {
func ParseEncoding(encoding string, h *PluginHandler) (*Encoding, error) {
if encoding == "" {
return &Encoding{name: Identity, q: 1.0}, nil
}

matches := encodingRegexp.FindStringSubmatch(encoding)

if len(matches) < 2 {
Expand Down Expand Up @@ -61,7 +65,7 @@ type Encodings struct {
encodings []Encoding
}

func ParseEncodings(acceptEncoding string) *Encodings {
func ParseEncodings(acceptEncoding string, h *PluginHandler) *Encodings {
// remove any spaces
acceptEncoding = strings.ReplaceAll(acceptEncoding, " ", "")

Expand All @@ -75,7 +79,7 @@ func ParseEncodings(acceptEncoding string) *Encodings {
continue
}

encoding, err := ParseEncoding(encodingString)
encoding, err := ParseEncoding(encodingString, h)
if err != nil {
continue
}
Expand Down
67 changes: 67 additions & 0 deletions encodings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,70 @@ func AssertEncodingsEquals(a, b *Encodings, t *testing.T) {
AssertEncodingEquals(&a.encodings[i], &b.encodings[i], t)
}
}

func TestParseEncoding(t *testing.T) {
testCases := []struct {
encoding string
expected *Encoding
err error
}{
{
encoding: "gzip;q=1.0",
expected: &Encoding{name: "gzip", q: 1.0},
err: nil,
},
{
encoding: "deflate;q=0.5",
expected: &Encoding{name: "deflate", q: 0.5},
err: nil,
},
{
encoding: "br;q=0.8",
expected: &Encoding{name: "br", q: 0.8},
err: nil,
},
{
encoding: "identity",
expected: &Encoding{name: "identity", q: 1.0},
err: nil,
},
{
encoding: "gzip;q=0.0",
expected: &Encoding{name: "gzip", q: 0.0},
err: nil,
},
{
encoding: "invalid",
expected: &Encoding{name: "identity", q: 1.0},
err: nil,
},
{
encoding: "",
expected: &Encoding{name: "identity", q: 1.0},
err: nil,
},
}

for _, tc := range testCases {
result, err := ParseEncoding(tc.encoding)

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.19, ubuntu-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.19, ubuntu-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.x, ubuntu-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.x, macos-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.19, macos-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.x, ubuntu-latest)

not enough arguments in call to ParseEncoding

Check failure on line 92 in encodings_test.go

View workflow job for this annotation

GitHub Actions / Go (1.x, macos-latest)

not enough arguments in call to ParseEncoding

if err != nil {
if tc.err == nil {
t.Errorf("unexpected error: %v", err)
} else if err.Error() != tc.err.Error() {
t.Errorf("error mismatch: expected %v, got %v", tc.err, err)
}
} else if tc.err != nil {
t.Errorf("expected error: %v, got nil", tc.err)
}

if result != nil && tc.expected != nil {
if result.name != tc.expected.name {
t.Errorf("name mismatch: expected %v, got %v", tc.expected.name, result.name)
}
if result.q != tc.expected.q {
t.Errorf("q mismatch: expected %v, got %v", tc.expected.q, result.q)
}
}
}
}
36 changes: 20 additions & 16 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,38 +143,42 @@ func (h *PluginHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// script injection
var injected bool = false

Check failure on line 144 in plugin.go

View workflow job for this annotation

GitHub Actions / Go (1.x, ubuntu-latest)

injected declared and not used

Check failure on line 144 in plugin.go

View workflow job for this annotation

GitHub Actions / Go (1.x, macos-latest)

injected declared and not used

Check failure on line 144 in plugin.go

View workflow job for this annotation

GitHub Actions / Go (1.x, ubuntu-latest)

injected declared and not used

Check failure on line 144 in plugin.go

View workflow job for this annotation

GitHub Actions / Go (1.x, macos-latest)

injected declared and not used
myReq := &Request{Request: *req}
myRw := NewResponseWriter(rw)
if h.config.ScriptInjection && myReq.CouldBeInjectable() {
// intercept body
myRw := NewResponseWriter(rw)
encoding := myReq.GetSupportedEncodings().GetPreferred()
myReq.SetSupportedEncoding()
encoding := myReq.GetSupportedEncodings(h).GetPreferred()
myReq.SetSupportedEncoding(h)
h.next.ServeHTTP(myRw, &myReq.Request)

// check if response is injectable
if myRw.IsInjectable() {
// h.log(fmt.Sprintf("Inject %s", req.URL.EscapedPath()))
body, err := myRw.ReadDecoded()
body, err := myRw.ReadDecoded(h)
if err != nil {
h.log(fmt.Sprintf("Error: %s", err))
}
newBody := InsertAtBodyEnd(body, h.scriptHtml)
h.log(fmt.Sprintf("newBody: %s", newBody))
h.log(fmt.Sprintf("encoding: %+v", encoding))
myRw.WriteEncoded(newBody, encoding)
rw.Write(myRw.Read())

injected = true
h.next.ServeHTTP(rw, req)
return
}
}

// server side tracking
shouldServerSideTrack := shouldServerSideTrack(req, &h.config, injected, h)
if shouldServerSideTrack {
// h.log(fmt.Sprintf("Track %s", req.URL.EscapedPath()))
go buildAndSendTrackingRequest(req, &h.config)
}

if !injected {
// h.log(fmt.Sprintf("Continue %s", req.URL.EscapedPath()))
h.next.ServeHTTP(rw, req)
}
// // server side tracking
// shouldServerSideTrack := shouldServerSideTrack(req, &h.config, injected, h)
// if shouldServerSideTrack {
// // h.log(fmt.Sprintf("Track %s", req.URL.EscapedPath()))
// go buildAndSendTrackingRequest(req, &h.config)
// }

// if !injected {
// // h.log(fmt.Sprintf("Continue %s", req.URL.EscapedPath()))
// h.next.ServeHTTP(rw, req)
// }
}

type responseWriter struct {
Expand Down
8 changes: 4 additions & 4 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ type Request struct {
http.Request
}

func (req *Request) SetSupportedEncoding() {
supported := req.GetSupportedEncodings()
func (req *Request) SetSupportedEncoding(h *PluginHandler) {
supported := req.GetSupportedEncodings(h)
req.Header.Set("Accept-Encoding", supported.String())
}

func (req *Request) GetSupportedEncodings() *Encodings {
func (req *Request) GetSupportedEncodings(h *PluginHandler) *Encodings {
acceptEncoding := req.Header.Get("Accept-Encoding")
return ParseEncodings(acceptEncoding).FilterSupported()
return ParseEncodings(acceptEncoding, h).FilterSupported()
}

func (req *Request) CouldBeInjectable() bool {
Expand Down
12 changes: 6 additions & 6 deletions response_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ func (w *ResponseWriter) Read() []byte {
// Body bytes
// Always uncompressed
// Error if encoding is not supported.
func (w *ResponseWriter) ReadDecoded() ([]byte, error) {
encoding, err := w.GetContentEncoding()
func (w *ResponseWriter) ReadDecoded(h *PluginHandler) ([]byte, error) {
encoding, err := w.GetContentEncoding(h)
if err != nil {
return nil, err
}
Expand All @@ -53,21 +53,21 @@ func (w *ResponseWriter) WriteEncoded(plain []byte, encoding *Encoding) (int, er
if err != nil {
return 0, err
}
w.Write(encoded)
w.SetContentEncoding(encoding)
w.SetContentLength(size)
w.Write(encoded)
return len(plain), nil
}

// Content-Encoding header.
func (w *ResponseWriter) GetContentEncoding() (*Encoding, error) {
func (w *ResponseWriter) GetContentEncoding(h *PluginHandler) (*Encoding, error) {
str := w.Header().Get("Content-Encoding")
return ParseEncoding(str)
return ParseEncoding(str, h)
}

// Set Content-Encoding header.
func (w *ResponseWriter) SetContentEncoding(encoding *Encoding) {
w.Header().Set("Content-Encoding", encoding.name)
// w.Header().Set("Content-Encoding", encoding.name)
}

// set content size.
Expand Down

0 comments on commit 6ab7d21

Please sign in to comment.