Watcher: Allow url as shortcut in requests

Instead of having to specify `scheme`, `host`, `port`, `path` and `params` each
one can now use the `url` field and specify something like `http://example.org/foo?bar=baz`

This works for HttpRequest and HttpRequestTemplate

Original commit: elastic/x-pack-elasticsearch@8c052cf419
This commit is contained in:
Alexander Reelsen 2015-12-30 11:44:28 +01:00
parent cc0933733c
commit d3ced7161b
3 changed files with 92 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
@ -16,6 +17,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.support.RestUtils;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.http.auth.HttpAuth;
@ -23,6 +25,8 @@ import org.elasticsearch.watcher.support.http.auth.HttpAuthRegistry;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
@ -295,6 +299,8 @@ public class HttpRequest implements ToXContent {
builder.path(parser.text());
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.BODY)) {
builder.body(parser.text());
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.URL)) {
builder.fromUrl(parser.text());
} else {
throw new ElasticsearchParseException("could not parse http request. unexpected string field [{}]", currentFieldName);
}
@ -427,6 +433,25 @@ public class HttpRequest implements ToXContent {
headers = null;
return request;
}
public Builder fromUrl(String supposedUrl) {
try {
URI uri = new URI(supposedUrl);
port = uri.getPort() > 0 ? uri.getPort() : 80;
host = uri.getHost();
scheme = Scheme.parse(uri.getScheme());
if (Strings.hasLength(uri.getPath())) {
path = uri.getPath();
}
String rawQuery = uri.getRawQuery();
if (Strings.hasLength(rawQuery)) {
RestUtils.decodeQueryString(rawQuery, 0, params);
}
} catch (URISyntaxException e) {
throw new ElasticsearchParseException("Malformed URL [{}]", supposedUrl);
}
return this;
}
}
public interface Field {
@ -442,5 +467,6 @@ public class HttpRequest implements ToXContent {
ParseField CONNECTION_TIMEOUT = new ParseField("connection_timeout");
ParseField READ_TIMEOUT = new ParseField("read_timeout");
ParseField PROXY = new ParseField("proxy");
ParseField URL = new ParseField("url");
}
}

View File

@ -8,12 +8,14 @@ package org.elasticsearch.watcher.support.http;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.support.RestUtils;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.http.HttpRequest.Field;
import org.elasticsearch.watcher.support.http.auth.HttpAuth;
@ -23,6 +25,8 @@ import org.elasticsearch.watcher.support.text.TextTemplateEngine;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
@ -272,6 +276,8 @@ public class HttpRequestTemplate implements ToXContent {
builder.putParams(parseFieldTemplates(currentFieldName, parser));
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.BODY)) {
builder.body(parseFieldTemplate(currentFieldName, parser));
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.URL)) {
builder.fromUrl(parser.text());
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.CONNECTION_TIMEOUT)) {
try {
builder.connectionTimeout(WatcherDateTimeUtils.parseTimeValue(parser, Field.CONNECTION_TIMEOUT.toString()));
@ -460,6 +466,30 @@ public class HttpRequestTemplate implements ToXContent {
return new HttpRequestTemplate(host, port, scheme, method, path, unmodifiableMap(new HashMap<>(params)),
unmodifiableMap(new HashMap<>(headers)), auth, body, connectionTimeout, readTimeout, proxy);
}
public Builder fromUrl(String supposedUrl) {
try {
URI uri = new URI(supposedUrl);
port = uri.getPort() > 0 ? uri.getPort() : 80;
host = uri.getHost();
scheme = Scheme.parse(uri.getScheme());
if (Strings.hasLength(uri.getPath())) {
path = TextTemplate.inline(uri.getPath()).build();
}
String rawQuery = uri.getRawQuery();
if (Strings.hasLength(rawQuery)) {
Map<String, String> stringParams = new HashMap<>();
RestUtils.decodeQueryString(rawQuery, 0, stringParams);
for (Map.Entry<String, String> entry : stringParams.entrySet()) {
params.put(entry.getKey(), TextTemplate.inline(entry.getValue()).build());
}
}
} catch (URISyntaxException e) {
throw new ElasticsearchParseException("Malformed URI [{}]", supposedUrl);
}
return this;
}
}
}

View File

@ -5,12 +5,15 @@
*/
package org.elasticsearch.watcher.support.http;
import com.google.common.collect.Lists;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.search.aggregations.support.format.ValueParser;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.watcher.support.http.auth.HttpAuthRegistry;
import org.elasticsearch.watcher.support.http.auth.basic.BasicAuth;
@ -21,6 +24,7 @@ import org.elasticsearch.watcher.support.text.TextTemplateEngine;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static java.util.Collections.emptyMap;
@ -133,6 +137,38 @@ public class HttpRequestTemplateTests extends ESTestCase {
assertThat(parsed, equalTo(template));
}
public void testParsingFromUrl() throws Exception {
HttpRequestTemplate.Builder builder = HttpRequestTemplate.builder("www.example.org", 1234);
builder.path("/foo/bar/org");
builder.putParam("param", TextTemplate.inline("test"));
builder.scheme(Scheme.HTTPS);
assertThatManualBuilderEqualsParsingFromUrl("https://www.example.org:1234/foo/bar/org?param=test", builder);
// test without specifying port
builder = HttpRequestTemplate.builder("www.example.org", 80);
assertThatManualBuilderEqualsParsingFromUrl("http://www.example.org", builder);
// encoded values
builder = HttpRequestTemplate.builder("www.example.org", 80).putParam("foo", TextTemplate.inline(" white space"));
assertThatManualBuilderEqualsParsingFromUrl("http://www.example.org?foo=%20white%20space", builder);
}
private void assertThatManualBuilderEqualsParsingFromUrl(String url, HttpRequestTemplate.Builder builder) throws Exception {
XContentBuilder urlContentBuilder = jsonBuilder().startObject().field("url", url).endObject();
XContentParser urlContentParser = JsonXContent.jsonXContent.createParser(urlContentBuilder.bytes());
urlContentParser.nextToken();
HttpRequestTemplate.Parser parser = new HttpRequestTemplate.Parser(mock(HttpAuthRegistry.class));
HttpRequestTemplate urlParsedTemplate = parser.parse(urlContentParser);
XContentBuilder xContentBuilder = builder.build().toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS);
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(xContentBuilder.bytes());
xContentParser.nextToken();
HttpRequestTemplate parsedTemplate = parser.parse(xContentParser);
assertThat(parsedTemplate, is(urlParsedTemplate));
}
static class MockTextTemplateEngine implements TextTemplateEngine {
@Override
public String render(TextTemplate template, Map<String, Object> model) {