提交 3f525aa5 编写于 作者: A Allen Wang

First pass of enabling request URI built from variables and template.

上级 c8cd7998
package com.netflix.ribbonclientextensions.http;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import io.reactivex.netty.protocol.http.client.ContentSource;
import io.reactivex.netty.protocol.http.client.HttpClient;
import io.reactivex.netty.protocol.http.client.HttpClientRequest;
import io.reactivex.netty.protocol.http.client.RawContentSource;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixObservableCommand;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import com.netflix.ribbonclientextensions.RequestTemplate.RequestBuilder;
import com.netflix.ribbonclientextensions.RibbonRequest;
import com.netflix.ribbonclientextensions.template.ParsedTemplate;
import com.netflix.ribbonclientextensions.template.TemplateParser;
import com.netflix.ribbonclientextensions.template.TemplateParsingException;
class HttpRequestBuilder<I, O> extends RequestBuilder<O> {
public class HttpRequestBuilder<I, O> extends RequestBuilder<O> {
private HttpRequestTemplate<I, O> requestTemplate;
private HttpClient<I, O> client;
private HystrixObservableCommand.Setter setter;
private Map<String, String> vars;
private ParsedTemplate parsedUriTemplate;
HttpRequestBuilder(HttpClient<I, O> client, HttpRequestTemplate<I, O> requestTemplate, HystrixObservableCommand.Setter setter) {
this.requestTemplate = requestTemplate;
this.client = client;
this.setter = setter;
this.parsedUriTemplate = requestTemplate.uriTemplate();
vars = new ConcurrentHashMap<String, String>();
}
RibbonHystrixObservableCommand<I, O> createHystrixCommand() {
......@@ -25,10 +37,20 @@ class HttpRequestBuilder<I, O> extends RequestBuilder<O> {
}
@Override
public RequestBuilder<O> withValue(
public HttpRequestBuilder<I, O> withValue(
String key, Object value) {
return null;
vars.put(key, value.toString());
return this;
}
public HttpRequestBuilder<I, O> withContentSource(ContentSource<I> source) {
return this;
}
public HttpRequestBuilder<I, O> withRawContentSource(RawContentSource<?> raw) {
return this;
}
@Override
public RibbonRequest<O> build() {
......@@ -36,7 +58,13 @@ class HttpRequestBuilder<I, O> extends RequestBuilder<O> {
}
HttpClientRequest<I> createClientRequest() {
return HttpClientRequest.create(requestTemplate.method(), requestTemplate.uriTemplate());
String uri;
try {
uri = TemplateParser.toData(vars, parsedUriTemplate.getTemplate(), parsedUriTemplate.getParsed());
} catch (TemplateParsingException e) {
throw new HystrixBadRequestException("Problem parsing the URI template", e);
}
return HttpClientRequest.create(requestTemplate.method(), uri);
}
String cacheKey() {
......
package com.netflix.ribbonclientextensions.http;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.reactivex.netty.protocol.http.client.ContentSource;
import io.reactivex.netty.protocol.http.client.HttpClient;
import io.reactivex.netty.protocol.http.client.HttpClientResponse;
import io.reactivex.netty.protocol.http.client.RawContentSource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
import com.netflix.client.netty.LoadBalancingRxClient;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
......@@ -19,6 +23,7 @@ import com.netflix.ribbonclientextensions.CacheProvider;
import com.netflix.ribbonclientextensions.RequestTemplate;
import com.netflix.ribbonclientextensions.ResponseTransformer;
import com.netflix.ribbonclientextensions.hystrix.FallbackHandler;
import com.netflix.ribbonclientextensions.template.ParsedTemplate;
public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClientResponse<O>> {
......@@ -27,12 +32,13 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
private final int maxResponseTime;
private HystrixObservableCommand.Setter setter;
private FallbackHandler<O> fallbackHandler;
private String uri;
private ParsedTemplate parsedUriTemplate;
private ResponseTransformer<HttpClientResponse<O>> transformer;
private HttpMethod method;
private String name;
private List<CacheProvider<O>> cacheProviders;
private String cacheKeyTemplate;
private Map<String, ParsedTemplate> parsedTemplates;
public HttpRequestTemplate(String name, HttpClient<I, O> client) {
this.client = client;
......@@ -48,6 +54,7 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
// default method to GET
method = HttpMethod.GET;
cacheProviders = new LinkedList<CacheProvider<O>>();
parsedTemplates = new HashMap<String, ParsedTemplate>();
}
@Override
......@@ -57,7 +64,7 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
}
@Override
public RequestBuilder<O> requestBuilder() {
public HttpRequestBuilder<I, O> requestBuilder() {
// TODO: apply hystrix properties passed in to the template
if (setter == null) {
setter = HystrixObservableCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(clientName))
......@@ -72,8 +79,17 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
return this;
}
private ParsedTemplate createParsedTemplate(String template) {
ParsedTemplate parsedTemplate = parsedTemplates.get(template);
if (parsedTemplate == null) {
parsedTemplate = ParsedTemplate.create(template);
parsedTemplates.put(template, parsedTemplate);
}
return parsedTemplate;
}
public HttpRequestTemplate<I, O> withUri(String uri) {
this.uri = uri;
this.parsedUriTemplate = createParsedTemplate(uri);
return this;
}
......@@ -81,14 +97,6 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
return this;
}
public HttpRequestTemplate<I, O> withContentSource(ContentSource<I> source) {
return this;
}
public HttpRequestTemplate<I, O> withRawContentSource(RawContentSource<?> raw) {
return this;
}
@Override
public HttpRequestTemplate<I, O> withCacheKey(
String cacheKeyTemplate) {
......@@ -119,8 +127,8 @@ public class HttpRequestTemplate<I, O> implements RequestTemplate<I, O, HttpClie
return fallbackHandler;
}
String uriTemplate() {
return uri;
ParsedTemplate uriTemplate() {
return parsedUriTemplate;
}
HttpMethod method() {
......
package com.netflix.ribbonclientextensions.template;
import java.util.List;
public class ParsedTemplate {
private List<Object> parsed;
private String template;
public ParsedTemplate(List<Object> parsed, String template) {
super();
this.parsed = parsed;
this.template = template;
}
public final List<Object> getParsed() {
return parsed;
}
public final String getTemplate() {
return template;
}
public static ParsedTemplate create(String template) {
List<Object> parsed = TemplateParser.parseTemplate(template);
return new ParsedTemplate(parsed, template);
}
}
package com.netflix.ribbonclientextensions.template;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Maps;
/**
* Created by mcohen on 5/1/14.
*/
......@@ -46,7 +46,7 @@ public class TemplateParser {
return templateParts;
}
public static String toData(Map<String, String> variables, String template, List parsedList) throws URISyntaxException {
public static String toData(Map<String, String> variables, String template, List<Object> parsedList) throws TemplateParsingException {
int params = variables.size();
// skip expansion if there's no valid variables set. ex. {a} is the
// first valid
......@@ -65,13 +65,13 @@ public class TemplateParser {
}
} else if (part instanceof PathVar) {
if (var == null) {
throw new URISyntaxException(template, String.format("template variable %s was not supplied", part.toString()));
throw new TemplateParsingException(String.format("template variable %s was not supplied for template %s", part.toString(), template));
} else {
builder.append(var);
params--;
}
} else {
throw new URISyntaxException(template, String.format("template variable type %s is not supplied", part.getClass().getCanonicalName()));
throw new TemplateParsingException(String.format("template variable type %s is not supplied for template template %s", part.getClass().getCanonicalName(), template));
}
} else {
builder.append(part.toString());
......@@ -80,4 +80,14 @@ public class TemplateParser {
return builder.toString();
}
public static void main(String[] args) throws TemplateParsingException {
String template = "/abc/{id}?name={name}";
Map<String, String> vars = Maps.newHashMap();
vars.put("id", "5");
vars.put("name", "netflix");
List<Object> list = parseTemplate(template);
System.out.println(toData(vars, template, list));
}
}
package com.netflix.ribbonclientextensions.template;
public class TemplateParsingException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1910187667077051723L;
public TemplateParsingException(String arg0, Throwable arg1) {
super(arg0, arg1);
}
public TemplateParsingException(String arg0) {
super(arg0);
}
}
package com.netflix.ribbonclientextensions.http;
import static org.junit.Assert.*;
import io.netty.buffer.ByteBuf;
import io.reactivex.netty.RxNetty;
import io.reactivex.netty.protocol.http.client.HttpClientRequest;
import org.junit.Test;
import com.netflix.ribbonclientextensions.Ribbon;
public class TemplateBuilderTest {
@Test
public void testVarReplacement() {
HttpRequestTemplate<ByteBuf, ByteBuf> template = Ribbon.newHttpRequestTemplate("test",
RxNetty.createHttpClient("foo", 1234));
template.withUri("/foo/{id}?name={name}");
HttpClientRequest<ByteBuf> request = template
.requestBuilder()
.withValue("id", "3")
.withValue("name", "netflix")
.createClientRequest();
assertEquals("/foo/3?name=netflix", request.getUri());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册