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