Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions web/relative.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ package web
import (
"net/http"
"net/url"
"path"
)

// RelativeEndpoint takes a path component of URL and constructs a new URL using
// the host and port from the request combined the provided path.
func RelativeEndpoint(request *http.Request, endpoint string) string {
// the host and port from the request combined the provided basePath and any
// additionalPaths if provided. If only a basePath is provided with no
// additionalPaths and the basePath has a trailing slash, the trailing
// slash will be retained.
func RelativeEndpoint(request *http.Request, basePath string, additionalPaths ...string) string {
var result string
proto := "http"
host := request.Host
Expand All @@ -29,6 +33,17 @@ func RelativeEndpoint(request *http.Request, endpoint string) string {
host = "localhost"
}

endpoint := basePath
// Checking for additionalPaths is vital because path.Join runs path.Clean
// and removes trailing slashes but there are scenarios such as in
// WebFrontEndImpl.acctIDFromURL where the basePath is only
// provided and the trailing slash needs to be kept
if len(additionalPaths) > 0 {
paths := []string{basePath}
paths = append(paths, additionalPaths...)
endpoint = path.Join(paths...)
}

resultUrl := url.URL{Scheme: proto, Host: host, Path: endpoint}
result = resultUrl.String()

Expand Down
36 changes: 19 additions & 17 deletions wfe2/wfe.go
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ func (wfe *WebFrontEndImpl) NewAccount(
}

response.Header().Set("Location",
web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, acctPB.Id)))
web.RelativeEndpoint(request, acctPath, fmt.Sprintf("%d", acctPB.Id)))
logEvent.Requester = acctPB.Id
addRequesterHeader(response, acctPB.Id)

Expand Down Expand Up @@ -889,7 +889,7 @@ func (wfe *WebFrontEndImpl) NewAccount(
logEvent.Requester = acct.ID
addRequesterHeader(response, acct.ID)

acctURL := web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, acct.ID))
acctURL := web.RelativeEndpoint(request, acctPath, fmt.Sprintf("%d", acct.ID))

response.Header().Add("Location", acctURL)
if len(wfe.SubscriberAgreementURL) > 0 {
Expand Down Expand Up @@ -1205,7 +1205,7 @@ func (wfe *WebFrontEndImpl) prepChallengeForDisplay(
challenge *core.Challenge,
) {
// Update the challenge URL to be relative to the HTTP request Host
challenge.URL = web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s/%s", challengePath, authz.RegistrationID, authz.ID, challenge.StringID()))
challenge.URL = web.RelativeEndpoint(request, challengePath, fmt.Sprintf("%d", authz.RegistrationID), authz.ID, challenge.StringID())

// Internally, we store challenge error problems with just the short form
// (e.g. "CAA") of the problem type. But for external display, we need to
Expand Down Expand Up @@ -1768,7 +1768,7 @@ func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *web.Reque
continue
}
chainURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%s/%d", certPath, serial, chainID))
certPath, serial, fmt.Sprintf("%d", chainID))
response.Header().Add("Link", link(chainURL, "alternate"))
}

Expand Down Expand Up @@ -1960,7 +1960,7 @@ func (wfe *WebFrontEndImpl) KeyRollover(
existingAcct, err := wfe.sa.GetRegistrationByKey(ctx, &sapb.JSONWebKey{Jwk: newKeyBytes})
if err == nil {
response.Header().Set("Location",
web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, existingAcct.Id)))
web.RelativeEndpoint(request, acctPath, fmt.Sprintf("%d", existingAcct.Id)))
wfe.sendError(response, logEvent,
probs.Conflict("New key is already in use for a different account"), err)
return
Expand All @@ -1983,7 +1983,7 @@ func (wfe *WebFrontEndImpl) KeyRollover(
return
}
response.Header().Set("Location",
web.RelativeEndpoint(request, fmt.Sprintf("%s%d", acctPath, existingAcct.Id)))
web.RelativeEndpoint(request, acctPath, fmt.Sprintf("%d", existingAcct.Id)))
wfe.sendError(response, logEvent,
probs.Conflict("New key is already in use for a different account"), err)
return
Expand Down Expand Up @@ -2022,8 +2022,8 @@ type orderJSON struct {
// DNS type identifiers and additionally create absolute URLs for the finalize
// URL and the certificate URL as appropriate.
func (wfe *WebFrontEndImpl) orderToOrderJSON(request *http.Request, order *corepb.Order) orderJSON {
finalizeURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%d/%d", finalizeOrderPath, order.RegistrationID, order.Id))
finalizeURL := web.RelativeEndpoint(request, finalizeOrderPath,
fmt.Sprintf("%d", order.RegistrationID), fmt.Sprintf("%d", order.Id))
respObj := orderJSON{
Status: core.AcmeStatus(order.Status),
Expires: order.Expires.AsTime(),
Expand All @@ -2043,11 +2043,13 @@ func (wfe *WebFrontEndImpl) orderToOrderJSON(request *http.Request, order *corep
respObj.Error.Type = probs.ErrorNS + respObj.Error.Type
}
for _, v2ID := range order.V2Authorizations {
respObj.Authorizations = append(respObj.Authorizations, web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%d", authzPath, order.RegistrationID, v2ID)))
endpoint := web.RelativeEndpoint(request,
authzPath, fmt.Sprintf("%d", order.RegistrationID), fmt.Sprintf("%d", v2ID))
respObj.Authorizations = append(respObj.Authorizations, endpoint)
}
if respObj.Status == core.StatusValid {
certURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%s", certPath, order.CertificateSerial))
certPath, order.CertificateSerial)
respObj.Certificate = certURL
}
return respObj
Expand Down Expand Up @@ -2432,8 +2434,8 @@ func (wfe *WebFrontEndImpl) NewOrder(
}
logEvent.Created = fmt.Sprintf("%d", order.Id)

orderURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%d/%d", orderPath, acct.ID, order.Id))
orderURL := web.RelativeEndpoint(request, orderPath,
fmt.Sprintf("%d", acct.ID), fmt.Sprintf("%d", order.Id))
response.Header().Set("Location", orderURL)

respObj := wfe.orderToOrderJSON(request, order)
Expand Down Expand Up @@ -2511,8 +2513,8 @@ func (wfe *WebFrontEndImpl) GetOrder(ctx context.Context, logEvent *web.RequestE
response.Header().Set(headerRetryAfter, strconv.Itoa(orderRetryAfter))
}

orderURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%d/%d", orderPath, acctID, order.Id))
orderURL := web.RelativeEndpoint(request, orderPath,
fmt.Sprintf("%d", acctID), fmt.Sprintf("%d", order.Id))
response.Header().Set("Location", orderURL)

err = wfe.writeJsonResponse(response, logEvent, http.StatusOK, respObj)
Expand Down Expand Up @@ -2640,8 +2642,8 @@ func (wfe *WebFrontEndImpl) FinalizeOrder(ctx context.Context, logEvent *web.Req
// Inc CSR signature algorithm counter
wfe.stats.csrSignatureAlgs.With(prometheus.Labels{"type": csr.SignatureAlgorithm.String()}).Inc()

orderURL := web.RelativeEndpoint(request,
fmt.Sprintf("%s%d/%d", orderPath, acct.ID, updatedOrder.Id))
orderURL := web.RelativeEndpoint(request, orderPath,
fmt.Sprintf("%d", acct.ID), fmt.Sprintf("%d", updatedOrder.Id))
response.Header().Set("Location", orderURL)

respObj := wfe.orderToOrderJSON(request, updatedOrder)
Expand Down Expand Up @@ -2735,5 +2737,5 @@ func (wfe *WebFrontEndImpl) RenewalInfo(ctx context.Context, logEvent *web.Reque
}

func urlForAuthz(authz core.Authorization, request *http.Request) string {
return web.RelativeEndpoint(request, fmt.Sprintf("%s%d/%s", authzPath, authz.RegistrationID, authz.ID))
return web.RelativeEndpoint(request, authzPath, fmt.Sprintf("%d", authz.RegistrationID), authz.ID)
}
Loading