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; ...@@ -18,8 +18,10 @@ package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket; import java.net.Socket;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
...@@ -259,10 +261,20 @@ public class SimpleHostRoutingFilter extends ZuulFilter { ...@@ -259,10 +261,20 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
return httpclient.execute(httpHost, httpRequest); return httpclient.execute(httpHost, httpRequest);
} }
private String getQueryString() { private String getQueryString() throws UnsupportedEncodingException {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest(); HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
String query = request.getQueryString(); MultiValueMap<String, String> params=helper.buildZuulRequestQueryParams(request);
return (query != null) ? "?" + query : ""; 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) { private HttpHost getHttpHost(URL host) {
......
...@@ -19,6 +19,9 @@ package org.springframework.cloud.netflix.zuul; ...@@ -19,6 +19,9 @@ package org.springframework.cloud.netflix.zuul;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -31,6 +34,8 @@ import org.springframework.boot.test.SpringApplicationConfiguration; ...@@ -31,6 +34,8 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate; import org.springframework.boot.test.TestRestTemplate;
import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients; 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.ProxyRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -42,10 +47,12 @@ import org.springframework.http.ResponseEntity; ...@@ -42,10 +47,12 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; 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.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.netflix.appinfo.EurekaInstanceConfig; import com.netflix.appinfo.EurekaInstanceConfig;
...@@ -53,6 +60,7 @@ import com.netflix.loadbalancer.BaseLoadBalancer; ...@@ -53,6 +60,7 @@ import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.Server;
import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class) @SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
...@@ -153,6 +161,28 @@ public class SampleZuulProxyApplicationTests { ...@@ -153,6 +161,28 @@ public class SampleZuulProxyApplicationTests {
assertEquals("Hello space", result.getBody()); 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 // Don't use @SpringBootApplication because we don't want to component scan
...@@ -190,6 +220,11 @@ class SampleZuulProxyApplication { ...@@ -190,6 +220,11 @@ class SampleZuulProxyApplication {
return "Posted " + id + "!"; return "Posted " + id + "!";
} }
@RequestMapping(value = "/qstring")
public String qstring(@RequestParam MultiValueMap<String,String> params) {
return "Received "+params.toString();
}
@RequestMapping("/") @RequestMapping("/")
public String home() { public String home() {
return "Hello world"; return "Hello world";
...@@ -215,6 +250,11 @@ class SampleZuulProxyApplication { ...@@ -215,6 +250,11 @@ class SampleZuulProxyApplication {
@Override @Override
public Object run() { 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; 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