/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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 io.restassured.config;
import java.util.HashMap;
import java.util.Map;
import static io.restassured.internal.assertion.AssertParameter.notNull;
/**
* Allow you to configure settings for headers.
*/
public class HeaderConfig implements Config {
private static final String ACCEPT_HEADER_NAME = "accept";
private static final String CONTENT_TYPE_HEADER_NAME = "content-type";
private final Map<String, Boolean> headersToOverwrite;
private final boolean isUserDefined;
/**
* Create a new instance of {@link HeaderConfig}.
*/
public HeaderConfig() {
this(newHashMapReturningFalseByDefault(CONTENT_TYPE_HEADER_NAME, ACCEPT_HEADER_NAME), false);
}
private HeaderConfig(Map<String, Boolean> headersToOverwrite, boolean isUserDefined) {
this.headersToOverwrite = headersToOverwrite;
this.isUserDefined = isUserDefined;
}
/**
* Define headers that should be overwritten instead of merged adding headers or using request specifications. Note that
* by default all headers are merged except the {@value #ACCEPT_HEADER_NAME} and {@value #CONTENT_TYPE_HEADER_NAME} headers.
* For example, if the header with name <code>header1</code> is <i>not</i> marked as overwritable (default) and you do the following:
* <pre>
* given().header("header1", "value1").header("header1, "value2"). ..
* </pre>
* <p/>
* Then <code>header1</code> will be sent twice in the request:
* <pre>
* header1: value1
* header1: value2
* </pre>
* <p/>
* If you configure <code>header1</code> to be overwritable by doing:
* <pre>
* given().
* config(RestAssured.config().headerConfig(headerConfig().overwriteHeadersWithName("header1")).
* header("header1", "value1").
* header("header1", "value2").
* ...
* </pre>
* then <code>header1</code> will only be sent once:
* <pre>
* header1: value2
* </pre>
*
* @param headerName The header name to overwrite.
* @param additionalHeaderNames Additional header names to overwrite (optional).
* @return A new instance of {@link HeaderConfig}.
*/
public HeaderConfig overwriteHeadersWithName(String headerName, String... additionalHeaderNames) {
notNull(headerName, "Header name");
Map<String, Boolean> map = newHashMapReturningFalseByDefault(headerName);
if (additionalHeaderNames != null && additionalHeaderNames.length > 0) {
for (String additionalHeaderName : additionalHeaderNames) {
map.put(additionalHeaderName.toUpperCase(), true);
}
}
return new HeaderConfig(map, true);
}
/**
* Define headers that should be be merged instead of overwritten when adding headers or using request specifications. Note that
* by default all headers are merged except the {@value #ACCEPT_HEADER_NAME} and {@value #CONTENT_TYPE_HEADER_NAME} headers.
* This method is thus mainly used to change to merge behavior for headers that by default are overwritten or the revert
* changes of a request specification merge.
*
* @param headerName The header name to merge.
* @param additionalHeaderNames Additional header names to merge (optional).
* @return A new instance of {@link HeaderConfig}.
*/
public HeaderConfig mergeHeadersWithName(String headerName, String... additionalHeaderNames) {
notNull(headerName, "Header name");
Map<String, Boolean> map = newHashMapReturningFalseByDefault();
map.put(headerName, false);
if (additionalHeaderNames != null && additionalHeaderNames.length > 0) {
for (String additionalHeaderName : additionalHeaderNames) {
map.put(additionalHeaderName.toUpperCase(), false);
}
}
return new HeaderConfig(map, true);
}
/**
* Returns whether or not the specified header should be returned
*
* @param headerName The header name to check.
* @return <code>true</code> if header should be overwritten, <code>false</code> otherwise.
*/
public boolean shouldOverwriteHeaderWithName(String headerName) {
notNull(headerName, "Header name");
return headersToOverwrite.get(headerName.toUpperCase());
}
/**
* Syntactic sugar, same as calling <code>new {@link HeaderConfig#HeaderConfig()}</code>.
*
* @return a new instance of {@link HeaderConfig}.
*/
public static HeaderConfig headerConfig() {
return new HeaderConfig();
}
private static Map<String, Boolean> newHashMapReturningFalseByDefault(final String... headerNamesToOverwrite) {
return new HashMap<String, Boolean>() {
{
for (String headerName : headerNamesToOverwrite) {
put(headerName.toUpperCase(), true);
}
}
@Override
public Boolean get(Object key) {
Boolean aBoolean = super.get(key);
if (aBoolean == null) {
return Boolean.FALSE;
}
return aBoolean;
}
};
}
public boolean isUserConfigured() {
return isUserDefined;
}
}