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