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 2017 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.parosproxy.paros.network;
21 
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.containsString;
24 import static org.hamcrest.Matchers.equalTo;
25 import static org.hamcrest.Matchers.is;
26 import static org.junit.jupiter.api.Assertions.assertFalse;
27 import static org.junit.jupiter.api.Assertions.assertThrows;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29 
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.params.ParameterizedTest;
32 import org.junit.jupiter.params.provider.ValueSource;
33 
34 /** Unit test for {@link HttpResponseHeader}. */
35 class HttpResponseHeaderUnitTest {
36 
37     @Test
shouldBeEmptyIfNoContents()38     void shouldBeEmptyIfNoContents() {
39         // Given
40         HttpResponseHeader header = new HttpResponseHeader();
41         // When
42         boolean empty = header.isEmpty();
43         // Then
44         assertThat(empty, is(equalTo(true)));
45     }
46 
47     @Test
shouldNotBeEmptyIfItHasStatusLine()48     void shouldNotBeEmptyIfItHasStatusLine() throws Exception {
49         // Given
50         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
51         // When
52         boolean empty = header.isEmpty();
53         // Then
54         assertThat(empty, is(equalTo(false)));
55     }
56 
57     @Test
shouldNotBeEmptyIfItHasStatusAndHeaders()58     void shouldNotBeEmptyIfItHasStatusAndHeaders() throws Exception {
59         // Given
60         HttpResponseHeader header =
61                 new HttpResponseHeader("HTTP/1.1 200 OK\r\nX-Header: value\r\n\r\n");
62         // When
63         boolean empty = header.isEmpty();
64         // Then
65         assertThat(empty, is(equalTo(false)));
66     }
67 
68     @Test
shouldSetValidStatusCode()69     void shouldSetValidStatusCode() throws Exception {
70         // Given
71         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
72         // When
73         header.setStatusCode(100);
74         // Then
75         assertThat(header.getStatusCode(), is(equalTo(100)));
76         assertThat(header.getPrimeHeader(), is(equalTo("HTTP/1.1 100 OK")));
77     }
78 
79     @Test
shouldFailToSetNegative3DigitStatusCode()80     void shouldFailToSetNegative3DigitStatusCode() throws Exception {
81         // Given
82         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
83         // When
84         IllegalArgumentException e =
85                 assertThrows(IllegalArgumentException.class, () -> header.setStatusCode(-200));
86         // Then
87         assertThat(e.getMessage(), containsString("positive"));
88     }
89 
90     @Test
shouldFailToSet2DigitStatusCode()91     void shouldFailToSet2DigitStatusCode() throws Exception {
92         // Given
93         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
94         // When
95         IllegalArgumentException e =
96                 assertThrows(IllegalArgumentException.class, () -> header.setStatusCode(99));
97         // Then
98         assertThat(e.getMessage(), containsString("3 digit number"));
99     }
100 
101     @Test
shouldFailToSet4DigitStatusCode()102     void shouldFailToSet4DigitStatusCode() throws Exception {
103         // Given
104         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
105         // When
106         IllegalArgumentException e =
107                 assertThrows(IllegalArgumentException.class, () -> header.setStatusCode(1000));
108         // Then
109         assertThat(e.getMessage(), containsString("3 digit number"));
110     }
111 
112     @Test
shouldSetReasonPhrase()113     void shouldSetReasonPhrase() throws Exception {
114         // Given
115         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
116         // When
117         header.setReasonPhrase("So So");
118         // Then
119         assertThat(header.getReasonPhrase(), is(equalTo("So So")));
120         assertThat(header.getPrimeHeader(), is(equalTo("HTTP/1.1 200 So So")));
121     }
122 
123     @Test
shouldSetEmptyReasonPhraseIfNull()124     void shouldSetEmptyReasonPhraseIfNull() throws Exception {
125         // Given
126         HttpResponseHeader header = new HttpResponseHeader("HTTP/1.1 200 OK\r\n\r\n");
127         // When
128         header.setReasonPhrase(null);
129         // Then
130         assertThat(header.getReasonPhrase(), is(equalTo("")));
131         assertThat(header.getPrimeHeader(), is(equalTo("HTTP/1.1 200")));
132     }
133 
134     @ParameterizedTest
135     @ValueSource(
136             strings = {
137                 "text/html", // Text but not css
138                 "image/png", // Not text or css
139                 "teXt/hTmL", // Mixed case
140                 "text/html; charset=UTF-8", // Expected charset
141                 "text/html;charset=UTF-8", // Charset without space
142                 "charset=UTF-8; text/html" // Charset first
143             })
isCssShouldReturnFalseWhenContentTypeDoesNotIndicateCss(String contentType)144     void isCssShouldReturnFalseWhenContentTypeDoesNotIndicateCss(String contentType) {
145         // Given
146         HttpResponseHeader hrh = createResponseHeader(contentType);
147         // When / Then
148         assertFalse(hrh.isCss());
149     }
150 
151     @ParameterizedTest
152     @ValueSource(
153             strings = {
154                 "text/css", // CSS
155                 "teXt/cSs", // Mixed case
156                 "text/css; charset=UTF-8", // Expected charset
157                 "text/css;charset=UTF-8", // Charset without space
158                 "charset=UTF-8; text/css" // Charset first
159             })
isCssShouldReturnTrueWhenContentTypeIndicatesCss(String contentType)160     void isCssShouldReturnTrueWhenContentTypeIndicatesCss(String contentType) {
161         // Given
162         HttpResponseHeader hrh = createResponseHeader(contentType);
163         // When / Then
164         assertTrue(hrh.isCss());
165     }
166 
createResponseHeader(String contentType)167     private static HttpResponseHeader createResponseHeader(String contentType) {
168         HttpResponseHeader hrh = new HttpResponseHeader();
169         hrh.setHeader(HttpHeader.CONTENT_TYPE, contentType);
170         return hrh;
171     }
172 }
173