11package com .gocardless .http ;
22
33import static org .assertj .core .api .Assertions .assertThat ;
4+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
45
56import com .google .common .collect .ImmutableMap ;
67import java .util .Map ;
@@ -72,12 +73,66 @@ public void shouldAddQueryParams() {
7273 }
7374
7475 @ Test
75- public void shouldEncodePathParam () {
76+ public void shouldRejectSlashInPathParam () {
7677 String template = "/foo/:bar" ;
7778 Map <String , String > pathParams = ImmutableMap .of ("bar" , "bar/lah" );
7879 Map <String , Object > queryParams = ImmutableMap .of ();
79- HttpUrl result = urlFormatter .formatUrl (template , pathParams , queryParams );
80- assertThat (result .toString ()).isEqualTo ("http://example.com/foo/bar%2Flah" );
80+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
81+ .isInstanceOf (IllegalArgumentException .class );
82+ }
83+
84+ @ Test
85+ public void shouldRejectQuestionMarkInPathParam () {
86+ String template = "/foo/:bar" ;
87+ Map <String , String > pathParams = ImmutableMap .of ("bar" , "?limit=500" );
88+ Map <String , Object > queryParams = ImmutableMap .of ();
89+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
90+ .isInstanceOf (IllegalArgumentException .class );
91+ }
92+
93+ @ Test
94+ public void shouldRejectFragmentMarkerInPathParam () {
95+ String template = "/foo/:bar" ;
96+ Map <String , String > pathParams = ImmutableMap .of ("bar" , "ID123#x" );
97+ Map <String , Object > queryParams = ImmutableMap .of ();
98+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
99+ .isInstanceOf (IllegalArgumentException .class );
100+ }
101+
102+ @ Test
103+ public void shouldRejectControlCharacterInPathParam () {
104+ String template = "/foo/:bar" ;
105+ Map <String , String > pathParams = ImmutableMap .of ("bar" , "ID123\n " );
106+ Map <String , Object > queryParams = ImmutableMap .of ();
107+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
108+ .isInstanceOf (IllegalArgumentException .class );
109+ }
110+
111+ @ Test
112+ public void shouldRejectDotPathParam () {
113+ String template = "/foo/:bar" ;
114+ Map <String , String > pathParams = ImmutableMap .of ("bar" , "." );
115+ Map <String , Object > queryParams = ImmutableMap .of ();
116+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
117+ .isInstanceOf (IllegalArgumentException .class );
118+ }
119+
120+ @ Test
121+ public void shouldRejectDoubleDotPathParam () {
122+ String template = "/foo/:bar" ;
123+ Map <String , String > pathParams = ImmutableMap .of ("bar" , ".." );
124+ Map <String , Object > queryParams = ImmutableMap .of ();
125+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
126+ .isInstanceOf (IllegalArgumentException .class );
127+ }
128+
129+ @ Test
130+ public void shouldRejectEmptyPathParam () {
131+ String template = "/foo/:bar" ;
132+ Map <String , String > pathParams = ImmutableMap .of ("bar" , "" );
133+ Map <String , Object > queryParams = ImmutableMap .of ();
134+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
135+ .isInstanceOf (IllegalArgumentException .class );
81136 }
82137
83138 @ Test
@@ -98,4 +153,55 @@ public void shouldSupportBaseUrlWithPath() {
98153 HttpUrl result = urlFormatter .formatUrl (template , pathParams , queryParams );
99154 assertThat (result .toString ()).isEqualTo ("http://example.com/direct/debit/ID123" );
100155 }
156+ // An absolute or scheme-relative path would replace the configured base URL while the
157+ // Authorization header is still attached, handing the token to whichever host it names.
158+
159+ @ Test
160+ public void shouldRejectAbsoluteUrlAsPath () {
161+ String template = "http://elsewhere.example.com/capture" ;
162+ Map <String , String > pathParams = ImmutableMap .of ();
163+ Map <String , Object > queryParams = ImmutableMap .of ();
164+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
165+ .isInstanceOf (IllegalArgumentException .class );
166+ }
167+
168+ @ Test
169+ public void shouldRejectSchemeRelativeUrlAsPath () {
170+ String template = "//elsewhere.example.com/capture" ;
171+ Map <String , String > pathParams = ImmutableMap .of ();
172+ Map <String , Object > queryParams = ImmutableMap .of ();
173+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
174+ .isInstanceOf (IllegalArgumentException .class );
175+ }
176+
177+ @ Test
178+ public void shouldRejectBackslashAuthorityAsPath () {
179+ // HttpUrl#resolve reads backslashes as slashes, so this is authority syntax that a
180+ // check on the raw string would be likely to miss.
181+ String template = "\\ \\ elsewhere.example.com/capture" ;
182+ Map <String , String > pathParams = ImmutableMap .of ();
183+ Map <String , Object > queryParams = ImmutableMap .of ();
184+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
185+ .isInstanceOf (IllegalArgumentException .class );
186+ }
187+
188+ @ Test
189+ public void shouldRejectAbsoluteUrlOnADifferentPortOfTheSameHost () {
190+ String template = "http://example.com:8080/capture" ;
191+ Map <String , String > pathParams = ImmutableMap .of ();
192+ Map <String , Object > queryParams = ImmutableMap .of ();
193+ assertThatThrownBy (() -> urlFormatter .formatUrl (template , pathParams , queryParams ))
194+ .isInstanceOf (IllegalArgumentException .class );
195+ }
196+
197+ @ Test
198+ public void shouldKeepDotSegmentsOnTheConfiguredBaseUrl () {
199+ // Dot segments resolve against the base URL, so they can reach another path on the
200+ // same origin but cannot leave it. They are allowed through.
201+ String template = "/foo/../other" ;
202+ Map <String , String > pathParams = ImmutableMap .of ();
203+ Map <String , Object > queryParams = ImmutableMap .of ();
204+ HttpUrl result = urlFormatter .formatUrl (template , pathParams , queryParams );
205+ assertThat (result .toString ()).isEqualTo ("http://example.com/other" );
206+ }
101207}
0 commit comments