Support POST-as-GET. (#695)
This commit is contained in:
parent
5992cc0ece
commit
4f36f4354b
3 changed files with 38 additions and 26 deletions
|
@ -665,7 +665,7 @@ func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, error)
|
|||
|
||||
go func(authzURL string) {
|
||||
var authz authorization
|
||||
_, err := getJSON(authzURL, &authz)
|
||||
_, err := postAsGet(c.jws, authzURL, &authz)
|
||||
if err != nil {
|
||||
errc <- domainError{Domain: authz.Identifier.Value, Error: err}
|
||||
return
|
||||
|
@ -789,7 +789,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
|||
case <-stopTimer.C:
|
||||
return nil, errors.New("certificate polling timed out")
|
||||
case <-retryTick.C:
|
||||
_, err := getJSON(order.URL, &retOrder)
|
||||
_, err := postAsGet(c.jws, order.URL, &retOrder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
|||
func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResource, bundle bool) (bool, error) {
|
||||
switch order.Status {
|
||||
case statusValid:
|
||||
resp, err := httpGet(order.Certificate)
|
||||
resp, err := postAsGet(c.jws, order.Certificate, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -871,7 +871,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
|
|||
// getIssuerCertificate requests the issuer certificate
|
||||
func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
|
||||
log.Infof("acme: Requesting issuer cert from %s", url)
|
||||
resp, err := httpGet(url)
|
||||
resp, err := postAsGet(c.jws, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -943,11 +943,15 @@ func validate(j *jws, domain, uri string, c challenge) error {
|
|||
// If it doesn't, we'll just poll hard.
|
||||
ra = 5
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(ra) * time.Second)
|
||||
|
||||
hdr, err = getJSON(uri, &chlng)
|
||||
resp, err := postAsGet(j, uri, &chlng)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp != nil {
|
||||
hdr = resp.Header
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,10 +155,10 @@ func TestValidate(t *testing.T) {
|
|||
privKey, err := rsa.GenerateKey(rand.Reader, 512)
|
||||
require.NoError(t, err)
|
||||
|
||||
// validateNoBody reads the http.Request POST body, parses the JWS and
|
||||
// validates it to read the body. If there is an error doing this, or if the
|
||||
// JWS body is not the empty JSON payload "{}" an error is returned. We use
|
||||
// this to verify challenge POSTs to the ts below do not send a JWS body.
|
||||
// validateNoBody reads the http.Request POST body, parses the JWS and validates it to read the body.
|
||||
// If there is an error doing this,
|
||||
// or if the JWS body is not the empty JSON payload "{}" or a POST-as-GET payload "" an error is returned.
|
||||
// We use this to verify challenge POSTs to the ts below do not send a JWS body.
|
||||
validateNoBody := func(r *http.Request) error {
|
||||
reqBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
|
@ -178,8 +178,8 @@ func TestValidate(t *testing.T) {
|
|||
return err
|
||||
}
|
||||
|
||||
if bodyStr := string(body); bodyStr != "{}" {
|
||||
return fmt.Errorf(`expected JWS POST body "{}", got %q`, bodyStr)
|
||||
if bodyStr := string(body); bodyStr != "{}" && bodyStr != "" {
|
||||
return fmt.Errorf(`expected JWS POST body "{}" or "", got %q`, bodyStr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
38
acme/http.go
38
acme/http.go
|
@ -151,48 +151,56 @@ func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, e
|
|||
return nil, errors.New("failed to marshal network message")
|
||||
}
|
||||
|
||||
resp, err := j.post(uri, jsonBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to post JWS message. -> %v", err)
|
||||
resp, err := post(j, uri, jsonBytes, respBody)
|
||||
if resp == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
return resp.Header, err
|
||||
}
|
||||
|
||||
func postAsGet(j *jws, uri string, respBody interface{}) (*http.Response, error) {
|
||||
return post(j, uri, []byte{}, respBody)
|
||||
}
|
||||
|
||||
func post(j *jws, uri string, reqBody []byte, respBody interface{}) (*http.Response, error) {
|
||||
resp, err := j.post(uri, reqBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to post JWS message. -> %v", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
err = handleHTTPError(resp)
|
||||
switch err.(type) {
|
||||
case NonceError:
|
||||
// Retry once if the nonce was invalidated
|
||||
|
||||
retryResp, errP := j.post(uri, jsonBytes)
|
||||
retryResp, errP := j.post(uri, reqBody)
|
||||
if errP != nil {
|
||||
return nil, fmt.Errorf("failed to post JWS message. -> %v", errP)
|
||||
}
|
||||
|
||||
defer retryResp.Body.Close()
|
||||
|
||||
if retryResp.StatusCode >= http.StatusBadRequest {
|
||||
return retryResp.Header, handleHTTPError(retryResp)
|
||||
return retryResp, handleHTTPError(retryResp)
|
||||
}
|
||||
|
||||
if respBody == nil {
|
||||
return retryResp.Header, nil
|
||||
return retryResp, nil
|
||||
}
|
||||
|
||||
return retryResp.Header, json.NewDecoder(retryResp.Body).Decode(respBody)
|
||||
|
||||
return retryResp, json.NewDecoder(retryResp.Body).Decode(respBody)
|
||||
default:
|
||||
return resp.Header, err
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if respBody == nil {
|
||||
return resp.Header, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
return resp.Header, json.NewDecoder(resp.Body).Decode(respBody)
|
||||
return resp, json.NewDecoder(resp.Body).Decode(respBody)
|
||||
}
|
||||
|
||||
// userAgent builds and returns the User-Agent string to use in requests.
|
||||
|
|
Loading…
Reference in a new issue