Commit dd1c5bb4 by Jakub Stachowski Committed by Spencer Gibb

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
parent 33548156
......@@ -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) {
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment