/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.cxf.transport.http; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.servlet.http.HttpServletRequest; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.easymock.EasyMock; import org.easymock.IMocksControl; import org.junit.Assert; import org.junit.Test; /** * */ public class HeadersTest extends Assert { @Test public void setHeadersTest() throws Exception { IMocksControl control = EasyMock.createNiceControl(); String[] headerNames = {"Content-Type", "authorization", "soapAction"}; String[] headerValues = {"text/xml", "Basic Zm9vOmJhcg==", "foo"}; Map<String, List<String>> inmap = new HashMap<>(); for (int i = 0; i < headerNames.length; i++) { inmap.put(headerNames[i], Arrays.asList(headerValues[i])); } HttpServletRequest req = control.createMock(HttpServletRequest.class); EasyMock.expect(req.getHeaderNames()).andReturn(Collections.enumeration(inmap.keySet())); for (int i = 0; i < headerNames.length; i++) { EasyMock.expect(req.getHeaders(headerNames[i])). andReturn(Collections.enumeration(inmap.get(headerNames[i]))); } EasyMock.expect(req.getContentType()).andReturn(headerValues[0]).anyTimes(); control.replay(); Message message = new MessageImpl(); message.put(AbstractHTTPDestination.HTTP_REQUEST, req); Headers headers = new Headers(message); headers.copyFromRequest(req); Map<String, List<String>> protocolHeaders = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS)); assertTrue("unexpected size", protocolHeaders.size() == headerNames.length); assertEquals("unexpected header", protocolHeaders.get("Content-Type").get(0), headerValues[0]); assertEquals("unexpected header", protocolHeaders.get("content-type").get(0), headerValues[0]); assertEquals("unexpected header", protocolHeaders.get("CONTENT-TYPE").get(0), headerValues[0]); assertEquals("unexpected header", protocolHeaders.get("content-TYPE").get(0), headerValues[0]); assertEquals("unexpected header", protocolHeaders.get("Authorization").get(0), headerValues[1]); assertEquals("unexpected header", protocolHeaders.get("authorization").get(0), headerValues[1]); assertEquals("unexpected header", protocolHeaders.get("AUTHORIZATION").get(0), headerValues[1]); assertEquals("unexpected header", protocolHeaders.get("authoriZATION").get(0), headerValues[1]); assertEquals("unexpected header", protocolHeaders.get("SOAPAction").get(0), headerValues[2]); assertEquals("unexpected header", protocolHeaders.get("soapaction").get(0), headerValues[2]); assertEquals("unexpected header", protocolHeaders.get("SOAPACTION").get(0), headerValues[2]); assertEquals("unexpected header", protocolHeaders.get("soapAction").get(0), headerValues[2]); control.verify(); } @Test public void sensitiveHeadersTest() { Map<String, List<String>> headerMap = new HashMap<>(); headerMap.put("Authorization", Arrays.asList("FAIL")); headerMap.put("Proxy-Authorization", Arrays.asList("FAIL")); headerMap.put("Content-Type", Arrays.asList("application/xml")); headerMap.put("Accept", Arrays.asList("text/plain")); String loggedString = Headers.toString(headerMap, false); assertFalse("The value of a sensitive header could be logged: " + loggedString, loggedString.contains("FAIL")); assertTrue("The value of a non-sensitive header would not be logged: " + loggedString, loggedString.contains("application/xml") && loggedString.contains("text/plain")); assertTrue("Expected header keys were not logged: " + loggedString, loggedString.contains("Authorization") && loggedString.contains("Proxy-Authorization") && loggedString.contains("Accept") && loggedString.contains("Content-Type")); } @Test public void logProtocolHeadersTest() { Map<String, List<String>> headerMap = new HashMap<>(); headerMap.put("Normal-Header", Arrays.asList("normal")); headerMap.put("Multivalue-Header", Arrays.asList("first", "second")); headerMap.put("Authorization", Arrays.asList("myPassword")); headerMap.put("Null-Header", Arrays.asList((String)null)); //Set up test logger Logger logger = Logger.getAnonymousLogger(); // remove all "normal" handlers and just use our custom handler for testing logger.setUseParentHandlers(false); logger.setLevel(Level.INFO); for (Handler h : logger.getHandlers()) { logger.removeHandler(h); } logger.addHandler(new Handler() { @Override public void publish(LogRecord record) { String msg = record.getMessage(); if (msg.startsWith("Normal-Header")) { assertTrue("Unexpected output for normal header - expected Normal-Header: normal, received " + msg, "Normal-Header: normal".equals(msg)); } else if (msg.startsWith("Multivalue-Header")) { assertTrue("Unexpected output for multi-value header - expected Multivalue-Header: first or " + "Multivalue-Header: second, received: " + msg, "Multivalue-Header: first".equals(msg) || "Multivalue-Header: second".equals(msg)); } else if (msg.startsWith("Authorization")) { assertTrue("Unexpected output for sensitive header - expected Authorization: ***, received " + msg, "Authorization: ***".equals(msg)); } else if (msg.startsWith("Null-Header")) { assertTrue("Unexpected output for null header - expected Null-Header: <null>, received " + msg, "Null-Header: <null>".equals(msg)); } else { fail("Unexpected header logged: " + msg); } } @Override public void flush() { // no-op } @Override public void close() throws SecurityException { // no-op } }); Headers.logProtocolHeaders(logger, Level.INFO, headerMap, false); } @Test public void nullContentTypeTest() { IMocksControl control = EasyMock.createNiceControl(); Message message = new MessageImpl(); // first check - content-type==null in message, nothing specified in request // expect that determineContentType will return the default value of text/xml message.put(Message.CONTENT_TYPE, null); Headers headers = new Headers(message); assertEquals("Unexpected content-type determined - expected text/xml", "text/xml", headers.determineContentType()); // second check - null specified in request, valid content-type specified in message // expect that determineContentType returns the content-type specified in the message HttpServletRequest req = control.createMock(HttpServletRequest.class); EasyMock.expect(req.getHeaderNames()).andReturn(Collections.emptyEnumeration()); EasyMock.expect(req.getContentType()).andReturn(null).anyTimes(); control.replay(); message = new MessageImpl(); message.put(Message.CONTENT_TYPE, "application/json"); headers = new Headers(message); headers.copyFromRequest(req); assertEquals("Unexpected content-type determined - expected application/json", "application/json", headers.determineContentType()); control.verify(); // third check - content-type==null in message, null in request // expect that determineContentType returns the default value of text/xml control = EasyMock.createNiceControl(); req = control.createMock(HttpServletRequest.class); EasyMock.expect(req.getHeaderNames()).andReturn(Collections.emptyEnumeration()); EasyMock.expect(req.getContentType()).andReturn(null).anyTimes(); control.replay(); message = new MessageImpl(); message.put(Message.CONTENT_TYPE, null); headers = new Headers(message); headers.copyFromRequest(req); assertEquals("Unexpected content-type determined - expected text/xml", "text/xml", headers.determineContentType()); control.verify(); } }