1 /*
2  * Zed Attack Proxy (ZAP) and its related class files.
3  *
4  * ZAP is an HTTP/HTTPS proxy for assessing web application security.
5  *
6  * Copyright 2016 The ZAP Development Team
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.apache.commons.httpclient;
21 
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.arrayContaining;
24 import static org.hamcrest.Matchers.hasSize;
25 import static org.hamcrest.Matchers.is;
26 import static org.junit.jupiter.params.provider.Arguments.arguments;
27 import static org.mockito.BDDMockito.given;
28 import static org.mockito.Mockito.mock;
29 
30 import java.util.List;
31 import java.util.stream.Stream;
32 import org.apache.commons.httpclient.protocol.Protocol;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.params.ParameterizedTest;
35 import org.junit.jupiter.params.provider.Arguments;
36 import org.junit.jupiter.params.provider.MethodSource;
37 
38 class HttpMethodBaseUnitTest {
39 
40     private static final Header EXPECTED_HOST_HEADER = header("Host", "example.com");
41 
42     @ParameterizedTest
43     @MethodSource("cookieHeaderProvider")
testParseCookieHeader(String cookieHeaderValue, int numberOfCookies)44     void testParseCookieHeader(String cookieHeaderValue, int numberOfCookies) {
45         List<Cookie> cookies = HttpMethodBase.parseCookieHeader("example.com", cookieHeaderValue);
46         assertThat(cookies, hasSize(numberOfCookies));
47     }
48 
cookieHeaderProvider()49     static Stream<Arguments> cookieHeaderProvider() {
50         return Stream.of(
51                 arguments("", 0),
52                 arguments("JSESSIONID=5DFA94B903A0063839E0440118808875", 1),
53                 arguments("has_js=1;JSESSIONID=5DFA94B903A0063839E0440118808875", 2),
54                 arguments("has_js=1; JSESSIONID=5DFA94B903A0063839E0440118808875", 2),
55                 arguments("has_js=;JSESSIONID=5DFA94B903A0063839E0440118808875", 2));
56     }
57 
58     @Test
shouldAddHostHeaderIfNotPresent()59     void shouldAddHostHeaderIfNotPresent() throws Exception {
60         // Given
61         HttpMethodBase methodBase = new TestHttpMethodBase();
62         Header headerA = header("A", "Value A");
63         methodBase.addRequestHeader(headerA);
64         HttpConnection conn = connection("example.com", 443);
65         // When
66         methodBase.addHostRequestHeader(null, conn);
67         // Then
68         assertThat(
69                 methodBase.getRequestHeaders(), is(arrayContaining(headerA, EXPECTED_HOST_HEADER)));
70     }
71 
72     @Test
shouldKeepHostHeaderIfValueMatch()73     void shouldKeepHostHeaderIfValueMatch() throws Exception {
74         // Given
75         HttpMethodBase methodBase = new TestHttpMethodBase();
76         Header hostHeader = header("Host", "example.com");
77         methodBase.addRequestHeader(hostHeader);
78         Header headerA = header("A", "Value A");
79         methodBase.addRequestHeader(headerA);
80         HttpConnection conn = connection("example.com", 443);
81         // When
82         methodBase.addHostRequestHeader(null, conn);
83         // Then
84         assertThat(
85                 methodBase.getRequestHeaders(), is(arrayContaining(EXPECTED_HOST_HEADER, headerA)));
86     }
87 
88     @Test
shouldUpdateHostHeaderIfValueMismatch()89     void shouldUpdateHostHeaderIfValueMismatch() throws Exception {
90         // Given
91         HttpMethodBase methodBase = new TestHttpMethodBase();
92         methodBase.addRequestHeader(header("Host", "example2.com"));
93         HttpConnection conn = connection("example.com", 443);
94         // When
95         methodBase.addHostRequestHeader(null, conn);
96         // Then
97         assertThat(methodBase.getRequestHeaders(), is(arrayContaining(EXPECTED_HOST_HEADER)));
98     }
99 
100     @Test
shouldUpdateHostHeaderInPlace()101     void shouldUpdateHostHeaderInPlace() throws Exception {
102         // Given
103         HttpMethodBase methodBase = new TestHttpMethodBase();
104         Header headerA = header("A", "Value A");
105         methodBase.addRequestHeader(headerA);
106         Header hostHeader = header("Host", "example2.com");
107         methodBase.addRequestHeader(hostHeader);
108         Header headerB = header("B", "Value B");
109         methodBase.addRequestHeader(headerB);
110         HttpConnection conn = connection("example.com", 443);
111         // When
112         methodBase.addHostRequestHeader(null, conn);
113         // Then
114         assertThat(
115                 methodBase.getRequestHeaders(),
116                 is(arrayContaining(headerA, EXPECTED_HOST_HEADER, headerB)));
117     }
118 
119     @Test
shouldKeepOnlyOneHostHeader()120     void shouldKeepOnlyOneHostHeader() throws Exception {
121         // Given
122         HttpMethodBase methodBase = new TestHttpMethodBase();
123         Header headerA = header("A", "Value A");
124         methodBase.addRequestHeader(headerA);
125         Header hostHeader1 = header("Host", "example.com");
126         methodBase.addRequestHeader(hostHeader1);
127         Header headerB = header("B", "Value B");
128         methodBase.addRequestHeader(headerB);
129         Header headerHost2 = header("Host", "Should Remove 1");
130         methodBase.addRequestHeader(headerHost2);
131         Header headerHost3 = header("Host", "Should Remove 2");
132         methodBase.addRequestHeader(headerHost3);
133         HttpConnection conn = connection("example.com", 443);
134         // When
135         methodBase.addHostRequestHeader(null, conn);
136         // Then
137         assertThat(
138                 methodBase.getRequestHeaders(),
139                 is(arrayContaining(headerA, EXPECTED_HOST_HEADER, headerB)));
140     }
141 
142     @Test
shouldUpdateAndKeepOnlyOneHostHeader()143     void shouldUpdateAndKeepOnlyOneHostHeader() throws Exception {
144         // Given
145         HttpMethodBase methodBase = new TestHttpMethodBase();
146         Header headerA = header("A", "Value A");
147         methodBase.addRequestHeader(headerA);
148         Header hostHeader1 = header("Host", "example2.com");
149         methodBase.addRequestHeader(hostHeader1);
150         Header headerB = header("B", "Value B");
151         methodBase.addRequestHeader(headerB);
152         Header headerHost2 = header("Host", "Should Remove 1");
153         methodBase.addRequestHeader(headerHost2);
154         Header headerHost3 = header("Host", "Should Remove 2");
155         methodBase.addRequestHeader(headerHost3);
156         HttpConnection conn = connection("example.com", 443);
157         // When
158         methodBase.addHostRequestHeader(null, conn);
159         // Then
160         assertThat(
161                 methodBase.getRequestHeaders(),
162                 is(arrayContaining(headerA, EXPECTED_HOST_HEADER, headerB)));
163     }
164 
connection(String host, int port)165     private static HttpConnection connection(String host, int port) {
166         HttpConnection connection = mock(HttpConnection.class);
167         given(connection.getHost()).willReturn(host);
168         given(connection.getPort()).willReturn(port);
169         Protocol protocol = mock(Protocol.class);
170         given(protocol.getDefaultPort()).willReturn(port);
171         given(connection.getProtocol()).willReturn(protocol);
172         return connection;
173     }
174 
header(String name, String value)175     private static Header header(String name, String value) {
176         return new Header(name, value);
177     }
178 
179     private static class TestHttpMethodBase extends HttpMethodBase {
180 
181         @Override
getName()182         public String getName() {
183             return "TEST";
184         }
185     }
186 }
187