static std::string buildCanonicalReuqest()

in sdk/src/signer/SignerV4.cc [146:224]


static std::string buildCanonicalReuqest(const std::shared_ptr<HttpRequest> &httpRequest, ParameterCollection &parameters,
    SignerParam &signerParam, const HeaderSet &additionalHeaders) 
{
    /*Version 4*/
    // HTTP Verb + "\n" +
    // Canonical URI + "\n" +
    // Canonical Query String + "\n" +
    // Canonical Headers + "\n" +
    // Additional Headers + "\n" +
    // Hashed PayLoad

    std::stringstream ss;
    // "GET" | "PUT" | "POST" | ... + "\n"
    ss << Http::MethodToString(httpRequest->method()) << "\n"; 
    
    // UriEncode(<Resource>) + "\n"
    std::string resource;
    resource.append("/");
    if (!signerParam.Bucket().empty()) {
        resource.append(signerParam.Bucket());
        resource.append("/");
    }
    if (!signerParam.Key().empty()) {
        resource.append(signerParam.Key());
    }    
    ss << UrlEncodePath(resource, true) << "\n"; 

    // Canonical Query String + "\n"
    // UriEncode(<QueryParam1>) + "=" + UriEncode(<Value>) + "&" + UriEncode(<QueryParam2>) + "\n"
    ParameterCollection signedParameters;
    for (auto const &param : parameters) {
        signedParameters[UrlEncode(param.first)] = UrlEncode(param.second);
    }
    char separator = '&';
    bool isFirstParam = true;
    for (auto const &param : signedParameters) {
        if (!isFirstParam) {
            ss << separator;
        } else {
            isFirstParam = false;
        }

        ss << param.first;
        if (!param.second.empty()) {
            ss << "=" << param.second;
        }
    }
    ss << "\n";

    // Lowercase(<HeaderName1>) + ":" + Trim(<value>) + "\n" + Lowercase(<HeaderName2>) + ":" + Trim(<value>) + "\n" + "\n"
    for (const auto &header : httpRequest->Headers()) {
        std::string lowerKey = ToLower(header.first.c_str());
        std::string value = Trim(header.second.c_str());
        if (value.empty()) {
            continue;
        }
        if (lowerKey == "content-type" ||
            lowerKey == "content-md5" ||
            lowerKey.compare(0, 6, "x-oss-") == 0) {
            ss << lowerKey << ":" << value << "\n";
        } else if (additionalHeaders.find(lowerKey) != additionalHeaders.end()) {
            ss << lowerKey << ":" << value << "\n";
        }
    }
    ss << "\n";

    // Lowercase(<AdditionalHeaderName1>) + ";" + Lowercase(<AdditionalHeaderName2>) + "\n" +
    ss << toHeaderSetString(additionalHeaders);
    ss << "\n";
   
    // Hashed PayLoad
    std::string hash = "UNSIGNED-PAYLOAD";
    if (httpRequest->hasHeader("x-oss-content-sha256")) {
        hash = httpRequest->Header("x-oss-content-sha256");
    }
    ss << hash;

    return ss.str();
}