Skip to content

Commit a5b947b

Browse files
committed
work: Handle 301 redirects from user agent
1 parent 62696c0 commit a5b947b

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

html/window.go

+26-5
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ func newWindow(windowOptions ...WindowOption) *window {
108108
return win
109109
}
110110

111+
func (w *window) checkRedirect(req *http.Request, via []*http.Request) error {
112+
if len(via) > 9 {
113+
return errors.New("Too many redirects")
114+
}
115+
w.history.ReplaceState(EMPTY_STATE, req.URL.String())
116+
return nil
117+
}
118+
111119
func NewWindow(windowOptions ...WindowOption) Window {
112120
return newWindow(windowOptions...)
113121
}
@@ -209,8 +217,13 @@ func (w *window) Document() dom.Document {
209217
return w.document
210218
}
211219

212-
func (w *window) Navigate(href string) error {
220+
func (w *window) Navigate(href string) (err error) {
213221
log.Info(w.Logger(), "Window.navigate:", "href", href)
222+
defer func() {
223+
if err != nil {
224+
log.Warn(w.logger, "Window.navigate: Error response", "err", err.Error())
225+
}
226+
}()
214227
w.History().pushLoad(href)
215228
w.initScriptEngine()
216229
w.baseLocation = href
@@ -236,15 +249,23 @@ func (w *window) reload(href string) error {
236249
}
237250
}
238251

239-
func (w *window) get(href string) (err error) {
252+
func (w *window) get(href string) error {
240253
if req, err := http.NewRequest("GET", href, nil); err == nil {
241-
err = w.fetchRequest(req)
254+
return w.fetchRequest(req)
255+
} else {
256+
return err
242257
}
243-
return err
244258
}
245259

260+
// fetchRequest handles "User agent" requests. I.e., navigation by clicking a
261+
// link, submitting a form, of calling a JS API that makes the browser itself
262+
// navigate to a new URL.
246263
func (w *window) fetchRequest(req *http.Request) error {
247-
resp, err := w.httpClient.Do(req)
264+
// Create a copy of the client, and set the CheckRedirect to a function that
265+
// updates the window location to reflect the new URL.
266+
client := w.httpClient
267+
client.CheckRedirect = w.checkRedirect
268+
resp, err := client.Do(req)
248269
if err != nil {
249270
return err
250271
}

html/window_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package html_test
22

33
import (
4+
"fmt"
5+
"io"
6+
"net/http"
47
"strings"
58
"testing"
69

@@ -10,6 +13,7 @@ import (
1013
. "github.com/gost-dom/browser/html"
1114
. "github.com/gost-dom/browser/internal/testing/gomega-matchers"
1215
"github.com/gost-dom/browser/internal/testing/gosttest"
16+
"github.com/gost-dom/browser/internal/testing/htmltest"
1317
. "github.com/gost-dom/browser/testing/gomega-matchers"
1418
)
1519

@@ -32,3 +36,52 @@ func (s *WindowTestSuite) TestDocumentWithDOCTYPE() {
3236
func TestWindow(t *testing.T) {
3337
suite.Run(t, new(WindowTestSuite))
3438
}
39+
40+
type WindowNavigationTestSuite struct {
41+
gosttest.GomegaSuite
42+
win htmltest.WindowHelper
43+
}
44+
45+
func (s *WindowNavigationTestSuite) SetupTest() {
46+
m := http.NewServeMux()
47+
m.HandleFunc("GET /page-1", func(w http.ResponseWriter, r *http.Request) {
48+
w.Write([]byte(`<body>
49+
<a id="link" href="/old-page-2">Link</a>
50+
<form method="post" action="/old-page-2" id="form">
51+
<input name="data" value="value" type="text" />
52+
<button type="submit" id="submit">Submit</button>
53+
</form>
54+
</body>`))
55+
})
56+
m.HandleFunc("/old-page-2", func(w http.ResponseWriter, r *http.Request) {
57+
u := r.URL
58+
u.Path = "/new-page-2"
59+
w.Header().Add("Location", u.String())
60+
w.WriteHeader(301)
61+
})
62+
m.HandleFunc("/new-page-2", func(w http.ResponseWriter, r *http.Request) {
63+
body, err := io.ReadAll(r.Body)
64+
if err != nil {
65+
w.WriteHeader(500)
66+
}
67+
respBody := fmt.Sprintf(
68+
`<body><h1>Page 2</h1>
69+
<div id="method">%s</div>
70+
<div id="request-body">%s</div>
71+
</body>`, r.Method, string(body),
72+
)
73+
w.Write([]byte(respBody))
74+
})
75+
s.win = htmltest.NewWindowHelper(s.T(), NewWindowFromHandler(m))
76+
s.win.Navigate("https://example.com/page-1")
77+
}
78+
79+
func TestWindowNavigation(t *testing.T) {
80+
suite.Run(t, new(WindowNavigationTestSuite))
81+
}
82+
83+
func (s *WindowNavigationTestSuite) TestRedirectGetRequests() {
84+
s.Assert().Equal("/page-1", s.win.Location().Pathname())
85+
s.win.HTMLDocument().GetHTMLElementById("link").Click()
86+
s.Assert().Equal("https://example.com/new-page-2", s.win.Location().Href())
87+
}

internal/gosthttp/test_round_tripper.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ func (h TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
2424
serverReq.Body = nullReader{}
2525
}
2626
h.ServeHTTP(rec, serverReq)
27-
return rec.Result(), nil
27+
resp := rec.Result()
28+
resp.Request = req
29+
return resp, nil
2830
}
2931

3032
// nullReader is just a reader with no content. When _sending_ an HTTP request,

0 commit comments

Comments
 (0)