http.go
func getExtHeader(credentials *Credentials) (header string, err error) {
	ext := &ExtHeader{}
	if credentials.Certificate != "" {
		certObj := new(Certificate)
		err = json.Unmarshal([]byte(credentials.Certificate), certObj)
		if err != nil {
			return "", err
		}
		ext.Certificate = certObj
	}

	if credentials.AuthorizedScopes != nil {
		ext.AuthorizedScopes = &credentials.AuthorizedScopes
	}
	extJSON, err := json.Marshal(ext)
	if err != nil {
		return "", err
	}
	if string(extJSON) != "{}" {
		return base64.StdEncoding.EncodeToString(extJSON), nil
	}
	return "", nil
}
func getExtHeader(credentials *Credentials) (header string, err error) {
	ext := &ExtHeader{}
	if credentials.Certificate != "" {
		certObj := new(Certificate)
		err = json.Unmarshal([]byte(credentials.Certificate), certObj)
		if err != nil {
			return "", err
		}
		ext.Certificate = certObj
	}

	if credentials.AuthorizedScopes != nil {
		ext.AuthorizedScopes = &credentials.AuthorizedScopes
	}
	extJSON, err := json.Marshal(ext)
	if err != nil {
		return "", err
	}
	if string(extJSON) != "{}" {
		return base64.StdEncoding.EncodeToString(extJSON), nil
	}
	return "", nil
}
// getExtHeader generates the hawk ext header based on the authorizedScopes and
// the certificate used in the case of temporary credentials. The header is a
// base64 encoded json object with a "certificate" property set to the
// certificate of the temporary credentials and a "authorizedScopes" property
// set to the array of authorizedScopes, if provided.  If either "certificate"
// or "authorizedScopes" is not supplied, they will be omitted from the json
// result. If neither are provided, an empty string is returned, rather than a
// base64 encoded representation of "null" or "{}". Hawk interprets the empty
// string as meaning the ext header is not needed.
//
// See:
//   * https://docs.taskcluster.net/docs/manual/design/apis/hawk/authorized-scopes
//   * https://docs.taskcluster.net/docs/manual/design/apis/hawk/temporary-credentials