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