1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.transport.http;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.net.ConnectException;
24 import java.net.ServerSocket;
25 import java.net.SocketTimeoutException;
26 import java.net.URI;
27 import java.nio.charset.StandardCharsets;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.concurrent.atomic.AtomicReference;
31
32 import org.apache.http.NoHttpResponseException;
33 import org.apache.http.client.HttpResponseException;
34 import org.apache.http.conn.ConnectTimeoutException;
35 import org.apache.http.pool.ConnPoolControl;
36 import org.apache.http.pool.PoolStats;
37 import org.eclipse.aether.ConfigurationProperties;
38 import org.eclipse.aether.DefaultRepositoryCache;
39 import org.eclipse.aether.DefaultRepositorySystemSession;
40 import org.eclipse.aether.internal.test.util.TestFileUtils;
41 import org.eclipse.aether.internal.test.util.TestUtils;
42 import org.eclipse.aether.repository.Authentication;
43 import org.eclipse.aether.repository.Proxy;
44 import org.eclipse.aether.repository.RemoteRepository;
45 import org.eclipse.aether.spi.connector.transport.GetTask;
46 import org.eclipse.aether.spi.connector.transport.PeekTask;
47 import org.eclipse.aether.spi.connector.transport.PutTask;
48 import org.eclipse.aether.spi.connector.transport.Transporter;
49 import org.eclipse.aether.spi.connector.transport.TransporterFactory;
50 import org.eclipse.aether.transfer.NoTransporterException;
51 import org.eclipse.aether.transfer.TransferCancelledException;
52 import org.eclipse.aether.util.repository.AuthenticationBuilder;
53 import org.junit.jupiter.api.AfterEach;
54 import org.junit.jupiter.api.BeforeEach;
55 import org.junit.jupiter.api.Test;
56 import org.junit.jupiter.api.TestInfo;
57 import org.junit.jupiter.api.Timeout;
58
59 import static org.junit.jupiter.api.Assertions.*;
60
61
62
63 public class HttpTransporterTest {
64
65 static {
66 System.setProperty(
67 "javax.net.ssl.trustStore", new File("src/test/resources/ssl/server-store").getAbsolutePath());
68 System.setProperty("javax.net.ssl.trustStorePassword", "server-pwd");
69 System.setProperty("javax.net.ssl.keyStore", new File("src/test/resources/ssl/client-store").getAbsolutePath());
70 System.setProperty("javax.net.ssl.keyStorePassword", "client-pwd");
71 }
72
73 private DefaultRepositorySystemSession session;
74
75 private TransporterFactory factory;
76
77 private Transporter transporter;
78
79 private File repoDir;
80
81 private HttpServer httpServer;
82
83 private Authentication auth;
84
85 private Proxy proxy;
86
87 private RemoteRepository newRepo(String url) {
88 return new RemoteRepository.Builder("test", "default", url)
89 .setAuthentication(auth)
90 .setProxy(proxy)
91 .build();
92 }
93
94 private void newTransporter(String url) throws Exception {
95 if (transporter != null) {
96 transporter.close();
97 transporter = null;
98 }
99 transporter = factory.newInstance(session, newRepo(url));
100 }
101
102 private static final long OLD_FILE_TIMESTAMP = 160660800000L;
103
104 @BeforeEach
105 void setUp(TestInfo testInfo) throws Exception {
106 System.out.println("=== " + testInfo.getDisplayName() + " ===");
107 session = TestUtils.newSession();
108 HashMap<String, ChecksumExtractor> extractors = new HashMap<>();
109 extractors.put(XChecksumChecksumExtractor.NAME, new XChecksumChecksumExtractor());
110 extractors.put(Nexus2ChecksumExtractor.NAME, new Nexus2ChecksumExtractor());
111 factory = new HttpTransporterFactory(extractors);
112 repoDir = TestFileUtils.createTempDir();
113 TestFileUtils.writeString(new File(repoDir, "file.txt"), "test");
114 TestFileUtils.writeString(new File(repoDir, "dir/file.txt"), "test");
115 TestFileUtils.writeString(new File(repoDir, "dir/oldFile.txt"), "oldTest", OLD_FILE_TIMESTAMP);
116 TestFileUtils.writeString(new File(repoDir, "empty.txt"), "");
117 TestFileUtils.writeString(new File(repoDir, "some space.txt"), "space");
118 File resumable = new File(repoDir, "resume.txt");
119 TestFileUtils.writeString(resumable, "resumable");
120 resumable.setLastModified(System.currentTimeMillis() - 90 * 1000);
121 httpServer = new HttpServer().setRepoDir(repoDir).start();
122 newTransporter(httpServer.getHttpUrl());
123 }
124
125 @AfterEach
126 void tearDown() throws Exception {
127 if (transporter != null) {
128 transporter.close();
129 transporter = null;
130 }
131 if (httpServer != null) {
132 httpServer.stop();
133 httpServer = null;
134 }
135 factory = null;
136 session = null;
137 }
138
139 @Test
140 void testClassify() {
141 assertEquals(Transporter.ERROR_OTHER, transporter.classify(new FileNotFoundException()));
142 assertEquals(Transporter.ERROR_OTHER, transporter.classify(new HttpResponseException(403, "Forbidden")));
143 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(new HttpResponseException(404, "Not Found")));
144 }
145
146 @Test
147 void testPeek() throws Exception {
148 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
149 }
150
151 @Test
152 void testRetryHandler_defaultCount_positive() throws Exception {
153 httpServer.setConnectionsToClose(3);
154 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
155 }
156
157 @Test
158 void testRetryHandler_defaultCount_negative() throws Exception {
159 httpServer.setConnectionsToClose(4);
160 try {
161 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
162 fail("Expected error");
163 } catch (NoHttpResponseException expected) {
164 }
165 }
166
167 @Test
168 void testRetryHandler_explicitCount_positive() throws Exception {
169 session.setConfigProperty(ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT, 10);
170 newTransporter(httpServer.getHttpUrl());
171 httpServer.setConnectionsToClose(10);
172 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
173 }
174
175 @Test
176 void testRetryHandler_disabled() throws Exception {
177 session.setConfigProperty(ConfigurationProperties.HTTP_RETRY_HANDLER_COUNT, 0);
178 newTransporter(httpServer.getHttpUrl());
179 httpServer.setConnectionsToClose(1);
180 try {
181 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
182 } catch (NoHttpResponseException expected) {
183 }
184 }
185
186 @Test
187 void testPeek_NotFound() throws Exception {
188 try {
189 transporter.peek(new PeekTask(URI.create("repo/missing.txt")));
190 fail("Expected error");
191 } catch (HttpResponseException e) {
192 assertEquals(404, e.getStatusCode());
193 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
194 }
195 }
196
197 @Test
198 void testPeek_Closed() throws Exception {
199 transporter.close();
200 try {
201 transporter.peek(new PeekTask(URI.create("repo/missing.txt")));
202 fail("Expected error");
203 } catch (IllegalStateException e) {
204 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
205 }
206 }
207
208 @Test
209 void testPeek_Authenticated() throws Exception {
210 httpServer.setAuthentication("testuser", "testpass");
211 auth = new AuthenticationBuilder()
212 .addUsername("testuser")
213 .addPassword("testpass")
214 .build();
215 newTransporter(httpServer.getHttpUrl());
216 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
217 }
218
219 @Test
220 void testPeek_Unauthenticated() throws Exception {
221 httpServer.setAuthentication("testuser", "testpass");
222 try {
223 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
224 fail("Expected error");
225 } catch (HttpResponseException e) {
226 assertEquals(401, e.getStatusCode());
227 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
228 }
229 }
230
231 @Test
232 void testPeek_ProxyAuthenticated() throws Exception {
233 httpServer.setProxyAuthentication("testuser", "testpass");
234 auth = new AuthenticationBuilder()
235 .addUsername("testuser")
236 .addPassword("testpass")
237 .build();
238 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
239 newTransporter("http://bad.localhost:1/");
240 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
241 }
242
243 @Test
244 void testPeek_ProxyUnauthenticated() throws Exception {
245 httpServer.setProxyAuthentication("testuser", "testpass");
246 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
247 newTransporter("http://bad.localhost:1/");
248 try {
249 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
250 fail("Expected error");
251 } catch (HttpResponseException e) {
252 assertEquals(407, e.getStatusCode());
253 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
254 }
255 }
256
257 @Test
258 void testPeek_SSL() throws Exception {
259 httpServer.addSslConnector();
260 newTransporter(httpServer.getHttpsUrl());
261 transporter.peek(new PeekTask(URI.create("repo/file.txt")));
262 }
263
264 @Test
265 void testPeek_Redirect() throws Exception {
266 httpServer.addSslConnector();
267 transporter.peek(new PeekTask(URI.create("redirect/file.txt")));
268 transporter.peek(new PeekTask(URI.create("redirect/file.txt?scheme=https")));
269 }
270
271 @Test
272 void testGet_ToMemory() throws Exception {
273 RecordingTransportListener listener = new RecordingTransportListener();
274 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
275 transporter.get(task);
276 assertEquals("test", task.getDataString());
277 assertEquals(0L, listener.dataOffset);
278 assertEquals(4L, listener.dataLength);
279 assertEquals(1, listener.startedCount);
280 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
281 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
282 }
283
284 @Test
285 void testGet_ToFile() throws Exception {
286 File file = TestFileUtils.createTempFile("failure");
287 RecordingTransportListener listener = new RecordingTransportListener();
288 GetTask task =
289 new GetTask(URI.create("repo/file.txt")).setDataFile(file).setListener(listener);
290 transporter.get(task);
291 assertEquals("test", TestFileUtils.readString(file));
292 assertEquals(0L, listener.dataOffset);
293 assertEquals(4L, listener.dataLength);
294 assertEquals(1, listener.startedCount);
295 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
296 assertEquals("test", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
297 }
298
299 @Test
300 void testGet_ToFileTimestamp() throws Exception {
301 File file = TestFileUtils.createTempFile("failure");
302 RecordingTransportListener listener = new RecordingTransportListener();
303 GetTask task = new GetTask(URI.create("repo/dir/oldFile.txt"))
304 .setDataFile(file)
305 .setListener(listener);
306 transporter.get(task);
307 assertEquals("oldTest", TestFileUtils.readString(file));
308 assertEquals(0L, listener.dataOffset);
309 assertEquals(7L, listener.dataLength);
310 assertEquals(1, listener.startedCount);
311 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
312 assertEquals("oldTest", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
313 assertEquals(file.lastModified(), OLD_FILE_TIMESTAMP);
314 }
315
316 @Test
317 void testGet_EmptyResource() throws Exception {
318 File file = TestFileUtils.createTempFile("failure");
319 RecordingTransportListener listener = new RecordingTransportListener();
320 GetTask task =
321 new GetTask(URI.create("repo/empty.txt")).setDataFile(file).setListener(listener);
322 transporter.get(task);
323 assertEquals("", TestFileUtils.readString(file));
324 assertEquals(0L, listener.dataOffset);
325 assertEquals(0L, listener.dataLength);
326 assertEquals(1, listener.startedCount);
327 assertEquals(0, listener.progressedCount);
328 assertEquals("", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
329 }
330
331 @Test
332 void testGet_EncodedResourcePath() throws Exception {
333 GetTask task = new GetTask(URI.create("repo/some%20space.txt"));
334 transporter.get(task);
335 assertEquals("space", task.getDataString());
336 }
337
338 @Test
339 void testGet_Authenticated() throws Exception {
340 httpServer.setAuthentication("testuser", "testpass");
341 auth = new AuthenticationBuilder()
342 .addUsername("testuser")
343 .addPassword("testpass")
344 .build();
345 newTransporter(httpServer.getHttpUrl());
346 RecordingTransportListener listener = new RecordingTransportListener();
347 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
348 transporter.get(task);
349 assertEquals("test", task.getDataString());
350 assertEquals(0L, listener.dataOffset);
351 assertEquals(4L, listener.dataLength);
352 assertEquals(1, listener.startedCount);
353 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
354 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
355 }
356
357 @Test
358 void testGet_Unauthenticated() throws Exception {
359 httpServer.setAuthentication("testuser", "testpass");
360 try {
361 transporter.get(new GetTask(URI.create("repo/file.txt")));
362 fail("Expected error");
363 } catch (HttpResponseException e) {
364 assertEquals(401, e.getStatusCode());
365 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
366 }
367 }
368
369 @Test
370 void testGet_ProxyAuthenticated() throws Exception {
371 httpServer.setProxyAuthentication("testuser", "testpass");
372 Authentication auth = new AuthenticationBuilder()
373 .addUsername("testuser")
374 .addPassword("testpass")
375 .build();
376 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
377 newTransporter("http://bad.localhost:1/");
378 RecordingTransportListener listener = new RecordingTransportListener();
379 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
380 transporter.get(task);
381 assertEquals("test", task.getDataString());
382 assertEquals(0L, listener.dataOffset);
383 assertEquals(4L, listener.dataLength);
384 assertEquals(1, listener.startedCount);
385 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
386 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
387 }
388
389 @Test
390 void testGet_ProxyUnauthenticated() throws Exception {
391 httpServer.setProxyAuthentication("testuser", "testpass");
392 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
393 newTransporter("http://bad.localhost:1/");
394 try {
395 transporter.get(new GetTask(URI.create("repo/file.txt")));
396 fail("Expected error");
397 } catch (HttpResponseException e) {
398 assertEquals(407, e.getStatusCode());
399 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
400 }
401 }
402
403 @Test
404 void testGet_SSL() throws Exception {
405 httpServer.addSslConnector();
406 newTransporter(httpServer.getHttpsUrl());
407 RecordingTransportListener listener = new RecordingTransportListener();
408 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
409 transporter.get(task);
410 assertEquals("test", task.getDataString());
411 assertEquals(0L, listener.dataOffset);
412 assertEquals(4L, listener.dataLength);
413 assertEquals(1, listener.startedCount);
414 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
415 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
416 }
417
418 @Test
419 void testGet_HTTPS_Unknown_SecurityMode() throws Exception {
420 session.setConfigProperty("aether.connector.https.securityMode", "unknown");
421 httpServer.addSelfSignedSslConnector();
422 try {
423 newTransporter(httpServer.getHttpsUrl());
424 fail("Unsupported security mode");
425 } catch (IllegalArgumentException a) {
426
427 }
428 }
429
430 @Test
431 void testGet_HTTPS_Insecure_SecurityMode() throws Exception {
432
433
434 session.setConfigProperty(
435 "aether.connector.https.securityMode", ConfigurationProperties.HTTPS_SECURITY_MODE_INSECURE);
436 httpServer.addSelfSignedSslConnector();
437 newTransporter(httpServer.getHttpsUrl());
438 RecordingTransportListener listener = new RecordingTransportListener();
439 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
440 transporter.get(task);
441 assertEquals("test", task.getDataString());
442 assertEquals(0L, listener.dataOffset);
443 assertEquals(4L, listener.dataLength);
444 assertEquals(1, listener.startedCount);
445 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
446 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
447 }
448
449 @Test
450 void testGet_WebDav() throws Exception {
451 httpServer.setWebDav(true);
452 RecordingTransportListener listener = new RecordingTransportListener();
453 GetTask task = new GetTask(URI.create("repo/dir/file.txt")).setListener(listener);
454 ((HttpTransporter) transporter).getState().setWebDav(true);
455 transporter.get(task);
456 assertEquals("test", task.getDataString());
457 assertEquals(0L, listener.dataOffset);
458 assertEquals(4L, listener.dataLength);
459 assertEquals(1, listener.startedCount);
460 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
461 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
462 assertEquals(
463 1, httpServer.getLogEntries().size(), httpServer.getLogEntries().toString());
464 }
465
466 @Test
467 void testGet_Redirect() throws Exception {
468 httpServer.addSslConnector();
469 RecordingTransportListener listener = new RecordingTransportListener();
470 GetTask task = new GetTask(URI.create("redirect/file.txt?scheme=https")).setListener(listener);
471 transporter.get(task);
472 assertEquals("test", task.getDataString());
473 assertEquals(0L, listener.dataOffset);
474 assertEquals(4L, listener.dataLength);
475 assertEquals(1, listener.startedCount);
476 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
477 assertEquals(task.getDataString(), new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
478 }
479
480 @Test
481 void testGet_Resume() throws Exception {
482 File file = TestFileUtils.createTempFile("re");
483 RecordingTransportListener listener = new RecordingTransportListener();
484 GetTask task = new GetTask(URI.create("repo/resume.txt"))
485 .setDataFile(file, true)
486 .setListener(listener);
487 transporter.get(task);
488 assertEquals("resumable", TestFileUtils.readString(file));
489 assertEquals(1L, listener.startedCount);
490 assertEquals(2L, listener.dataOffset);
491 assertEquals(9, listener.dataLength);
492 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
493 assertEquals("sumable", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
494 }
495
496 @Test
497 void testGet_ResumeLocalContentsOutdated() throws Exception {
498 File file = TestFileUtils.createTempFile("re");
499 file.setLastModified(System.currentTimeMillis() - 5 * 60 * 1000);
500 RecordingTransportListener listener = new RecordingTransportListener();
501 GetTask task = new GetTask(URI.create("repo/resume.txt"))
502 .setDataFile(file, true)
503 .setListener(listener);
504 transporter.get(task);
505 assertEquals("resumable", TestFileUtils.readString(file));
506 assertEquals(1L, listener.startedCount);
507 assertEquals(0L, listener.dataOffset);
508 assertEquals(9, listener.dataLength);
509 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
510 assertEquals("resumable", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
511 }
512
513 @Test
514 void testGet_ResumeRangesNotSupportedByServer() throws Exception {
515 httpServer.setRangeSupport(false);
516 File file = TestFileUtils.createTempFile("re");
517 RecordingTransportListener listener = new RecordingTransportListener();
518 GetTask task = new GetTask(URI.create("repo/resume.txt"))
519 .setDataFile(file, true)
520 .setListener(listener);
521 transporter.get(task);
522 assertEquals("resumable", TestFileUtils.readString(file));
523 assertEquals(1L, listener.startedCount);
524 assertEquals(0L, listener.dataOffset);
525 assertEquals(9, listener.dataLength);
526 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
527 assertEquals("resumable", new String(listener.baos.toByteArray(), StandardCharsets.UTF_8));
528 }
529
530 @Test
531 void testGet_Checksums_Nexus() throws Exception {
532 httpServer.setChecksumHeader(HttpServer.ChecksumHeader.NEXUS);
533 GetTask task = new GetTask(URI.create("repo/file.txt"));
534 transporter.get(task);
535 assertEquals("test", task.getDataString());
536 assertEquals(
537 "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", task.getChecksums().get("SHA-1"));
538 }
539
540 @Test
541 void testGet_Checksums_XChecksum() throws Exception {
542 httpServer.setChecksumHeader(HttpServer.ChecksumHeader.XCHECKSUM);
543 GetTask task = new GetTask(URI.create("repo/file.txt"));
544 transporter.get(task);
545 assertEquals("test", task.getDataString());
546 assertEquals(
547 "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", task.getChecksums().get("SHA-1"));
548 }
549
550 @Test
551 void testGet_FileHandleLeak() throws Exception {
552 for (int i = 0; i < 100; i++) {
553 File file = TestFileUtils.createTempFile("failure");
554 transporter.get(new GetTask(URI.create("repo/file.txt")).setDataFile(file));
555 assertTrue(file.delete(), i + ", " + file.getAbsolutePath());
556 }
557 }
558
559 @Test
560 void testGet_NotFound() throws Exception {
561 try {
562 transporter.get(new GetTask(URI.create("repo/missing.txt")));
563 fail("Expected error");
564 } catch (HttpResponseException e) {
565 assertEquals(404, e.getStatusCode());
566 assertEquals(Transporter.ERROR_NOT_FOUND, transporter.classify(e));
567 }
568 }
569
570 @Test
571 void testGet_Closed() throws Exception {
572 transporter.close();
573 try {
574 transporter.get(new GetTask(URI.create("repo/file.txt")));
575 fail("Expected error");
576 } catch (IllegalStateException e) {
577 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
578 }
579 }
580
581 @Test
582 void testGet_StartCancelled() throws Exception {
583 RecordingTransportListener listener = new RecordingTransportListener();
584 listener.cancelStart = true;
585 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
586 try {
587 transporter.get(task);
588 fail("Expected error");
589 } catch (TransferCancelledException e) {
590 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
591 }
592 assertEquals(0L, listener.dataOffset);
593 assertEquals(4L, listener.dataLength);
594 assertEquals(1, listener.startedCount);
595 assertEquals(0, listener.progressedCount);
596 }
597
598 @Test
599 void testGet_ProgressCancelled() throws Exception {
600 RecordingTransportListener listener = new RecordingTransportListener();
601 listener.cancelProgress = true;
602 GetTask task = new GetTask(URI.create("repo/file.txt")).setListener(listener);
603 try {
604 transporter.get(task);
605 fail("Expected error");
606 } catch (TransferCancelledException e) {
607 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
608 }
609 assertEquals(0L, listener.dataOffset);
610 assertEquals(4L, listener.dataLength);
611 assertEquals(1, listener.startedCount);
612 assertEquals(1, listener.progressedCount);
613 }
614
615 @Test
616 void testPut_FromMemory() throws Exception {
617 RecordingTransportListener listener = new RecordingTransportListener();
618 PutTask task =
619 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
620 transporter.put(task);
621 assertEquals(0L, listener.dataOffset);
622 assertEquals(6L, listener.dataLength);
623 assertEquals(1, listener.startedCount);
624 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
625 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
626 }
627
628 @Test
629 void testPut_FromFile() throws Exception {
630 File file = TestFileUtils.createTempFile("upload");
631 RecordingTransportListener listener = new RecordingTransportListener();
632 PutTask task =
633 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataFile(file);
634 transporter.put(task);
635 assertEquals(0L, listener.dataOffset);
636 assertEquals(6L, listener.dataLength);
637 assertEquals(1, listener.startedCount);
638 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
639 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
640 }
641
642 @Test
643 void testPut_EmptyResource() throws Exception {
644 RecordingTransportListener listener = new RecordingTransportListener();
645 PutTask task = new PutTask(URI.create("repo/file.txt")).setListener(listener);
646 transporter.put(task);
647 assertEquals(0L, listener.dataOffset);
648 assertEquals(0L, listener.dataLength);
649 assertEquals(1, listener.startedCount);
650 assertEquals(0, listener.progressedCount);
651 assertEquals("", TestFileUtils.readString(new File(repoDir, "file.txt")));
652 }
653
654 @Test
655 void testPut_EncodedResourcePath() throws Exception {
656 RecordingTransportListener listener = new RecordingTransportListener();
657 PutTask task = new PutTask(URI.create("repo/some%20space.txt"))
658 .setListener(listener)
659 .setDataString("OK");
660 transporter.put(task);
661 assertEquals(0L, listener.dataOffset);
662 assertEquals(2L, listener.dataLength);
663 assertEquals(1, listener.startedCount);
664 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
665 assertEquals("OK", TestFileUtils.readString(new File(repoDir, "some space.txt")));
666 }
667
668 @Test
669 void testPut_Authenticated_ExpectContinue() throws Exception {
670 httpServer.setAuthentication("testuser", "testpass");
671 auth = new AuthenticationBuilder()
672 .addUsername("testuser")
673 .addPassword("testpass")
674 .build();
675 newTransporter(httpServer.getHttpUrl());
676 RecordingTransportListener listener = new RecordingTransportListener();
677 PutTask task =
678 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
679 transporter.put(task);
680 assertEquals(0L, listener.dataOffset);
681 assertEquals(6L, listener.dataLength);
682 assertEquals(1, listener.startedCount);
683 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
684 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
685 }
686
687 @Test
688 void testPut_Authenticated_ExpectContinueBroken() throws Exception {
689
690 session.setConfigProperty(ConfigurationProperties.HTTP_SUPPORT_WEBDAV, true);
691 httpServer.setAuthentication("testuser", "testpass");
692 httpServer.setExpectSupport(HttpServer.ExpectContinue.BROKEN);
693 auth = new AuthenticationBuilder()
694 .addUsername("testuser")
695 .addPassword("testpass")
696 .build();
697 newTransporter(httpServer.getHttpUrl());
698 RecordingTransportListener listener = new RecordingTransportListener();
699 PutTask task =
700 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
701 transporter.put(task);
702 assertEquals(0L, listener.dataOffset);
703 assertEquals(6L, listener.dataLength);
704 assertEquals(1, listener.startedCount);
705 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
706 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
707 }
708
709 @Test
710 void testPut_Authenticated_ExpectContinueRejected() throws Exception {
711 httpServer.setAuthentication("testuser", "testpass");
712 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
713 auth = new AuthenticationBuilder()
714 .addUsername("testuser")
715 .addPassword("testpass")
716 .build();
717 newTransporter(httpServer.getHttpUrl());
718 RecordingTransportListener listener = new RecordingTransportListener();
719 PutTask task =
720 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
721 transporter.put(task);
722 assertEquals(0L, listener.dataOffset);
723 assertEquals(6L, listener.dataLength);
724 assertEquals(1, listener.startedCount);
725 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
726 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
727 }
728
729 @Test
730 void testPut_Authenticated_ExpectContinueDisabled() throws Exception {
731 session.setConfigProperty(ConfigurationProperties.HTTP_EXPECT_CONTINUE, false);
732 httpServer.setAuthentication("testuser", "testpass");
733 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
734 auth = new AuthenticationBuilder()
735 .addUsername("testuser")
736 .addPassword("testpass")
737 .build();
738 newTransporter(httpServer.getHttpUrl());
739 RecordingTransportListener listener = new RecordingTransportListener();
740 PutTask task =
741 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
742 transporter.put(task);
743 assertEquals(0L, listener.dataOffset);
744 assertEquals(6L, listener.dataLength);
745 assertEquals(1, listener.startedCount);
746 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
747 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
748 }
749
750 @Test
751 void testPut_Authenticated_ExpectContinueRejected_ExplicitlyConfiguredHeader() throws Exception {
752 Map<String, String> headers = new HashMap<>();
753 headers.put("Expect", "100-continue");
754 session.setConfigProperty(ConfigurationProperties.HTTP_HEADERS + ".test", headers);
755 httpServer.setAuthentication("testuser", "testpass");
756 httpServer.setExpectSupport(HttpServer.ExpectContinue.FAIL);
757 auth = new AuthenticationBuilder()
758 .addUsername("testuser")
759 .addPassword("testpass")
760 .build();
761 newTransporter(httpServer.getHttpUrl());
762 RecordingTransportListener listener = new RecordingTransportListener();
763 PutTask task =
764 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
765 transporter.put(task);
766 assertEquals(0L, listener.dataOffset);
767 assertEquals(6L, listener.dataLength);
768 assertEquals(1, listener.startedCount);
769 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
770 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
771 }
772
773 @Test
774 void testPut_Unauthenticated() throws Exception {
775 httpServer.setAuthentication("testuser", "testpass");
776 RecordingTransportListener listener = new RecordingTransportListener();
777 PutTask task =
778 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
779 try {
780 transporter.put(task);
781 fail("Expected error");
782 } catch (HttpResponseException e) {
783 assertEquals(401, e.getStatusCode());
784 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
785 }
786 assertEquals(0, listener.startedCount);
787 assertEquals(0, listener.progressedCount);
788 }
789
790 @Test
791 void testPut_ProxyAuthenticated() throws Exception {
792 httpServer.setProxyAuthentication("testuser", "testpass");
793 Authentication auth = new AuthenticationBuilder()
794 .addUsername("testuser")
795 .addPassword("testpass")
796 .build();
797 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
798 newTransporter("http://bad.localhost:1/");
799 RecordingTransportListener listener = new RecordingTransportListener();
800 PutTask task =
801 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
802 transporter.put(task);
803 assertEquals(0L, listener.dataOffset);
804 assertEquals(6L, listener.dataLength);
805 assertEquals(1, listener.startedCount);
806 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
807 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
808 }
809
810 @Test
811 void testPut_ProxyUnauthenticated() throws Exception {
812 httpServer.setProxyAuthentication("testuser", "testpass");
813 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
814 newTransporter("http://bad.localhost:1/");
815 RecordingTransportListener listener = new RecordingTransportListener();
816 PutTask task =
817 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
818 try {
819 transporter.put(task);
820 fail("Expected error");
821 } catch (HttpResponseException e) {
822 assertEquals(407, e.getStatusCode());
823 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
824 }
825 assertEquals(0, listener.startedCount);
826 assertEquals(0, listener.progressedCount);
827 }
828
829 @Test
830 void testPut_SSL() throws Exception {
831 httpServer.addSslConnector();
832 httpServer.setAuthentication("testuser", "testpass");
833 auth = new AuthenticationBuilder()
834 .addUsername("testuser")
835 .addPassword("testpass")
836 .build();
837 newTransporter(httpServer.getHttpsUrl());
838 RecordingTransportListener listener = new RecordingTransportListener();
839 PutTask task =
840 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
841 transporter.put(task);
842 assertEquals(0L, listener.dataOffset);
843 assertEquals(6L, listener.dataLength);
844 assertEquals(1, listener.startedCount);
845 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
846 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "file.txt")));
847 }
848
849 @Test
850 void testPut_WebDav() throws Exception {
851 httpServer.setWebDav(true);
852 session.setConfigProperty(ConfigurationProperties.HTTP_SUPPORT_WEBDAV, true);
853 newTransporter(httpServer.getHttpUrl());
854
855 RecordingTransportListener listener = new RecordingTransportListener();
856 PutTask task = new PutTask(URI.create("repo/dir1/dir2/file.txt"))
857 .setListener(listener)
858 .setDataString("upload");
859 transporter.put(task);
860 assertEquals(0L, listener.dataOffset);
861 assertEquals(6L, listener.dataLength);
862 assertEquals(1, listener.startedCount);
863 assertTrue(listener.progressedCount > 0, "Count: " + listener.progressedCount);
864 assertEquals("upload", TestFileUtils.readString(new File(repoDir, "dir1/dir2/file.txt")));
865
866 assertEquals(5, httpServer.getLogEntries().size());
867 assertEquals("OPTIONS", httpServer.getLogEntries().get(0).method);
868 assertEquals("MKCOL", httpServer.getLogEntries().get(1).method);
869 assertEquals("/repo/dir1/dir2/", httpServer.getLogEntries().get(1).path);
870 assertEquals("MKCOL", httpServer.getLogEntries().get(2).method);
871 assertEquals("/repo/dir1/", httpServer.getLogEntries().get(2).path);
872 assertEquals("MKCOL", httpServer.getLogEntries().get(3).method);
873 assertEquals("/repo/dir1/dir2/", httpServer.getLogEntries().get(3).path);
874 assertEquals("PUT", httpServer.getLogEntries().get(4).method);
875 }
876
877 @Test
878 void testPut_FileHandleLeak() throws Exception {
879 for (int i = 0; i < 100; i++) {
880 File src = TestFileUtils.createTempFile("upload");
881 File dst = new File(repoDir, "file.txt");
882 transporter.put(new PutTask(URI.create("repo/file.txt")).setDataFile(src));
883 assertTrue(src.delete(), i + ", " + src.getAbsolutePath());
884 assertTrue(dst.delete(), i + ", " + dst.getAbsolutePath());
885 }
886 }
887
888 @Test
889 void testPut_Closed() throws Exception {
890 transporter.close();
891 try {
892 transporter.put(new PutTask(URI.create("repo/missing.txt")));
893 fail("Expected error");
894 } catch (IllegalStateException e) {
895 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
896 }
897 }
898
899 @Test
900 void testPut_StartCancelled() throws Exception {
901 RecordingTransportListener listener = new RecordingTransportListener();
902 listener.cancelStart = true;
903 PutTask task =
904 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
905 try {
906 transporter.put(task);
907 fail("Expected error");
908 } catch (TransferCancelledException e) {
909 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
910 }
911 assertEquals(0L, listener.dataOffset);
912 assertEquals(6L, listener.dataLength);
913 assertEquals(1, listener.startedCount);
914 assertEquals(0, listener.progressedCount);
915 }
916
917 @Test
918 void testPut_ProgressCancelled() throws Exception {
919 RecordingTransportListener listener = new RecordingTransportListener();
920 listener.cancelProgress = true;
921 PutTask task =
922 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
923 try {
924 transporter.put(task);
925 fail("Expected error");
926 } catch (TransferCancelledException e) {
927 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
928 }
929 assertEquals(0L, listener.dataOffset);
930 assertEquals(6L, listener.dataLength);
931 assertEquals(1, listener.startedCount);
932 assertEquals(1, listener.progressedCount);
933 }
934
935 @Test
936 void testGetPut_AuthCache() throws Exception {
937 httpServer.setAuthentication("testuser", "testpass");
938 auth = new AuthenticationBuilder()
939 .addUsername("testuser")
940 .addPassword("testpass")
941 .build();
942 newTransporter(httpServer.getHttpUrl());
943 GetTask get = new GetTask(URI.create("repo/file.txt"));
944 transporter.get(get);
945 RecordingTransportListener listener = new RecordingTransportListener();
946 PutTask task =
947 new PutTask(URI.create("repo/file.txt")).setListener(listener).setDataString("upload");
948 transporter.put(task);
949 assertEquals(1, listener.startedCount);
950 }
951
952 @Test
953 void testPut_PreemptiveIsDefault() throws Exception {
954 httpServer.setAuthentication("testuser", "testpass");
955 auth = new AuthenticationBuilder()
956 .addUsername("testuser")
957 .addPassword("testpass")
958 .build();
959 newTransporter(httpServer.getHttpUrl());
960 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
961 transporter.put(task);
962 assertEquals(1, httpServer.getLogEntries().size());
963 }
964
965 @Test
966 void testPut_AuthCache() throws Exception {
967 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_PUT_AUTH, false);
968 httpServer.setAuthentication("testuser", "testpass");
969 auth = new AuthenticationBuilder()
970 .addUsername("testuser")
971 .addPassword("testpass")
972 .build();
973 newTransporter(httpServer.getHttpUrl());
974 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
975 transporter.put(task);
976 assertEquals(2, httpServer.getLogEntries().size());
977 httpServer.getLogEntries().clear();
978 task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
979 transporter.put(task);
980 assertEquals(1, httpServer.getLogEntries().size());
981 }
982
983 @Test
984 void testPut_AuthCache_Preemptive() throws Exception {
985 httpServer.setAuthentication("testuser", "testpass");
986 auth = new AuthenticationBuilder()
987 .addUsername("testuser")
988 .addPassword("testpass")
989 .build();
990 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, true);
991 newTransporter(httpServer.getHttpUrl());
992 PutTask task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
993 transporter.put(task);
994 assertEquals(1, httpServer.getLogEntries().size());
995 httpServer.getLogEntries().clear();
996 task = new PutTask(URI.create("repo/file.txt")).setDataString("upload");
997 transporter.put(task);
998 assertEquals(1, httpServer.getLogEntries().size());
999 }
1000
1001 @Test
1002 @Timeout(20)
1003 public void testConcurrency() throws Exception {
1004 httpServer.setAuthentication("testuser", "testpass");
1005 auth = new AuthenticationBuilder()
1006 .addUsername("testuser")
1007 .addPassword("testpass")
1008 .build();
1009 newTransporter(httpServer.getHttpUrl());
1010 final AtomicReference<Throwable> error = new AtomicReference<>();
1011 Thread[] threads = new Thread[20];
1012 for (int i = 0; i < threads.length; i++) {
1013 final String path = "repo/file.txt?i=" + i;
1014 threads[i] = new Thread() {
1015 @Override
1016 public void run() {
1017 try {
1018 for (int j = 0; j < 100; j++) {
1019 GetTask task = new GetTask(URI.create(path));
1020 transporter.get(task);
1021 assertEquals("test", task.getDataString());
1022 }
1023 } catch (Throwable t) {
1024 error.compareAndSet(null, t);
1025 System.err.println(path);
1026 t.printStackTrace();
1027 }
1028 }
1029 };
1030 threads[i].setName("Task-" + i);
1031 }
1032 for (Thread thread : threads) {
1033 thread.start();
1034 }
1035 for (Thread thread : threads) {
1036 thread.join();
1037 }
1038 assertNull(error.get(), String.valueOf(error.get()));
1039 }
1040
1041 @Test
1042 @Timeout(10)
1043 public void testConnectTimeout() throws Exception {
1044 session.setConfigProperty(ConfigurationProperties.CONNECT_TIMEOUT, 100);
1045 int port = 1;
1046 newTransporter("http://localhost:" + port);
1047 try {
1048 transporter.get(new GetTask(URI.create("repo/file.txt")));
1049 fail("Expected error");
1050 } catch (ConnectTimeoutException | ConnectException e) {
1051 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
1052 }
1053 }
1054
1055 @Test
1056 @Timeout(10)
1057 public void testRequestTimeout() throws Exception {
1058 session.setConfigProperty(ConfigurationProperties.REQUEST_TIMEOUT, 100);
1059 ServerSocket server = new ServerSocket(0);
1060 newTransporter("http://localhost:" + server.getLocalPort());
1061 try {
1062 try {
1063 transporter.get(new GetTask(URI.create("repo/file.txt")));
1064 fail("Expected error");
1065 } catch (SocketTimeoutException e) {
1066 assertEquals(Transporter.ERROR_OTHER, transporter.classify(e));
1067 }
1068 } finally {
1069 server.close();
1070 }
1071 }
1072
1073 @Test
1074 void testUserAgent() throws Exception {
1075 session.setConfigProperty(ConfigurationProperties.USER_AGENT, "SomeTest/1.0");
1076 newTransporter(httpServer.getHttpUrl());
1077 transporter.get(new GetTask(URI.create("repo/file.txt")));
1078 assertEquals(1, httpServer.getLogEntries().size());
1079 for (HttpServer.LogEntry log : httpServer.getLogEntries()) {
1080 assertEquals("SomeTest/1.0", log.headers.get("User-Agent"));
1081 }
1082 }
1083
1084 @Test
1085 void testCustomHeaders() throws Exception {
1086 Map<String, String> headers = new HashMap<>();
1087 headers.put("User-Agent", "Custom/1.0");
1088 headers.put("X-CustomHeader", "Custom-Value");
1089 session.setConfigProperty(ConfigurationProperties.USER_AGENT, "SomeTest/1.0");
1090 session.setConfigProperty(ConfigurationProperties.HTTP_HEADERS + ".test", headers);
1091 newTransporter(httpServer.getHttpUrl());
1092 transporter.get(new GetTask(URI.create("repo/file.txt")));
1093 assertEquals(1, httpServer.getLogEntries().size());
1094 for (HttpServer.LogEntry log : httpServer.getLogEntries()) {
1095 for (Map.Entry<String, String> entry : headers.entrySet()) {
1096 assertEquals(entry.getValue(), log.headers.get(entry.getKey()), entry.getKey());
1097 }
1098 }
1099 }
1100
1101 @Test
1102 void testServerAuthScope_NotUsedForProxy() throws Exception {
1103 String username = "testuser", password = "testpass";
1104 httpServer.setProxyAuthentication(username, password);
1105 auth = new AuthenticationBuilder()
1106 .addUsername(username)
1107 .addPassword(password)
1108 .build();
1109 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort());
1110 newTransporter("http://" + httpServer.getHost() + ":12/");
1111 try {
1112 transporter.get(new GetTask(URI.create("repo/file.txt")));
1113 fail("Server auth must not be used as proxy auth");
1114 } catch (HttpResponseException e) {
1115 assertEquals(407, e.getStatusCode());
1116 }
1117 }
1118
1119 @Test
1120 void testProxyAuthScope_NotUsedForServer() throws Exception {
1121 String username = "testuser", password = "testpass";
1122 httpServer.setAuthentication(username, password);
1123 Authentication auth = new AuthenticationBuilder()
1124 .addUsername(username)
1125 .addPassword(password)
1126 .build();
1127 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
1128 newTransporter("http://" + httpServer.getHost() + ":12/");
1129 try {
1130 transporter.get(new GetTask(URI.create("repo/file.txt")));
1131 fail("Proxy auth must not be used as server auth");
1132 } catch (HttpResponseException e) {
1133 assertEquals(401, e.getStatusCode());
1134 }
1135 }
1136
1137 @Test
1138 void testAuthSchemeReuse() throws Exception {
1139 httpServer.setAuthentication("testuser", "testpass");
1140 httpServer.setProxyAuthentication("proxyuser", "proxypass");
1141 session.setCache(new DefaultRepositoryCache());
1142 auth = new AuthenticationBuilder()
1143 .addUsername("testuser")
1144 .addPassword("testpass")
1145 .build();
1146 Authentication auth = new AuthenticationBuilder()
1147 .addUsername("proxyuser")
1148 .addPassword("proxypass")
1149 .build();
1150 proxy = new Proxy(Proxy.TYPE_HTTP, httpServer.getHost(), httpServer.getHttpPort(), auth);
1151 newTransporter("http://bad.localhost:1/");
1152 GetTask task = new GetTask(URI.create("repo/file.txt"));
1153 transporter.get(task);
1154 assertEquals("test", task.getDataString());
1155 assertEquals(3, httpServer.getLogEntries().size());
1156 httpServer.getLogEntries().clear();
1157 newTransporter("http://bad.localhost:1/");
1158 task = new GetTask(URI.create("repo/file.txt"));
1159 transporter.get(task);
1160 assertEquals("test", task.getDataString());
1161 assertEquals(1, httpServer.getLogEntries().size());
1162 assertNotNull(httpServer.getLogEntries().get(0).headers.get("Authorization"));
1163 assertNotNull(httpServer.getLogEntries().get(0).headers.get("Proxy-Authorization"));
1164 }
1165
1166 @Test
1167 void testAuthSchemePreemptive() throws Exception {
1168 httpServer.setAuthentication("testuser", "testpass");
1169 session.setCache(new DefaultRepositoryCache());
1170 auth = new AuthenticationBuilder()
1171 .addUsername("testuser")
1172 .addPassword("testpass")
1173 .build();
1174
1175 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, false);
1176 newTransporter(httpServer.getHttpUrl());
1177 GetTask task = new GetTask(URI.create("repo/file.txt"));
1178 transporter.get(task);
1179 assertEquals("test", task.getDataString());
1180
1181 assertEquals(2, httpServer.getLogEntries().size());
1182
1183 httpServer.getLogEntries().clear();
1184
1185 session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_AUTH, true);
1186 newTransporter(httpServer.getHttpUrl());
1187 task = new GetTask(URI.create("repo/file.txt"));
1188 transporter.get(task);
1189 assertEquals("test", task.getDataString());
1190
1191 assertEquals(1, httpServer.getLogEntries().size());
1192 }
1193
1194 @Test
1195 void testConnectionReuse() throws Exception {
1196 httpServer.addSslConnector();
1197 session.setCache(new DefaultRepositoryCache());
1198 for (int i = 0; i < 3; i++) {
1199 newTransporter(httpServer.getHttpsUrl());
1200 GetTask task = new GetTask(URI.create("repo/file.txt"));
1201 transporter.get(task);
1202 assertEquals("test", task.getDataString());
1203 }
1204 PoolStats stats = ((ConnPoolControl<?>)
1205 ((HttpTransporter) transporter).getState().getConnectionManager())
1206 .getTotalStats();
1207 assertEquals(1, stats.getAvailable(), stats.toString());
1208 }
1209
1210 @Test
1211 void testConnectionNoReuse() throws Exception {
1212 httpServer.addSslConnector();
1213 session.setCache(new DefaultRepositoryCache());
1214 session.setConfigProperty(ConfigurationProperties.HTTP_REUSE_CONNECTIONS, false);
1215 for (int i = 0; i < 3; i++) {
1216 newTransporter(httpServer.getHttpsUrl());
1217 GetTask task = new GetTask(URI.create("repo/file.txt"));
1218 transporter.get(task);
1219 assertEquals("test", task.getDataString());
1220 }
1221 PoolStats stats = ((ConnPoolControl<?>)
1222 ((HttpTransporter) transporter).getState().getConnectionManager())
1223 .getTotalStats();
1224 assertEquals(0, stats.getAvailable(), stats.toString());
1225 }
1226
1227 @Test
1228 void testInit_BadProtocol() {
1229 assertThrows(NoTransporterException.class, () -> newTransporter("bad:/void"));
1230 }
1231
1232 @Test
1233 void testInit_BadUrl() {
1234 assertThrows(NoTransporterException.class, () -> newTransporter("http://localhost:NaN"));
1235 }
1236
1237 @Test
1238 void testInit_CaseInsensitiveProtocol() throws Exception {
1239 newTransporter("http://localhost");
1240 newTransporter("HTTP://localhost");
1241 newTransporter("Http://localhost");
1242 newTransporter("https://localhost");
1243 newTransporter("HTTPS://localhost");
1244 newTransporter("HttpS://localhost");
1245 }
1246 }