// Registers a new account or updates an existing account. // // The ContactURIs specified will be set. // // If a new agreement is required and it is set in AgreementURIs, it will be // agreed to automatically. Otherwise AgreementError will be returned. func (c *Client) UpsertRegistration(ctx context.Context) error { regURI, err := c.getRegistrationURI(ctx) if err != nil { return err } reqInfo := regInfo{ Resource: "reg", Contact: c.AccountInfo.ContactURIs, } var resInfo *regInfo res, err := c.doReq("POST", regURI, &reqInfo, &resInfo, ctx) if err != nil { return err } lg := link.ParseResponse(res) if tosLink, ok := lg["terms-of-service"]; ok { if resInfo.AgreementURI != tosLink.URI { _, ok := c.AccountInfo.AgreementURIs[tosLink.URI] if !ok { return &AgreementError{tosLink.URI} } reqInfo.AgreementURI = tosLink.URI _, err = c.doReq("POST", regURI, &reqInfo, &resInfo, ctx) if err != nil { return err } } } return nil }
func (c *Client) loadExtraCertificates(crt *Certificate, res *http.Response, ctx context.Context) error { crt.ExtraCertificates = nil for { var err error lg := link.ParseResponse(res) up, ok := lg["up"] if !ok { return nil } crtURI, _ := url.Parse(crt.URI) upURI, _ := url.Parse(up.URI) if crtURI == nil || upURI == nil { return fmt.Errorf("invalid URI") } upURI = crtURI.ResolveReference(upURI) res, err = c.doReq("GET", upURI.String(), nil, nil, ctx) if err != nil { return err } defer res.Body.Close() ct := res.Header.Get("Content-Type") if ct != "application/pkix-cert" { return fmt.Errorf("unexpected certificate type: %v", ct) } der, err := ioutil.ReadAll(res.Body) if err != nil { return err } res.Body.Close() crt.ExtraCertificates = append(crt.ExtraCertificates, der) } }
// Loads an existing registration. If reg.URI is set, then that registration is // updated, and the operation fails if the registration does not exist. // Otherwise, the registration is created if it does not exist or updated if it // does and the URI is returned. // // Note that this operation requires an account key, since the registration is // private data requiring authentication to access. func (c *Client) UpsertRegistration(reg *Registration, ctx context.Context) error { reg.Resource = "reg" if reg.URI == "" { var err error reg.URI, err = c.getRegistrationURI(ctx) if err != nil { return err } } res, err := c.doReq("POST", reg.URI, reg, reg, ctx) if err != nil { return err } lg := link.ParseResponse(res) if tosLink, ok := lg["terms-of-service"]; ok { reg.LatestAgreementURI = tosLink.URI } return nil }
// Loads an existing registration. If reg.URI is set, then that registration is // updated, and the operation fails if the registration does not exist. // Otherwise, the registration is created if it does not exist or updated if it // does and the URI is returned. // // Note that this operation requires an account key, since the registration is // private data requiring authentication to access. func (c *Client) UpsertRegistration(reg *Registration, ctx context.Context) error { di, err := c.getDirectory(ctx) if err != nil { return err } // Determine whether we need to get the registration URI. endp := reg.URI resource := "reg" expectCode := updateRegCodes if endp == "" { endp = di.NewReg resource = "new-reg" expectCode = newRegCodes } // Make request. reg.Resource = resource res, err := c.doReq("POST", endp, reg, reg, ctx) if res == nil { return err } // Get TOS URI. lg := link.ParseResponse(res) if tosLink, ok := lg["terms-of-service"]; ok { reg.LatestAgreementURI = tosLink.URI } // Ensure status code is an expected value. if !isStatusCode(res, expectCode) { if err != nil { return err } return fmt.Errorf("unexpected status code: %d: %v", res.StatusCode, endp) } // Process registration URI. loc := res.Header.Get("Location") switch { case resource == "reg": // Updating existing registration, so we already have the URL and // shouldn't be redirected anywhere. if loc != "" { return fmt.Errorf("unexpected Location header: %q", loc) } case !ValidURL(loc): return fmt.Errorf("invalid URL: %q", loc) default: // Save the registration URL. reg.URI = loc } // If conflict occurred, need to issue the request again to update fields. if res.StatusCode == 409 { return c.UpsertRegistration(reg, ctx) } return nil }