1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.transport;
11
12 import static org.hamcrest.MatcherAssert.assertThat;
13
14 import java.io.File;
15 import java.io.IOException;
16 import java.net.HttpCookie;
17 import java.time.Instant;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.Date;
21 import java.util.LinkedHashMap;
22 import java.util.LinkedHashSet;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.eclipse.jgit.internal.transport.http.NetscapeCookieFile;
27 import org.eclipse.jgit.lib.Config;
28 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
29 import org.eclipse.jgit.transport.http.HttpConnection;
30 import org.eclipse.jgit.util.http.HttpCookiesMatcher;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.mockito.ArgumentMatchers;
35 import org.mockito.Mockito;
36
37 public class TransportHttpTest extends SampleDataRepositoryTestCase {
38 private URIish uri;
39 private File cookieFile;
40
41 @Override
42 @Before
43 public void setUp() throws Exception {
44 super.setUp();
45 uri = new URIish("https://everyones.loves.git/u/2");
46
47 final Config config = db.getConfig();
48 config.setBoolean("http", null, "saveCookies", true);
49 cookieFile = createTempFile();
50 config.setString("http", null, "cookieFile",
51 cookieFile.getAbsolutePath());
52 }
53
54 @Test
55 public void testMatchesCookieDomain() {
56 Assert.assertTrue(TransportHttp.matchesCookieDomain("example.com",
57 "example.com"));
58 Assert.assertTrue(TransportHttp.matchesCookieDomain("Example.Com",
59 "example.cOM"));
60 Assert.assertTrue(TransportHttp.matchesCookieDomain(
61 "some.subdomain.example.com", "example.com"));
62 Assert.assertFalse(TransportHttp
63 .matchesCookieDomain("someotherexample.com", "example.com"));
64 Assert.assertFalse(TransportHttp.matchesCookieDomain("example.com",
65 "example1.com"));
66 Assert.assertFalse(TransportHttp
67 .matchesCookieDomain("sub.sub.example.com", ".example.com"));
68 Assert.assertTrue(TransportHttp.matchesCookieDomain("host.example.com",
69 "example.com"));
70 Assert.assertTrue(TransportHttp.matchesCookieDomain(
71 "something.example.com", "something.example.com"));
72 Assert.assertTrue(TransportHttp.matchesCookieDomain(
73 "host.something.example.com", "something.example.com"));
74 }
75
76 @Test
77 public void testMatchesCookiePath() {
78 Assert.assertTrue(
79 TransportHttp.matchesCookiePath("/some/path", "/some/path"));
80 Assert.assertTrue(TransportHttp.matchesCookiePath("/some/path/child",
81 "/some/path"));
82 Assert.assertTrue(TransportHttp.matchesCookiePath("/some/path/child",
83 "/some/path/"));
84 Assert.assertFalse(TransportHttp.matchesCookiePath("/some/pathother",
85 "/some/path"));
86 Assert.assertFalse(
87 TransportHttp.matchesCookiePath("otherpath", "/some/path"));
88 }
89
90 @Test
91 public void testProcessResponseCookies() throws IOException {
92 HttpConnection connection = Mockito.mock(HttpConnection.class);
93 Mockito.when(
94 connection.getHeaderFields(ArgumentMatchers.eq("Set-Cookie")))
95 .thenReturn(Arrays.asList(
96 "id=a3fWa; Expires=Fri, 01 Jan 2100 11:00:00 GMT; Secure; HttpOnly",
97 "sessionid=38afes7a8; HttpOnly; Path=/"));
98 Mockito.when(
99 connection.getHeaderFields(ArgumentMatchers.eq("Set-Cookie2")))
100 .thenReturn(Collections
101 .singletonList("cookie2=some value; Max-Age=1234; Path=/"));
102
103 try (TransportHttp transportHttp = new TransportHttp(db, uri)) {
104 Date creationDate = new Date();
105 transportHttp.processResponseCookies(connection);
106
107
108 Set<HttpCookie> expectedCookies = new LinkedHashSet<>();
109
110 HttpCookie cookie = new HttpCookie("id", "a3fWa");
111 cookie.setDomain("everyones.loves.git");
112 cookie.setPath("/u/2/");
113
114 cookie.setMaxAge(
115 (Instant.parse("2100-01-01T11:00:00.000Z").toEpochMilli()
116 - creationDate.getTime()) / 1000);
117 cookie.setSecure(true);
118 cookie.setHttpOnly(true);
119 expectedCookies.add(cookie);
120
121 cookie = new HttpCookie("cookie2", "some value");
122 cookie.setDomain("everyones.loves.git");
123 cookie.setPath("/");
124 cookie.setMaxAge(1234);
125 expectedCookies.add(cookie);
126
127 assertThat(
128 new NetscapeCookieFile(cookieFile.toPath())
129 .getCookies(true),
130 HttpCookiesMatcher.containsInOrder(expectedCookies, 5));
131 }
132 }
133
134 @Test
135 public void testProcessResponseCookiesNotPersistingWithSaveCookiesFalse()
136 throws IOException {
137 HttpConnection connection = Mockito.mock(HttpConnection.class);
138 Mockito.when(
139 connection.getHeaderFields(ArgumentMatchers.eq("Set-Cookie")))
140 .thenReturn(Arrays.asList(
141 "id=a3fWa; Expires=Thu, 21 Oct 2100 11:00:00 GMT; Secure; HttpOnly",
142 "sessionid=38afes7a8; HttpOnly; Path=/"));
143 Mockito.when(
144 connection.getHeaderFields(ArgumentMatchers.eq("Set-Cookie2")))
145 .thenReturn(Collections.singletonList(
146 "cookie2=some value; Max-Age=1234; Path=/"));
147
148
149 final Config config = db.getConfig();
150 config.setBoolean("http", null, "saveCookies", false);
151
152 try (TransportHttp transportHttp = new TransportHttp(db, uri)) {
153 transportHttp.processResponseCookies(connection);
154
155
156 Assert.assertFalse("Cookie file was not supposed to be written!",
157 cookieFile.exists());
158 }
159 }
160
161 private void assertHeaders(String expected, String... headersToAdd) {
162 HttpConnection fake = Mockito.mock(HttpConnection.class);
163 Map<String, String> headers = new LinkedHashMap<>();
164 Mockito.doAnswer(invocation -> {
165 Object[] args = invocation.getArguments();
166 headers.put(args[0].toString(), args[1].toString());
167 return null;
168 }).when(fake).setRequestProperty(ArgumentMatchers.anyString(),
169 ArgumentMatchers.anyString());
170 TransportHttp.addHeaders(fake, Arrays.asList(headersToAdd));
171 Assert.assertEquals(expected, headers.toString());
172 }
173
174 @Test
175 public void testAddHeaders() {
176 assertHeaders("{a=b, c=d}", "a: b", "c :d");
177 }
178
179 @Test
180 public void testAddHeaderEmptyValue() {
181 assertHeaders("{a-x=b, c=, d=e}", "a-x: b", "c:", "d:e");
182 }
183
184 @Test
185 public void testSkipHeaderWithEmptyKey() {
186 assertHeaders("{a=b, c=d}", "a: b", " : x", "c :d");
187 assertHeaders("{a=b, c=d}", "a: b", ": x", "c :d");
188 }
189
190 @Test
191 public void testSkipHeaderWithoutKey() {
192 assertHeaders("{a=b, c=d}", "a: b", "x", "c :d");
193 }
194
195 @Test
196 public void testSkipHeaderWithInvalidKey() {
197 assertHeaders("{a=b, c=d}", "a: b", "q/p: x", "c :d");
198 assertHeaders("{a=b, c=d}", "a: b", "ä: x", "c :d");
199 }
200
201 @Test
202 public void testSkipHeaderWithNonAsciiValue() {
203 assertHeaders("{a=b, c=d}", "a: b", "q/p: x", "c :d");
204 assertHeaders("{a=b, c=d}", "a: b", "x: ä", "c :d");
205 }
206 }