View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.transport.apache;
20  
21  import java.util.Arrays;
22  
23  import org.apache.http.HttpHost;
24  import org.apache.http.HttpRequest;
25  import org.apache.http.message.BasicHttpRequest;
26  import org.apache.http.protocol.HttpContext;
27  import org.apache.http.protocol.HttpCoreContext;
28  import org.junit.jupiter.api.Test;
29  
30  import static org.junit.jupiter.api.Assertions.assertEquals;
31  import static org.junit.jupiter.api.Assertions.assertFalse;
32  import static org.junit.jupiter.api.Assertions.assertTrue;
33  
34  /**
35   * UT for {@link OriginScopedHeadersInterceptor}: configured headers must only be sent to the repository origin;
36   * any other target (cross-host, downgraded scheme or different port - e.g. after a redirect) must not receive them.
37   */
38  public class OriginScopedHeadersInterceptorTest {
39      private static final HttpHost ORIGIN = new HttpHost("repo.example.com", -1, "https");
40  
41      private final OriginScopedHeadersInterceptor interceptor =
42              new OriginScopedHeadersInterceptor(ORIGIN, Arrays.asList("Authorization", "Private-Token"));
43  
44      private static HttpRequest newRequestWithConfiguredHeaders() {
45          HttpRequest request = new BasicHttpRequest("GET", "/base/g/a/1.0/a-1.0.jar");
46          request.setHeader("Authorization", "Bearer s3cr3t");
47          request.setHeader("Private-Token", "t0ken");
48          request.setHeader("Accept", "*/*");
49          return request;
50      }
51  
52      private static HttpContext contextTargeting(HttpHost target) {
53          HttpCoreContext context = HttpCoreContext.create();
54          if (target != null) {
55              context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target);
56          }
57          return context;
58      }
59  
60      private static void assertConfiguredHeadersPresent(HttpRequest request) {
61          assertTrue(request.containsHeader("Authorization"));
62          assertTrue(request.containsHeader("Private-Token"));
63          assertTrue(request.containsHeader("Accept"));
64      }
65  
66      private static void assertConfiguredHeadersStripped(HttpRequest request) {
67          assertFalse(request.containsHeader("Authorization"));
68          assertFalse(request.containsHeader("Private-Token"));
69          // headers not coming from the configured map are left alone
70          assertTrue(request.containsHeader("Accept"));
71      }
72  
73      @Test
74      void keepsHeadersForOrigin() throws Exception {
75          HttpRequest request = newRequestWithConfiguredHeaders();
76          interceptor.process(request, contextTargeting(new HttpHost("repo.example.com", -1, "https")));
77          assertConfiguredHeadersPresent(request);
78      }
79  
80      @Test
81      void keepsHeadersForOriginWithExplicitDefaultPort() throws Exception {
82          HttpRequest request = newRequestWithConfiguredHeaders();
83          interceptor.process(request, contextTargeting(new HttpHost("repo.example.com", 443, "https")));
84          assertConfiguredHeadersPresent(request);
85      }
86  
87      @Test
88      void keepsHeadersForOriginWithDifferentHostCase() throws Exception {
89          HttpRequest request = newRequestWithConfiguredHeaders();
90          interceptor.process(request, contextTargeting(new HttpHost("REPO.Example.COM", -1, "HTTPS")));
91          assertConfiguredHeadersPresent(request);
92      }
93  
94      @Test
95      void stripsHeadersForCrossHostTarget() throws Exception {
96          HttpRequest request = newRequestWithConfiguredHeaders();
97          interceptor.process(request, contextTargeting(new HttpHost("cdn.example.net", -1, "https")));
98          assertConfiguredHeadersStripped(request);
99      }
100 
101     @Test
102     void stripsHeadersForSchemeDowngradeOnSameHost() throws Exception {
103         HttpRequest request = newRequestWithConfiguredHeaders();
104         interceptor.process(request, contextTargeting(new HttpHost("repo.example.com", -1, "http")));
105         assertConfiguredHeadersStripped(request);
106     }
107 
108     @Test
109     void stripsHeadersForDifferentPortOnSameHost() throws Exception {
110         HttpRequest request = newRequestWithConfiguredHeaders();
111         interceptor.process(request, contextTargeting(new HttpHost("repo.example.com", 8443, "https")));
112         assertConfiguredHeadersStripped(request);
113     }
114 
115     @Test
116     void stripsHeadersWhenTargetHostUnknown() throws Exception {
117         // fail closed: no determinable target means configured headers are not attached
118         HttpRequest request = newRequestWithConfiguredHeaders();
119         interceptor.process(request, contextTargeting(null));
120         assertConfiguredHeadersStripped(request);
121     }
122 
123     @Test
124     void noConfiguredHeadersIsNoOp() throws Exception {
125         OriginScopedHeadersInterceptor empty =
126                 new OriginScopedHeadersInterceptor(ORIGIN, Arrays.asList(new Object[] {null}));
127         HttpRequest request = newRequestWithConfiguredHeaders();
128         empty.process(request, contextTargeting(new HttpHost("cdn.example.net", -1, "https")));
129         assertConfiguredHeadersPresent(request);
130     }
131 
132     @Test
133     void effectivePortFollowsScheme() {
134         assertEquals(443, OriginScopedHeadersInterceptor.schemeDefaultPort(new HttpHost("h", -1, "https")));
135         assertEquals(80, OriginScopedHeadersInterceptor.schemeDefaultPort(new HttpHost("h", -1, "http")));
136         assertEquals(8081, OriginScopedHeadersInterceptor.schemeDefaultPort(new HttpHost("h", 8081, "https")));
137     }
138 }