Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit 0cf97e5

Browse files
authored
Merge pull request #12 from JSainsburyPLC/fix/localhost-links
Change links to point to localhost on local dev
2 parents 7359c15 + e1980b4 commit 0cf97e5

File tree

3 files changed

+115
-8
lines changed

3 files changed

+115
-8
lines changed

domain/config.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ type Config struct {
1717
}
1818

1919
type Route struct {
20-
Type string `json:"type"`
21-
PathPattern *PathPattern `json:"path_pattern"`
22-
Backend *Backend `json:"backend"`
23-
Mock *Mock `json:"mock"`
24-
Rewrite []Rewrite `json:"rewrite"`
25-
Redirect *Redirect `json:"redirect"`
26-
ProxyPassHeaders map[string]string `json:"proxy_pass_headers"`
27-
ProxyResponseHeaders map[string]string `json:"proxy_response_headers"`
20+
Type string `json:"type"`
21+
PathPattern *PathPattern `json:"path_pattern"`
22+
Backend *Backend `json:"backend"`
23+
Mock *Mock `json:"mock"`
24+
Rewrite []Rewrite `json:"rewrite"`
25+
Redirect *Redirect `json:"redirect"`
26+
ProxyPassHeaders map[string]string `json:"proxy_pass_headers"`
27+
ProxyResponseHeaders map[string]string `json:"proxy_response_headers"`
28+
ProxyResponseReplacements map[string]string `json:"proxy_response_replacements"`
2829
}
2930

3031
type Rewrite struct {

proxy/proxy.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package proxy
22

33
import (
4+
"bytes"
5+
"compress/gzip"
46
"context"
57
"encoding/json"
68
"errors"
79
"fmt"
10+
"io"
11+
"io/ioutil"
812
"log"
913
"net/http"
1014
"net/http/httputil"
1115
"net/url"
1216
"path"
17+
"strings"
1318
"time"
1419

1520
"github.com/JSainsburyPLC/ui-dev-proxy/domain"
@@ -93,6 +98,44 @@ func director(defaultBackend *url.URL, logger *log.Logger) func(req *http.Reques
9398
}
9499
}
95100

101+
func gUnzipData(data []byte) ([]byte, error) {
102+
b := bytes.NewBuffer(data)
103+
104+
var r io.Reader
105+
r, err := gzip.NewReader(b)
106+
if err != nil {
107+
return nil, err
108+
}
109+
110+
var resB bytes.Buffer
111+
_, err = resB.ReadFrom(r)
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
return resB.Bytes(), nil
117+
}
118+
119+
func gZipData(data []byte) ([]byte, error) {
120+
var b bytes.Buffer
121+
gz := gzip.NewWriter(&b)
122+
123+
_, err := gz.Write(data)
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
if err = gz.Flush(); err != nil {
129+
return nil, err
130+
}
131+
132+
if err = gz.Close(); err != nil {
133+
return nil, err
134+
}
135+
136+
return b.Bytes(), nil
137+
}
138+
96139
func modifyResponse() func(*http.Response) error {
97140
return func(res *http.Response) error {
98141
route, ok := res.Request.Context().Value(routeCtxKey).(*domain.Route)
@@ -105,6 +148,48 @@ func modifyResponse() func(*http.Response) error {
105148
res.Header.Set(k, v)
106149
}
107150

151+
if len(route.ProxyResponseReplacements) != 0 {
152+
153+
bodyBytes, err := ioutil.ReadAll(res.Body)
154+
if err != nil {
155+
return err
156+
}
157+
158+
isGZipped := http.DetectContentType(bodyBytes) == "application/x-gzip"
159+
160+
if isGZipped {
161+
bodyBytes, err = gUnzipData(bodyBytes)
162+
if err != nil {
163+
return err
164+
}
165+
}
166+
167+
bodyString := string(bodyBytes)
168+
169+
for k, v := range route.ProxyResponseReplacements {
170+
bodyString = strings.ReplaceAll(bodyString, k, v)
171+
172+
for headerKey, headerValues := range res.Header {
173+
res.Header.Del(headerKey)
174+
for _, headerValue := range headerValues {
175+
res.Header.Add(headerKey, strings.ReplaceAll(headerValue, k, v))
176+
}
177+
}
178+
}
179+
180+
bodyBytes = []byte(bodyString)
181+
182+
if isGZipped {
183+
bodyBytes, err = gZipData(bodyBytes)
184+
if err != nil {
185+
return err
186+
}
187+
}
188+
189+
res.Header.Set("content-length", fmt.Sprintf("%d", len(bodyBytes)))
190+
res.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
191+
}
192+
108193
return nil
109194
}
110195
}

proxy/proxy_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ func TestProxy_ProxyBackend_UserProxy_Success(t *testing.T) {
6363
End()
6464
}
6565

66+
func TestProxy_ProxyBackend_ResponseReplacements(t *testing.T) {
67+
backendMock := apitest.NewMock().Get("http://localhost:3001/test-ui/users/info").
68+
RespondWith().
69+
Status(http.StatusOK).
70+
Header("test-header", "test-value-1").
71+
Body(`{"product_id": "test-value-1"}`).
72+
End()
73+
74+
newApiTest(config(), "http://test-backend", false).
75+
Mocks(backendMock).
76+
Get("/test-ui/users/info").
77+
Expect(t).
78+
Status(http.StatusOK).
79+
Header("test-header", "test-value-2").
80+
Body(`{"product_id": "test-value-2"}`).
81+
End()
82+
}
83+
6684
func TestProxy_Rewrite(t *testing.T) {
6785
tests := map[string]struct {
6886
pattern string
@@ -335,6 +353,9 @@ func config() domain.Config {
335353
ProxyResponseHeaders: map[string]string{
336354
"Cache-Control": "no-cache",
337355
},
356+
ProxyResponseReplacements: map[string]string{
357+
"test-value-1": "test-value-2",
358+
},
338359
},
339360
{
340361
Type: "proxy",

0 commit comments

Comments
 (0)