22
33import com .github .tomakehurst .wiremock .WireMockServer ;
44import com .github .tomakehurst .wiremock .client .WireMock ;
5+ import com .github .tomakehurst .wiremock .core .WireMockConfiguration ;
56import com .github .tomakehurst .wiremock .verification .LoggedRequest ;
67import io .swagger .v3 .parser .core .models .AuthorizationValue ;
8+ import io .swagger .v3 .parser .urlresolver .exceptions .HostDeniedException ;
79import org .testng .annotations .AfterMethod ;
810import org .testng .annotations .BeforeMethod ;
911import org .testng .annotations .Test ;
1012
1113import javax .net .ssl .HttpsURLConnection ;
14+ import java .io .IOException ;
1215import java .net .SocketTimeoutException ;
1316import java .net .URL ;
14- import java .util .Arrays ;
17+ import java .util .Collections ;
1518import java .util .List ;
1619
1720import static com .github .tomakehurst .wiremock .client .WireMock .aResponse ;
@@ -35,15 +38,21 @@ public class RemoteUrlTest {
3538
3639
3740 @ AfterMethod
38- public void tearDown () throws Exception {
41+ public void tearDown () {
3942 wireMockServer .stop ();
4043 }
4144
4245 @ BeforeMethod
43- public void setUp () throws Exception {
44- wireMockServer = new WireMockServer (WIRE_MOCK_PORT );
46+ public void setUp () {
47+ System .setProperty ("io.swagger.v3.parser.util.RemoteUrl.trustAll" , "true" );
48+ wireMockServer = new WireMockServer (
49+ WireMockConfiguration .options ()
50+ .port (0 ) // disables HTTP
51+ .httpsPort (WIRE_MOCK_PORT ) // enables HTTPS
52+ );
4553 wireMockServer .start ();
46- WireMock .configureFor (WIRE_MOCK_PORT );
54+ WireMock .configureFor ("https" , LOCALHOST , WIRE_MOCK_PORT ); // Use HTTPS for WireMock
55+
4756 }
4857
4958 @ Test
@@ -62,7 +71,7 @@ public void testReadARemoteUrl() throws Exception {
6271 assertEquals (actualBody , expectedBody );
6372
6473 verify (getRequestedFor (urlEqualTo ("/v2/pet/1" ))
65- .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER )));
74+ .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER )));
6675 }
6776
6877 @ Test
@@ -73,13 +82,13 @@ public void testAuthorizationHeader() throws Exception {
7382 final String headerName = "Authorization" ;
7483 final String headerValue = "foobar" ;
7584 final AuthorizationValue authorizationValue = new AuthorizationValue (headerName , headerValue , "header" );
76- final String actualBody = RemoteUrl .urlToString (getUrl (), Arrays . asList (authorizationValue ));
85+ final String actualBody = RemoteUrl .urlToString (getUrl (), Collections . singletonList (authorizationValue ));
7786
7887 assertEquals (actualBody , expectedBody );
7988
8089 verify (getRequestedFor (urlEqualTo ("/v2/pet/1" ))
81- .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER ))
82- .withHeader (headerName , equalTo (headerValue ))
90+ .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER ))
91+ .withHeader (headerName , equalTo (headerValue ))
8392 );
8493 }
8594
@@ -91,14 +100,14 @@ public void testAuthorizationHeaderWithMatchingUrl() throws Exception {
91100 final String headerName = "Authorization" ;
92101 final String headerValue = "foobar" ;
93102 final AuthorizationValue authorizationValue = new AuthorizationValue (headerName , headerValue , "header" ,
94- url -> url .toString ().startsWith ("http ://localhost" ));
95- final String actualBody = RemoteUrl .urlToString (getUrl (), Arrays . asList (authorizationValue ));
103+ url -> url .toString ().startsWith ("https ://localhost" ));
104+ final String actualBody = RemoteUrl .urlToString (getUrl (), Collections . singletonList (authorizationValue ));
96105
97106 assertEquals (actualBody , expectedBody );
98107
99108 verify (getRequestedFor (urlEqualTo ("/v2/pet/1" ))
100- .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER ))
101- .withHeader (headerName , equalTo (headerValue ))
109+ .withHeader ("Accept" , equalTo (EXPECTED_ACCEPTS_HEADER ))
110+ .withHeader (headerName , equalTo (headerValue ))
102111 );
103112 }
104113
@@ -110,33 +119,32 @@ public void testAuthorizationHeaderWithNonMatchingUrl() throws Exception {
110119 final String headerValue = "foobar" ;
111120 String authorization = "Authorization" ;
112121 final AuthorizationValue authorizationValue = new AuthorizationValue (authorization ,
113- headerValue , "header" , u -> false );
114- final String actualBody = RemoteUrl .urlToString (getUrl (), Arrays . asList (authorizationValue ));
122+ headerValue , "header" , u -> false );
123+ final String actualBody = RemoteUrl .urlToString (getUrl (), Collections . singletonList (authorizationValue ));
115124
116125 assertEquals (actualBody , expectedBody );
117126
118127 List <LoggedRequest > requests = WireMock .findAll (getRequestedFor (urlEqualTo ("/v2/pet/1" )));
119- assertEquals (1 , requests .size ());
128+ assertEquals (requests .size (), 1 );
120129 assertFalse (requests .get (0 ).containsHeader (authorization ));
121130 }
122131
123132 private String getUrl () {
124- return String .format ("http ://%s:%d/v2/pet/1" , LOCALHOST , WIRE_MOCK_PORT );
133+ return String .format ("https ://%s:%d/v2/pet/1" , LOCALHOST , WIRE_MOCK_PORT );
125134 }
126135
127136 private String setupStub () {
128137 final String expectedBody = "a really good body" ;
129138 stubFor (get (urlEqualTo ("/v2/pet/1" ))
130139 .willReturn (aResponse ()
131- .withBody (expectedBody )
132- .withHeader ("Content-Type" , "application/json" )
140+ .withBody (expectedBody )
141+ .withHeader ("Content-Type" , "application/json" )
133142 ));
134143 return expectedBody ;
135144 }
136145
137146 @ Test
138147 public void testConnectionTimeoutEnforced () throws Exception {
139- System .setProperty ("io.swagger.v3.parser.util.RemoteUrl.trustAll" , "true" );
140148 RemoteUrl .ConnectionConfigurator configurator = RemoteUrl .createConnectionConfigurator ();
141149 URL url = new URL ("https://10.255.255.1" ); // non-routable IP to simulate timeout
142150 HttpsURLConnection conn = (HttpsURLConnection ) url .openConnection ();
@@ -152,4 +160,62 @@ public void testConnectionTimeoutEnforced() throws Exception {
152160 assertTrue (duration <= CONNECTION_TIMEOUT + 2000 , "Timeout was not enforced properly (took too long)" );
153161 }
154162 }
163+
164+ @ Test (expectedExceptions = IOException .class )
165+ public void testTooManyRedirectsThrowsException () throws Exception {
166+ String nextPath = "/redirect" ;
167+ // Chain 6 redirects
168+ for (int i = 0 ; i < 6 ; i ++) {
169+ String target = "/redirect" + (i + 1 );
170+ stubFor (get (urlEqualTo (nextPath ))
171+ .willReturn (aResponse ()
172+ .withStatus (302 )
173+ .withHeader ("Location" , wireMockServer .baseUrl () + target )));
174+ nextPath = target ;
175+ }
176+
177+ // Add stub for /redirect6 to return a 200 OK response, but it's not expected to be reached
178+ stubFor (get (urlEqualTo (nextPath ))
179+ .willReturn (aResponse ()
180+ .withStatus (200 )
181+ .withBody ("Final destination" )));
182+
183+ String startUrl = String .format ("https://%s:%d/redirect" , LOCALHOST , WIRE_MOCK_PORT );
184+
185+ try {
186+ RemoteUrl .urlToString (startUrl , null , new PermittedUrlsCheckerAllowLocal ());
187+ } catch (IOException e ) {
188+ assertTrue (e .getMessage ().contains ("Too many redirects" ));
189+ throw e ;
190+ }
191+ }
192+
193+ @ Test (expectedExceptions = HostDeniedException .class )
194+ public void testRedirectWithForbiddenProtocolThrowsException () throws Exception {
195+ String nextPath = "/redirect" ;
196+ // Chain 6 redirects
197+ for (int i = 0 ; i < 3 ; i ++) {
198+ String target = "/redirect" + (i + 1 );
199+ stubFor (get (urlEqualTo (nextPath ))
200+ .willReturn (aResponse ()
201+ .withStatus (302 )
202+ .withHeader ("Location" , "ftp://localhost/" + target )));
203+ nextPath = target ;
204+ }
205+
206+ // Add stub for /redirect6 to return a 200 OK response, but it's not expected to be reached
207+ stubFor (get (urlEqualTo (nextPath ))
208+ .willReturn (aResponse ()
209+ .withStatus (200 )
210+ .withBody ("Final destination" )));
211+
212+ String startUrl = String .format ("https://%s:%d/redirect" , LOCALHOST , WIRE_MOCK_PORT );
213+
214+ try {
215+ RemoteUrl .urlToString (startUrl , null , new PermittedUrlsCheckerAllowLocal ());
216+ } catch (IOException e ) {
217+ assertTrue (e .getMessage ().contains ("Too many redirects" ));
218+ throw e ;
219+ }
220+ }
155221}
0 commit comments