Build query string from context instead of original request

Recreate query string from either getCurrentContext().getRequestQueryParams()
or original request as fallback. This allows to override query string
params in pre filters.

fixes gh-426
This commit is contained in:
Jakub Stachowski
2015-07-11 20:21:41 +02:00
committed by Spencer Gibb
parent 335481563f
commit dd1c5bb495
2 changed files with 55 additions and 3 deletions

View File

@@ -18,8 +18,10 @@ package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
@@ -259,10 +261,20 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
return httpclient.execute(httpHost, httpRequest);
}
private String getQueryString() {
private String getQueryString() throws UnsupportedEncodingException {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
String query = request.getQueryString();
return (query != null) ? "?" + query : "";
MultiValueMap<String, String> params=helper.buildZuulRequestQueryParams(request);
StringBuilder query=new StringBuilder();
for (Map.Entry<String, List<String>> entry : params.entrySet()) {
String key=URLEncoder.encode(entry.getKey(), "UTF-8");
for (String value : entry.getValue()) {
query.append("&");
query.append(key);
query.append("=");
query.append(URLEncoder.encode(value, "UTF-8"));
}
}
return (query.length()>0) ? "?" + query.substring(1) : "";
}
private HttpHost getHttpHost(URL host) {

View File

@@ -19,6 +19,9 @@ package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,6 +34,8 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.RoutesEndpoint;
import org.springframework.cloud.netflix.zuul.filters.ProxyRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.context.annotation.Bean;
@@ -42,10 +47,12 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.appinfo.EurekaInstanceConfig;
@@ -53,6 +60,7 @@ import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
@@ -153,6 +161,28 @@ public class SampleZuulProxyApplicationTests {
assertEquals("Hello space", result.getBody());
}
@Test
public void simpleHostRouteWithOriginalQString() {
routes.addRoute("/self/**", "http://localhost:" + this.port);
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/qstring?original=value1&original=value2", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Received {original=[value1, value2]}", result.getBody());
}
@Test
public void simpleHostRouteWithOverriddenQString() {
routes.addRoute("/self/**", "http://localhost:" + this.port);
this.endpoint.reset();
ResponseEntity<String> result = new TestRestTemplate().exchange(
"http://localhost:" + this.port + "/self/qstring?override=true&different=key", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals("Received {key=[overridden]}", result.getBody());
}
}
// Don't use @SpringBootApplication because we don't want to component scan
@@ -190,6 +220,11 @@ class SampleZuulProxyApplication {
return "Posted " + id + "!";
}
@RequestMapping(value = "/qstring")
public String qstring(@RequestParam MultiValueMap<String,String> params) {
return "Received "+params.toString();
}
@RequestMapping("/")
public String home() {
return "Hello world";
@@ -215,6 +250,11 @@ class SampleZuulProxyApplication {
@Override
public Object run() {
if (RequestContext.getCurrentContext().getRequest().getParameterMap().containsKey("override")) {
Map<String,List<String>> overridden=new HashMap<>();
overridden.put("key", Arrays.asList("overridden"));
RequestContext.getCurrentContext().setRequestQueryParams(overridden);
}
return null;
}