|
@@ -38,8 +38,11 @@ import org.elasticsearch.index.shard.ShardId;
|
|
|
import org.elasticsearch.rest.RestStatus;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
import java.net.URI;
|
|
|
import java.net.URISyntaxException;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.nio.charset.Charset;
|
|
|
import java.util.Locale;
|
|
|
|
|
|
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
|
@@ -201,31 +204,43 @@ public abstract class DocWriteResponse extends ReplicationResponse implements Wr
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Gets the location of the written document as a string suitable for a {@code Location} header.
|
|
|
- * @param routing any routing used in the request. If null the location doesn't include routing information.
|
|
|
+ * Return the relative URI for the location of the document suitable for use in the {@code Location} header. The use of relative URIs is
|
|
|
+ * permitted as of HTTP/1.1 (cf. https://tools.ietf.org/html/rfc7231#section-7.1.2).
|
|
|
*
|
|
|
+ * @param routing custom routing or {@code null} if custom routing is not used
|
|
|
+ * @return the relative URI for the location of the document
|
|
|
*/
|
|
|
- public String getLocation(@Nullable String routing) throws URISyntaxException {
|
|
|
- // Absolute path for the location of the document. This should be allowed as of HTTP/1.1:
|
|
|
- // https://tools.ietf.org/html/rfc7231#section-7.1.2
|
|
|
- String index = getIndex();
|
|
|
- String type = getType();
|
|
|
- String id = getId();
|
|
|
- String routingStart = "?routing=";
|
|
|
- int bufferSize = 3 + index.length() + type.length() + id.length();
|
|
|
- if (routing != null) {
|
|
|
- bufferSize += routingStart.length() + routing.length();
|
|
|
+ public String getLocation(@Nullable String routing) {
|
|
|
+ final String encodedIndex;
|
|
|
+ final String encodedType;
|
|
|
+ final String encodedId;
|
|
|
+ final String encodedRouting;
|
|
|
+ try {
|
|
|
+ // encode the path components separately otherwise the path separators will be encoded
|
|
|
+ encodedIndex = URLEncoder.encode(getIndex(), "UTF-8");
|
|
|
+ encodedType = URLEncoder.encode(getType(), "UTF-8");
|
|
|
+ encodedId = URLEncoder.encode(getId(), "UTF-8");
|
|
|
+ encodedRouting = routing == null ? null : URLEncoder.encode(routing, "UTF-8");
|
|
|
+ } catch (final UnsupportedEncodingException e) {
|
|
|
+ throw new AssertionError(e);
|
|
|
}
|
|
|
- StringBuilder location = new StringBuilder(bufferSize);
|
|
|
- location.append('/').append(index);
|
|
|
- location.append('/').append(type);
|
|
|
- location.append('/').append(id);
|
|
|
- if (routing != null) {
|
|
|
- location.append(routingStart).append(routing);
|
|
|
+ final String routingStart = "?routing=";
|
|
|
+ final int bufferSizeExcludingRouting = 3 + encodedIndex.length() + encodedType.length() + encodedId.length();
|
|
|
+ final int bufferSize;
|
|
|
+ if (encodedRouting == null) {
|
|
|
+ bufferSize = bufferSizeExcludingRouting;
|
|
|
+ } else {
|
|
|
+ bufferSize = bufferSizeExcludingRouting + routingStart.length() + encodedRouting.length();
|
|
|
+ }
|
|
|
+ final StringBuilder location = new StringBuilder(bufferSize);
|
|
|
+ location.append('/').append(encodedIndex);
|
|
|
+ location.append('/').append(encodedType);
|
|
|
+ location.append('/').append(encodedId);
|
|
|
+ if (encodedRouting != null) {
|
|
|
+ location.append(routingStart).append(encodedRouting);
|
|
|
}
|
|
|
|
|
|
- URI uri = new URI(location.toString());
|
|
|
- return uri.toASCIIString();
|
|
|
+ return location.toString();
|
|
|
}
|
|
|
|
|
|
@Override
|