Skip to content

Commit 6e944d6

Browse files
committed
Merge pull request juju#80 from mhilton/000-httptesting-transport
Add Transport to httptesting Add a request rewriting RoundTripper to httptesting. (Review request: http://reviews.vapour.ws/r/2825/)
2 parents c037f3a + 3564d7f commit 6e944d6

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

httptesting/http.go

+37
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,40 @@ type readSeekNopCloser struct {
321321
func (readSeekNopCloser) Close() error {
322322
return nil
323323
}
324+
325+
// URLRewritingTransport is an http.RoundTripper that can rewrite request
326+
// URLs. If the request URL has the prefix specified in Match that part
327+
// will be changed to the value specified in Replace. RoundTripper will
328+
// then be used to perform the resulting request. If RoundTripper is nil
329+
// http.DefaultTransport will be used.
330+
//
331+
// This can be used in tests that, for whatever reason, need to make a
332+
// call to a URL that's not in our control but we want to control the
333+
// results of HTTP requests to that URL.
334+
type URLRewritingTransport struct {
335+
MatchPrefix string
336+
Replace string
337+
RoundTripper http.RoundTripper
338+
}
339+
340+
// RoundTrip implements http.RoundTripper.
341+
func (t URLRewritingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
342+
rt := t.RoundTripper
343+
if rt == nil {
344+
rt = http.DefaultTransport
345+
}
346+
if !strings.HasPrefix(req.URL.String(), t.MatchPrefix) {
347+
return rt.RoundTrip(req)
348+
}
349+
req1 := *req
350+
var err error
351+
req1.URL, err = url.Parse(t.Replace + strings.TrimPrefix(req.URL.String(), t.MatchPrefix))
352+
if err != nil {
353+
panic(err)
354+
}
355+
resp, err := rt.RoundTrip(&req1)
356+
if resp != nil {
357+
resp.Request = req
358+
}
359+
return resp, err
360+
}

httptesting/http_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,41 @@ func (*requestsSuite) TestDoRequestWithInferrableContentLength(c *gc.C) {
319319
// calls. Failures are already massively tested in practice. DoRequest and
320320
// AssertJSONResponse are also indirectly tested as they are called by
321321
// AssertJSONCall.
322+
323+
type urlRewritingTransportSuite struct {
324+
server *httptest.Server
325+
}
326+
327+
var _ = gc.Suite(&urlRewritingTransportSuite{})
328+
329+
func (s *urlRewritingTransportSuite) SetUpTest(c *gc.C) {
330+
s.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
331+
w.Write([]byte(r.URL.String()))
332+
}))
333+
}
334+
335+
func (s *urlRewritingTransportSuite) TestTransport(c *gc.C) {
336+
t := httptesting.URLRewritingTransport{
337+
MatchPrefix: "http://example.com",
338+
Replace: s.server.URL,
339+
}
340+
client := http.Client{
341+
Transport: &t,
342+
}
343+
resp, err := client.Get("http://example.com/path")
344+
c.Assert(err, jc.ErrorIsNil)
345+
body, err := ioutil.ReadAll(resp.Body)
346+
c.Assert(err, jc.ErrorIsNil)
347+
resp.Body.Close()
348+
c.Assert(resp.Request.URL.String(), gc.Equals, "http://example.com/path")
349+
c.Assert(string(body), gc.Equals, "/path")
350+
351+
t.RoundTripper = &http.Transport{}
352+
resp, err = client.Get(s.server.URL + "/otherpath")
353+
c.Assert(err, jc.ErrorIsNil)
354+
body, err = ioutil.ReadAll(resp.Body)
355+
c.Assert(err, jc.ErrorIsNil)
356+
resp.Body.Close()
357+
c.Assert(resp.Request.URL.String(), gc.Equals, s.server.URL+"/otherpath")
358+
c.Assert(string(body), gc.Equals, "/otherpath")
359+
}

0 commit comments

Comments
 (0)