func (s *ClientSuite) TestDoWithBodyAndCustomError(c *gc.C) { d := bakerytest.NewDischarger(nil, noCaveatChecker) defer d.Close() // Create a target service. svc := newService("loc", d) type customError struct { CustomError *httpbakery.Error } callCount := 0 handler := func(w http.ResponseWriter, req *http.Request) { callCount++ if _, checkErr := httpbakery.CheckRequest(svc, req, nil, checkers.New()); checkErr != nil { httprequest.WriteJSON(w, http.StatusTeapot, customError{ CustomError: newDischargeRequiredError(svc, d.Location(), nil, checkErr, req).(*httpbakery.Error), }) return } fmt.Fprintf(w, "hello there") } srv := httptest.NewServer(http.HandlerFunc(handler)) defer srv.Close() req, err := http.NewRequest("GET", srv.URL, nil) c.Assert(err, gc.IsNil) // First check that a normal request fails. resp, err := httpbakery.NewClient().Do(req) c.Assert(err, gc.IsNil) defer resp.Body.Close() c.Assert(resp.StatusCode, gc.Equals, http.StatusTeapot) c.Assert(callCount, gc.Equals, 1) callCount = 0 // Then check that a request with a custom error getter succeeds. errorGetter := func(resp *http.Response) error { if resp.StatusCode != http.StatusTeapot { return nil } data, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } var respErr customError if err := json.Unmarshal(data, &respErr); err != nil { panic(err) } return respErr.CustomError } resp, err = httpbakery.NewClient().DoWithBodyAndCustomError(req, nil, errorGetter) c.Assert(err, gc.IsNil) data, err := ioutil.ReadAll(resp.Body) c.Assert(err, gc.IsNil) c.Assert(string(data), gc.Equals, "hello there") c.Assert(callCount, gc.Equals, 2) }
func (s *registrationSuite) TestMeteredCharmDeployError(c *gc.C) { client := httpbakery.NewClient().Client d := DeploymentInfo{ CharmURL: charm.MustParseURL("cs:quantal/metered-1"), ServiceName: "service name", ModelUUID: "environment uuid", } err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d) c.Assert(err, jc.ErrorIsNil) deployError := errors.New("deployment failed") err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d, deployError) c.Assert(err, jc.ErrorIsNil) authorization, err := json.Marshal([]byte("hello registration")) authorization = append(authorization, byte(0xa)) c.Assert(err, jc.ErrorIsNil) s.stub.CheckCalls(c, []testing.StubCall{{ "APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}}, }, { "Authorize", []interface{}{metricRegistrationPost{ ModelUUID: "environment uuid", CharmURL: "cs:quantal/metered-1", ServiceName: "service name", PlanURL: "someplan", }}, }}) }
func (s *suite) TestInteractiveDischargerURL(c *gc.C) { var d *bakerytest.InteractiveDischarger d = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, d.URL("/redirect", r), http.StatusFound) }, )) defer d.Close() d.Mux.Handle("/redirect", http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { d.FinishInteraction(w, r, nil, nil) }, )) svc, err := bakery.NewService(bakery.NewServiceParams{ Location: "here", Locator: d, }) c.Assert(err, gc.IsNil) m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{ Location: d.Location(), Condition: "something", }}) c.Assert(err, gc.IsNil) client := httpbakery.NewClient() client.VisitWebPage = func(u *url.URL) error { var c httprequest.Client return c.Get(u.String(), nil) } ms, err := client.DischargeAll(m) c.Assert(err, gc.IsNil) c.Assert(ms, gc.HasLen, 2) err = svc.Check(ms, failChecker) c.Assert(err, gc.IsNil) }
func (s *suite) TestLoginDischargerError(c *gc.C) { var d *bakerytest.InteractiveDischarger d = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { d.FinishInteraction(w, r, nil, errors.New("test error")) }, )) defer d.Close() svc, err := bakery.NewService(bakery.NewServiceParams{ Location: "here", Locator: d, }) c.Assert(err, gc.IsNil) m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{ Location: d.Location(), Condition: "something", }}) c.Assert(err, gc.IsNil) client := httpbakery.NewClient() client.VisitWebPage = func(u *url.URL) error { c.Logf("visiting %s", u) var c httprequest.Client return c.Get(u.String(), nil) } _, err = client.DischargeAll(m) c.Assert(err, gc.ErrorMatches, `cannot get discharge from ".*": failed to acquire macaroon after waiting: third party refused discharge: test error`) }
func (s *registrationSuite) TestMeteredCharmNoDefaultPlan(c *gc.C) { s.stub.SetErrors(nil, errors.NotFoundf("default plan")) s.register = &RegisterMeteredCharm{ AllocationSpec: "personal:100", RegisterURL: s.server.URL, QueryURL: s.server.URL} client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("cs:quantal/metered-1"), }, ApplicationName: "application name", ModelUUID: "model uuid", CharmInfo: &apicharms.CharmInfo{ Metrics: &charm.Metrics{ Plan: &charm.Plan{Required: true}, }, }, } err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d) c.Assert(err, gc.ErrorMatches, `cs:quantal/metered-1 has no default plan. Try "juju deploy --plan <plan-name> with one of thisplan, thisotherplan"`) s.stub.CheckCalls(c, []testing.StubCall{{ "IsMetered", []interface{}{"cs:quantal/metered-1"}, }, { "DefaultPlan", []interface{}{"cs:quantal/metered-1"}, }, { "ListPlans", []interface{}{"cs:quantal/metered-1"}, }}) }
func (s *agentSuite) TestAgentLogin(c *gc.C) { u, err := url.Parse(s.discharger.URL) c.Assert(err, gc.IsNil) for i, test := range agentLoginTests { c.Logf("%d. %s", i, test.about) s.discharger.LoginHandler = test.loginHandler client := httpbakery.NewClient() client.Key, err = bakery.GenerateKey() c.Assert(err, gc.IsNil) err = agent.SetUpAuth(client, u, "test-user") c.Assert(err, gc.IsNil) m, err := s.bakery.NewMacaroon("", nil, []checkers.Caveat{{ Location: s.discharger.URL, Condition: "test condition", }}) c.Assert(err, gc.IsNil) ms, err := client.DischargeAll(m) if test.expectError != "" { c.Assert(err, gc.ErrorMatches, test.expectError) continue } c.Assert(err, gc.IsNil) err = s.bakery.Check(ms, bakery.FirstPartyCheckerFunc( func(caveat string) error { return nil }, )) c.Assert(err, gc.IsNil) } }
func (s *registrationSuite) TestMeteredCharmNoPlanSet(c *gc.C) { s.register = &RegisterMeteredCharm{RegisterURL: s.server.URL, QueryURL: s.server.URL} client := httpbakery.NewClient().Client d := DeploymentInfo{ CharmURL: charm.MustParseURL("local:quantal/metered-1"), ServiceName: "service name", EnvUUID: "environment uuid", } err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, d) c.Assert(err, jc.ErrorIsNil) err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, d) c.Assert(err, jc.ErrorIsNil) authorization, err := json.Marshal([]byte("hello registration")) authorization = append(authorization, byte(0xa)) c.Assert(err, jc.ErrorIsNil) s.stub.CheckCalls(c, []testing.StubCall{{ "APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "local:quantal/metered-1"}}, }, { "DefaultPlan", []interface{}{"local:quantal/metered-1"}, }, { "Authorize", []interface{}{metricRegistrationPost{ EnvironmentUUID: "environment uuid", CharmURL: "local:quantal/metered-1", ServiceName: "service name", PlanURL: "thisplan", }}, }, { "APICall", []interface{}{"Service", "SetMetricCredentials", params.ServiceMetricCredentials{ Creds: []params.ServiceMetricCredential{params.ServiceMetricCredential{ ServiceName: "service name", MetricCredentials: authorization, }}, }}, }}) }
func (s *registrationSuite) TestMeteredCharmAPIError(c *gc.C) { s.stub.SetErrors(nil, errors.New("something failed")) client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("cs:quantal/metered-1"), }, ServiceName: "service name", ModelUUID: "model uuid", } err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d) c.Assert(err, gc.ErrorMatches, `authorization failed: something failed`) s.stub.CheckCalls(c, []testing.StubCall{{ "APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}}, }, { "Authorize", []interface{}{metricRegistrationPost{ ModelUUID: "model uuid", CharmURL: "cs:quantal/metered-1", ServiceName: "service name", PlanURL: "someplan", Budget: "personal", Limit: "100", }}, }}) }
func (*VisitorSuite) TestMultiVisitorSequence(c *gc.C) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, `{"method": "http://somewhere/something"}`) })) defer srv.Close() firstCalled, secondCalled := 0, 0 v := httpbakery.NewMultiVisitor( visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error { c.Check(m["method"], gc.NotNil) firstCalled++ return httpbakery.ErrMethodNotSupported }), visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error { c.Check(m["method"], gc.NotNil) secondCalled++ return nil }), ) err := v.VisitWebPage(httpbakery.NewClient(), map[string]*url.URL{ httpbakery.UserInteractionMethod: mustParseURL(srv.URL), }) c.Assert(err, gc.IsNil) c.Assert(firstCalled, gc.Equals, 1) c.Assert(secondCalled, gc.Equals, 1) }
func (s *formSuite) TestFormLogin(c *gc.C) { d := &formDischarger{} d.discharger = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(d.login)) defer d.discharger.Close() d.discharger.Mux.Handle("/form", http.HandlerFunc(d.form)) svc, err := bakery.NewService(bakery.NewServiceParams{ Locator: d.discharger, }) c.Assert(err, gc.IsNil) for i, test := range formLoginTests { c.Logf("%d. %s", i, test.about) d.dischargeOptions = test.opts m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{ Location: d.discharger.Location(), Condition: "test condition", }}) c.Assert(err, gc.Equals, nil) client := httpbakery.NewClient() h := defaultFiller if test.filler != nil { h = test.filler } client.VisitWebPage = test.fallback form.SetUpAuth(client, h) ms, err := client.DischargeAll(m) if test.expectError != "" { c.Assert(err, gc.ErrorMatches, test.expectError) continue } c.Assert(err, gc.IsNil) c.Assert(len(ms), gc.Equals, 2) } }
func (*VisitorSuite) TestUserInteractionFallback(c *gc.C) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, `{"method": "http://somewhere/something"}`) })) defer srv.Close() called := 0 // Check that even though the methods didn't explicitly // include the "interactive" method, it is still supplied. v := httpbakery.NewMultiVisitor( visitorFunc(func(_ *httpbakery.Client, m map[string]*url.URL) error { c.Check(m, jc.DeepEquals, map[string]*url.URL{ "method": mustParseURL("http://somewhere/something"), httpbakery.UserInteractionMethod: mustParseURL(srv.URL), }) called++ return nil }), ) err := v.VisitWebPage(httpbakery.NewClient(), map[string]*url.URL{ httpbakery.UserInteractionMethod: mustParseURL(srv.URL), }) c.Assert(err, gc.IsNil) c.Assert(called, gc.Equals, 1) }
func (s *macaroonServerSuite) TestServerBakery(c *gc.C) { srv := newServer(c, s.State) defer srv.Stop() m, err := apiserver.ServerMacaroon(srv) c.Assert(err, gc.IsNil) bsvc, err := apiserver.ServerBakeryService(srv) c.Assert(err, gc.IsNil) // Check that we can add a third party caveat addressed to the // discharger, which indirectly ensures that the discharger's public // key has been added to the bakery service's locator. m = m.Clone() err = bsvc.AddCaveat(m, checkers.Caveat{ Location: s.discharger.Location(), Condition: "true", }) c.Assert(err, jc.ErrorIsNil) // Check that we can discharge the macaroon and check it with // the service. client := httpbakery.NewClient() ms, err := client.DischargeAll(m) c.Assert(err, jc.ErrorIsNil) err = bsvc.Check(ms, checkers.New()) c.Assert(err, gc.IsNil) }
func (s *ClientSuite) TestThirdPartyDischargeRefused(c *gc.C) { d := bakerytest.NewDischarger(nil, func(_ *http.Request, cond, arg string) ([]checkers.Caveat, error) { return nil, errgo.New("boo! cond " + cond) }) defer d.Close() // Create a target service. svc := newService("loc", d) ts := httptest.NewServer(serverHandler(serverHandlerParams{ service: svc, authLocation: d.Location(), })) defer ts.Close() // Create a client request. req, err := http.NewRequest("GET", ts.URL, nil) c.Assert(err, gc.IsNil) client := httpbakery.NewClient() // Make the request to the server. resp, err := client.Do(req) c.Assert(errgo.Cause(err), gc.FitsTypeOf, (*httpbakery.DischargeError)(nil)) c.Assert(err, gc.ErrorMatches, `cannot get discharge from ".*": third party refused discharge: cannot discharge: boo! cond is-ok`) c.Assert(resp, gc.IsNil) }
func (s ClientSuite) TestWithLargeBody(c *gc.C) { // This test is designed to fail when run with the race // checker enabled and when go issue #12796 // is not fixed. d := bakerytest.NewDischarger(nil, noCaveatChecker) defer d.Close() // Create a target service. svc := newService("loc", d) ts := httptest.NewServer(serverHandler(serverHandlerParams{ service: svc, authLocation: d.Location(), })) defer ts.Close() // Create a client request. req, err := http.NewRequest("POST", ts.URL+"/no-body", nil) c.Assert(err, gc.IsNil) body := &largeReader{total: 3 * 1024 * 1024} resp, err := httpbakery.NewClient().DoWithBody(req, body) c.Assert(err, gc.IsNil) resp.Body.Close() body.Close() c.Assert(resp.StatusCode, gc.Equals, http.StatusOK) }
func (s *formSuite) TestFormTitle(c *gc.C) { d := &formDischarger{} d.discharger = bakerytest.NewInteractiveDischarger(nil, http.HandlerFunc(d.login)) defer d.discharger.Close() d.discharger.Mux.Handle("/form", http.HandlerFunc(d.form)) svc, err := bakery.NewService(bakery.NewServiceParams{ Locator: testLocator{ loc: d.discharger.Location(), locator: d.discharger, }, }) c.Assert(err, gc.IsNil) for i, test := range formTitleTests { c.Logf("%d. %s", i, test.host) m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{ Location: "https://" + test.host, Condition: "test condition", }}) c.Assert(err, gc.Equals, nil) client := httpbakery.NewClient() client.Client.Transport = httptesting.URLRewritingTransport{ MatchPrefix: "https://" + test.host, Replace: d.discharger.Location(), RoundTripper: http.DefaultTransport, } f := new(titleTestFiller) form.SetUpAuth(client, f) ms, err := client.DischargeAll(m) c.Assert(err, gc.IsNil) c.Assert(len(ms), gc.Equals, 2) c.Assert(f.title, gc.Equals, test.expect) } }
func (s *ClientSuite) TestDischargeAcquirer(c *gc.C) { rootKey := []byte("secret") m, err := macaroon.New(rootKey, "", "here") c.Assert(err, gc.IsNil) dischargeRootKey := []byte("shared root key") thirdPartyCaveatId := "3rd party caveat" err = m.AddThirdPartyCaveat(dischargeRootKey, thirdPartyCaveatId, "there") c.Assert(err, gc.IsNil) dm, err := macaroon.New(dischargeRootKey, thirdPartyCaveatId, "there") c.Assert(err, gc.IsNil) ta := &testAcquirer{dischargeMacaroon: dm} cl := httpbakery.NewClient() cl.DischargeAcquirer = ta ms, err := cl.DischargeAll(m) c.Assert(err, gc.IsNil) c.Assert(ms, gc.HasLen, 2) c.Assert(ta.acquireLocation, gc.Equals, "here") // should be first-party location c.Assert(ta.acquireCaveat.Id, gc.Equals, thirdPartyCaveatId) expectCaveat := "must foo" var lastCaveat string err = ms[0].Verify(rootKey, func(s string) error { if s != expectCaveat { return errgo.Newf(`expected %q, got %q`, expectCaveat, s) } lastCaveat = s return nil }, ms[1:]) c.Assert(err, gc.IsNil) c.Assert(lastCaveat, gc.Equals, expectCaveat) }
func (*suite) TestDoRequest(c *gc.C) { var h handler srv := httptest.NewServer(&h) for i, test := range doRequestTests { c.Logf("test %d: %s", i, test.about) client := httpbakery.NewClient() u, err := url.Parse(srv.URL + test.url) c.Assert(err, gc.IsNil) test.ctxt.url = u if test.ctxt.header == nil { test.ctxt.header = make(http.Header) } resp, err := test.ctxt.doRequest(client, strings.NewReader(test.stdin)) c.Assert(err, gc.IsNil) c.Assert(resp.StatusCode, gc.Equals, http.StatusOK) resp.Body.Close() // Don't do a DeepEquals on the expected request, // as it will contain all kinds of stuff that we aren't // that concerned with. Instead, test that the // data we've specified is there in the request. c.Assert(h.request.Method, gc.Equals, test.expectRequest.Method) for attr, vals := range test.expectRequest.Header { c.Assert(h.request.Header[attr], jc.DeepEquals, vals, gc.Commentf("attr %s", attr)) } h.request.URL.Host = "" c.Assert(h.request.URL, jc.DeepEquals, test.expectRequest.URL) c.Assert(string(h.requestBody), gc.Equals, test.expectRequestBody) } }
func (s *registrationSuite) TestMeteredLocalCharmWithPlan(c *gc.C) { client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("local:quantal/metered-1"), }, ServiceName: "service name", ModelUUID: "model uuid", } err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d) c.Assert(err, jc.ErrorIsNil) err = s.register.RunPost(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d, nil) c.Assert(err, jc.ErrorIsNil) authorization, err := json.Marshal([]byte("hello registration")) authorization = append(authorization, byte(0xa)) s.stub.CheckCalls(c, []testing.StubCall{{ "APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "local:quantal/metered-1"}}, }, { "Authorize", []interface{}{metricRegistrationPost{ ModelUUID: "model uuid", CharmURL: "local:quantal/metered-1", ServiceName: "service name", PlanURL: "someplan", Budget: "personal", Limit: "100", }}, }, { "APICall", []interface{}{"Service", "SetMetricCredentials", params.ServiceMetricCredentials{ Creds: []params.ServiceMetricCredential{params.ServiceMetricCredential{ ServiceName: "service name", MetricCredentials: authorization, }}, }}, }}) }
func (s *registrationSuite) TestFailedAuth(c *gc.C) { s.stub.SetErrors(nil, fmt.Errorf("could not authorize")) client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("cs:quantal/metered-1"), }, ServiceName: "service name", ModelUUID: "model uuid", } err := s.register.RunPre(&mockAPIConnection{Stub: s.stub}, client, s.ctx, d) c.Assert(err, gc.ErrorMatches, `authorization failed:.*`) authorization, err := json.Marshal([]byte("hello registration")) authorization = append(authorization, byte(0xa)) c.Assert(err, jc.ErrorIsNil) s.stub.CheckCalls(c, []testing.StubCall{{ "APICall", []interface{}{"Charms", "IsMetered", params.CharmInfo{CharmURL: "cs:quantal/metered-1"}}, }, { "Authorize", []interface{}{metricRegistrationPost{ ModelUUID: "model uuid", CharmURL: "cs:quantal/metered-1", ServiceName: "service name", PlanURL: "someplan", Budget: "personal", Limit: "100", }}, }}) }
func (s *registrationSuite) TestMeteredCharmFailToQueryDefaultCharm(c *gc.C) { s.stub.SetErrors(nil, errors.New("something failed")) s.register = &RegisterMeteredCharm{ AllocationSpec: "personal:100", RegisterURL: s.server.URL, QueryURL: s.server.URL} client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("cs:quantal/metered-1"), }, ApplicationName: "application name", ModelUUID: "model uuid", CharmInfo: &apicharms.CharmInfo{ Metrics: &charm.Metrics{ Plan: &charm.Plan{Required: true}, }, }, } err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d) c.Assert(err, gc.ErrorMatches, `failed to query default plan:.*`) s.stub.CheckCalls(c, []testing.StubCall{{ "IsMetered", []interface{}{"cs:quantal/metered-1"}, }, { "DefaultPlan", []interface{}{"cs:quantal/metered-1"}, }}) }
// NewAPIContext returns an API context that will use the given // context for user interactions when authorizing. // The returned API context must be closed after use. // // If ctxt is nil, no command-line authorization // will be supported. // // This function is provided for use by commands that cannot use // JujuCommandBase. Most clients should use that instead. func NewAPIContext(ctxt *cmd.Context) (*APIContext, error) { jar, err := cookiejar.New(&cookiejar.Options{ Filename: cookieFile(), }) if err != nil { return nil, errors.Trace(err) } client := httpbakery.NewClient() client.Jar = jar if ctxt != nil { filler := &form.IOFiller{ In: ctxt.Stdin, Out: ctxt.Stdout, } client.VisitWebPage = ussologin.VisitWebPage( "juju", &http.Client{}, filler, jujuclient.NewTokenStore(), ) } else { client.VisitWebPage = httpbakery.OpenWebBrowser } return &APIContext{ Jar: jar, BakeryClient: client, }, nil }
func (s *registrationSuite) TestMeteredCharmDeployError(c *gc.C) { client := httpbakery.NewClient() d := DeploymentInfo{ CharmID: charmstore.CharmID{ URL: charm.MustParseURL("cs:quantal/metered-1"), }, ApplicationName: "application name", ModelUUID: "model uuid", CharmInfo: &apicharms.CharmInfo{ Metrics: &charm.Metrics{ Plan: &charm.Plan{Required: true}, }, }, } err := s.register.RunPre(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d) c.Assert(err, jc.ErrorIsNil) deployError := errors.New("deployment failed") err = s.register.RunPost(&mockMeteredDeployAPI{Stub: s.stub}, client, s.ctx, d, deployError) c.Assert(err, jc.ErrorIsNil) authorization, err := json.Marshal([]byte("hello registration")) authorization = append(authorization, byte(0xa)) c.Assert(err, jc.ErrorIsNil) s.stub.CheckCalls(c, []testing.StubCall{{ "IsMetered", []interface{}{"cs:quantal/metered-1"}, }, { "Authorize", []interface{}{metricRegistrationPost{ ModelUUID: "model uuid", CharmURL: "cs:quantal/metered-1", ApplicationName: "application name", PlanURL: "someplan", Budget: "personal", Limit: "100", }}, }}) }
func newClient(p *params) (*cookiejar.Jar, *httpbakery.Client, error) { client := httpbakery.NewClient() var jar *cookiejar.Jar if p.cookieFile != "" { var err error jar, err = cookiejar.New(&cookiejar.Options{ PublicSuffixList: publicsuffix.List, }) if err != nil { panic(err) } if err := jar.Load(p.cookieFile); err != nil { return nil, nil, fmt.Errorf("cannot load cookie jar: %v", err) } client.Client.Jar = jar } client.VisitWebPage = httpbakery.OpenWebBrowser if p.insecure { rt := *http.DefaultTransport.(*http.Transport) rt.TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, } client.Transport = &rt } return jar, client, nil }
func (s *ClientSuite) TestDoWithBodyFailsWithBodyInRequest(c *gc.C) { body := strings.NewReader("foo") // Create a client request. req, err := http.NewRequest("POST", "http://0.1.2.3/", body) c.Assert(err, gc.IsNil) _, err = httpbakery.NewClient().DoWithBody(req, body) c.Assert(err, gc.ErrorMatches, "body unexpectedly supplied in Request struct") }
func (s *formSuite) TestFormLoginNewRequestError(c *gc.C) { client := httpbakery.NewClient() form.SetUpAuth(client, defaultFiller) u := url.URL{ Scheme: ":", } err := client.VisitWebPage(&u) c.Assert(err, gc.ErrorMatches, "cannot create request: parse :://: missing protocol scheme") }
func (s *ClientSuite) TestHandleErrorDifferentError(c *gc.C) { berr := &httpbakery.Error{ Message: "an error", Code: "another code", } client := httpbakery.NewClient() err := client.HandleError(&url.URL{}, berr) c.Assert(err, gc.Equals, berr) }
func ExampleVisitWebPage() { var key *bakery.KeyPair var u *url.URL client := httpbakery.NewClient() client.Key = key agent.SetCookie(client.Jar, u, "agent-username", &client.Key.Public) client.VisitWebPage = agent.VisitWebPage(client) }
func (s *ClientSuite) TestRepeatedRequestWithBody(c *gc.C) { d := bakerytest.NewDischarger(nil, noCaveatChecker) defer d.Close() // Create a target service. svc := newService("loc", d) ts := httptest.NewServer(serverHandler(serverHandlerParams{ service: svc, authLocation: d.Location(), alwaysReadBody: true, })) defer ts.Close() // Create a client request. req, err := http.NewRequest("POST", ts.URL, nil) c.Assert(err, gc.IsNil) // Make the request to the server. // First try with a body in the request, which should be denied // because we must use DoWithBody. req.Body = ioutil.NopCloser(strings.NewReader("postbody")) resp, err := httpbakery.NewClient().Do(req) c.Assert(err, gc.ErrorMatches, "body unexpectedly provided in request - use DoWithBody") c.Assert(resp, gc.IsNil) // Then try with no authorization, so make sure that httpbakery.Do // really will retry the request. req.Body = nil bodyText := "postbody" bodyReader := &readCounter{ReadSeeker: strings.NewReader(bodyText)} resp, err = httpbakery.NewClient().DoWithBody(req, bodyReader) c.Assert(err, gc.IsNil) defer resp.Body.Close() assertResponse(c, resp, "done postbody") // Sanity check that the body really was read twice and hence // that we are checking the logic we intend to check. c.Assert(bodyReader.byteCount, gc.Equals, len(bodyText)*2) }
func (*suite) TestMacaraq(c *gc.C) { checked := false d := bakerytest.NewDischarger(nil, func(_ *http.Request, cond, arg string) ([]checkers.Caveat, error) { if cond != "something" { return nil, fmt.Errorf("unexpected 3rd party cond") } checked = true return nil, nil }) bsvc, err := bakery.NewService(bakery.NewServiceParams{ Location: "here", Locator: d, }) c.Assert(err, gc.IsNil) svc := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.ParseForm() _, checkErr := httpbakery.CheckRequest(bsvc, req, nil, checkers.New()) if checkErr == nil { w.Header().Set("Content-Type", "application/json") data, err := json.Marshal(req.Form) c.Check(err, gc.IsNil) w.Write(data) return } m, err := bsvc.NewMacaroon("", nil, []checkers.Caveat{{ Location: d.Service.Location(), Condition: "something", }}) c.Check(err, gc.IsNil) httpbakery.WriteDischargeRequiredError(w, m, "/", checkErr) })) fset := flag.NewFlagSet("http", flag.ContinueOnError) ctxt, params, err := newContext(fset, []string{ svc.URL, "x=y", }) c.Assert(err, gc.IsNil) client := httpbakery.NewClient() resp, err := ctxt.doRequest(client, nil) c.Assert(err, gc.IsNil) defer resp.Body.Close() c.Assert(resp.StatusCode, gc.Equals, http.StatusOK) c.Assert(checked, jc.IsTrue) var stdout bytes.Buffer err = showResponse(params, resp, &stdout) c.Assert(err, gc.IsNil) c.Assert(stdout.String(), gc.Equals, `{ x: [ "y" ] } `) }
func (s *registrationSuite) TestHttpMetricsRegistrar(c *gc.C) { client := httpbakery.NewClient() data, err := registerMetrics(s.server.URL, "environment uuid", "charm url", "service name", client) c.Assert(err, gc.IsNil) var b []byte err = json.Unmarshal(data, &b) c.Assert(err, gc.IsNil) c.Assert(string(b), gc.Equals, "hello registration") c.Assert(s.handler.registrationCalls, gc.HasLen, 1) c.Assert(s.handler.registrationCalls[0], gc.DeepEquals, metricRegistrationPost{EnvironmentUUID: "environment uuid", CharmURL: "charm url", ServiceName: "service name"}) }