All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.auth.signer.internal.util.HeaderTransformsHelper Maven / Gradle / Ivy

Go to download

The AWS SDK for Java - Auth module holds the classes that are used for authentication with services

There is a newer version: 2.29.15
Show newest version
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package software.amazon.awssdk.auth.signer.internal.util;

import static software.amazon.awssdk.utils.StringUtils.lowerCase;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import software.amazon.awssdk.annotations.SdkInternalApi;

/**
 * Helper class for transforming headers required during signing of headers.
 */
@SdkInternalApi
public final class HeaderTransformsHelper {

    private static final List LIST_OF_HEADERS_TO_IGNORE_IN_LOWER_CASE =
            Arrays.asList("connection", "x-amzn-trace-id", "user-agent", "expect");

    private HeaderTransformsHelper() {
    }

    public static Map> canonicalizeSigningHeaders(Map> headers) {
        Map> result = new TreeMap<>();

        for (Map.Entry> header : headers.entrySet()) {
            String lowerCaseHeader = lowerCase(header.getKey());
            if (LIST_OF_HEADERS_TO_IGNORE_IN_LOWER_CASE.contains(lowerCaseHeader)) {
                continue;
            }

            result.computeIfAbsent(lowerCaseHeader, x -> new ArrayList<>()).addAll(header.getValue());
        }
        return result;
    }

    /**
     * "The Trimall function removes excess white space before and after values,
     * and converts sequential spaces to a single space."
     * 

* https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html *

* The collapse-whitespace logic is equivalent to: *

     *     value.replaceAll("\\s+", " ")
     * 
* but does not create a Pattern object that needs to compile the match * string; it also prevents us from having to make a Matcher object as well. */ public static String trimAll(String value) { boolean previousIsWhiteSpace = false; StringBuilder sb = new StringBuilder(value.length()); for (int i = 0; i < value.length(); i++) { char ch = value.charAt(i); if (isWhiteSpace(ch)) { if (previousIsWhiteSpace) { continue; } sb.append(' '); previousIsWhiteSpace = true; } else { sb.append(ch); previousIsWhiteSpace = false; } } return sb.toString().trim(); } private static List trimAll(List values) { return values.stream().map(HeaderTransformsHelper::trimAll).collect(Collectors.toList()); } /** * Tests a char to see if is it whitespace. * This method considers the same characters to be white * space as the Pattern class does when matching \s * * @param ch the character to be tested * @return true if the character is white space, false otherwise. */ private static boolean isWhiteSpace(final char ch) { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\u000b' || ch == '\r' || ch == '\f'; } public static String getCanonicalizedHeaderString(Map> canonicalizedHeaders) { StringBuilder buffer = new StringBuilder(); canonicalizedHeaders.forEach((headerName, headerValues) -> { buffer.append(headerName); buffer.append(":"); buffer.append(String.join(",", trimAll(headerValues))); buffer.append("\n"); }); return buffer.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy