Promote headers to first class citizens on exceptions
This commit merges the pre-existing special exception that allowed to associate headers with exceptions and the elasticsaerch base class `ElasticsearchException` This allows for more generic use of exceptions where plugins can associate meta-data with any elasticsearch base exception to control behavior etc. This also addds a generic SecurityException to allow plugins to pass on information based on the RestStatus.
This commit is contained in:
parent
3084bed194
commit
20d0b4f446
|
@ -19,18 +19,13 @@
|
||||||
|
|
||||||
package org.elasticsearch;
|
package org.elasticsearch;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
|
||||||
import org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper;
|
import org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
import org.elasticsearch.common.logging.support.LoggerMessageFormat;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.rest.HasRestHeaders;
|
|
||||||
import org.elasticsearch.rest.RestStatus;
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -45,6 +40,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
||||||
|
|
||||||
public static final String REST_EXCEPTION_SKIP_CAUSE = "rest.exception.skip_cause";
|
public static final String REST_EXCEPTION_SKIP_CAUSE = "rest.exception.skip_cause";
|
||||||
private static final Map<String, Constructor<? extends ElasticsearchException>> MAPPING;
|
private static final Map<String, Constructor<? extends ElasticsearchException>> MAPPING;
|
||||||
|
private final Map<String, List<String>> headers = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a <code>ElasticsearchException</code> with the specified detail message.
|
* Construct a <code>ElasticsearchException</code> with the specified detail message.
|
||||||
|
@ -77,6 +73,48 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
||||||
public ElasticsearchException(StreamInput in) throws IOException {
|
public ElasticsearchException(StreamInput in) throws IOException {
|
||||||
super(in.readOptionalString(), in.readThrowable());
|
super(in.readOptionalString(), in.readThrowable());
|
||||||
readStackTrace(this, in);
|
readStackTrace(this, in);
|
||||||
|
int numKeys = in.readVInt();
|
||||||
|
for (int i = 0; i < numKeys; i++) {
|
||||||
|
final String key = in.readString();
|
||||||
|
final int numValues = in.readVInt();
|
||||||
|
final ArrayList<String> values = new ArrayList<>(numValues);
|
||||||
|
for (int j = 0; j < numValues; j++) {
|
||||||
|
values.add(in.readString());
|
||||||
|
}
|
||||||
|
headers.put(key, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new header with the given key.
|
||||||
|
* This method will replace existing header if a header with the same key already exists
|
||||||
|
*/
|
||||||
|
public void addHeader(String key, String... value) {
|
||||||
|
this.headers.put(key, Arrays.asList(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new header with the given key.
|
||||||
|
* This method will replace existing header if a header with the same key already exists
|
||||||
|
*/
|
||||||
|
public void addHeader(String key, List<String> value) {
|
||||||
|
this.headers.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set of all header keys on this exception
|
||||||
|
*/
|
||||||
|
public Set<String> getHeaderKeys() {
|
||||||
|
return headers.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of header values for the given key or {@code null} if not header for the
|
||||||
|
* given key exists.
|
||||||
|
*/
|
||||||
|
public List<String> getHeader(String key) {
|
||||||
|
return headers.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,6 +211,14 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
||||||
out.writeOptionalString(this.getMessage());
|
out.writeOptionalString(this.getMessage());
|
||||||
out.writeThrowable(this.getCause());
|
out.writeThrowable(this.getCause());
|
||||||
writeStackTraces(this, out);
|
writeStackTraces(this, out);
|
||||||
|
out.writeVInt(headers.size());
|
||||||
|
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
|
out.writeString(entry.getKey());
|
||||||
|
out.writeVInt(entry.getValue().size());
|
||||||
|
for (String v : entry.getValue()) {
|
||||||
|
out.writeString(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ElasticsearchException readException(StreamInput input, String name) throws IOException {
|
public static ElasticsearchException readException(StreamInput input, String name) throws IOException {
|
||||||
|
@ -198,79 +244,6 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
||||||
return MAPPING.keySet();
|
return MAPPING.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A base class for exceptions that should carry rest headers
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static class WithRestHeadersException extends ElasticsearchException implements HasRestHeaders {
|
|
||||||
|
|
||||||
private final Map<String, List<String>> headers;
|
|
||||||
|
|
||||||
public WithRestHeadersException(String msg, Tuple<String, String[]>... headers) {
|
|
||||||
super(msg);
|
|
||||||
this.headers = headers(headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected WithRestHeadersException(String msg, Throwable cause, Map<String, List<String>> headers) {
|
|
||||||
super(msg, cause);
|
|
||||||
this.headers = headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WithRestHeadersException(StreamInput in) throws IOException {
|
|
||||||
super(in);
|
|
||||||
int numKeys = in.readVInt();
|
|
||||||
ImmutableMap.Builder<String, List<String>> builder = ImmutableMap.builder();
|
|
||||||
for (int i = 0; i < numKeys; i++) {
|
|
||||||
final String key = in.readString();
|
|
||||||
final int numValues = in.readVInt();
|
|
||||||
final ArrayList<String> headers = new ArrayList<>(numValues);
|
|
||||||
for (int j = 0; j < numValues; j++) {
|
|
||||||
headers.add(in.readString());
|
|
||||||
}
|
|
||||||
builder.put(key, headers);
|
|
||||||
}
|
|
||||||
headers = builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
|
||||||
super.writeTo(out);
|
|
||||||
out.writeVInt(headers.size());
|
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
|
||||||
out.writeString(entry.getKey());
|
|
||||||
out.writeVInt(entry.getValue().size());
|
|
||||||
for (String v : entry.getValue()) {
|
|
||||||
out.writeString(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, List<String>> getHeaders() {
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Tuple<String, String[]> header(String name, String... values) {
|
|
||||||
return Tuple.tuple(name, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, List<String>> headers(Tuple<String, String[]>... headers) {
|
|
||||||
Map<String, List<String>> map = Maps.newHashMap();
|
|
||||||
for (Tuple<String, String[]> header : headers) {
|
|
||||||
List<String> list = map.get(header.v1());
|
|
||||||
if (list == null) {
|
|
||||||
list = Lists.newArrayList(header.v2());
|
|
||||||
map.put(header.v1(), list);
|
|
||||||
} else {
|
|
||||||
for (String value : header.v2()) {
|
|
||||||
list.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ImmutableMap.copyOf(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
if (this instanceof ElasticsearchWrapperException) {
|
if (this instanceof ElasticsearchWrapperException) {
|
||||||
|
@ -559,7 +532,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
||||||
org.elasticsearch.action.PrimaryMissingActionException.class,
|
org.elasticsearch.action.PrimaryMissingActionException.class,
|
||||||
org.elasticsearch.index.engine.CreateFailedEngineException.class,
|
org.elasticsearch.index.engine.CreateFailedEngineException.class,
|
||||||
org.elasticsearch.index.shard.IllegalIndexShardStateException.class,
|
org.elasticsearch.index.shard.IllegalIndexShardStateException.class,
|
||||||
WithRestHeadersException.class,
|
ElasticsearchSecurityException.class,
|
||||||
NotSerializableExceptionWrapper.class
|
NotSerializableExceptionWrapper.class
|
||||||
};
|
};
|
||||||
Map<String, Constructor<? extends ElasticsearchException>> mapping = new HashMap<>(exceptions.length);
|
Map<String, Constructor<? extends ElasticsearchException>> mapping = new HashMap<>(exceptions.length);
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic security exception
|
||||||
|
*/
|
||||||
|
public class ElasticsearchSecurityException extends ElasticsearchException {
|
||||||
|
|
||||||
|
private final RestStatus status;
|
||||||
|
|
||||||
|
public ElasticsearchSecurityException(String msg, RestStatus status, Throwable cause, Object... args) {
|
||||||
|
super(msg, cause, args);
|
||||||
|
this.status = status ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticsearchSecurityException(String msg, Throwable cause, Object... args) {
|
||||||
|
this(msg, ExceptionsHelper.status(cause), cause, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticsearchSecurityException(String msg, Object... args) {
|
||||||
|
this(msg, RestStatus.INTERNAL_SERVER_ERROR, null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticsearchSecurityException(String msg, RestStatus status, Object... args) {
|
||||||
|
this(msg, status, null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticsearchSecurityException(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
status = RestStatus.readFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
RestStatus.writeTo(out, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final RestStatus status() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,13 +21,9 @@ package org.elasticsearch.common.io.stream;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.ExceptionsHelper;
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
|
||||||
import org.elasticsearch.rest.RestStatus;
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception can be used to wrap a given, not serializable exception
|
* This exception can be used to wrap a given, not serializable exception
|
||||||
|
@ -36,27 +32,25 @@ import java.util.Map;
|
||||||
* the throwable it was created with instead of it's own. The stacktrace has no indication
|
* the throwable it was created with instead of it's own. The stacktrace has no indication
|
||||||
* of where this exception was created.
|
* of where this exception was created.
|
||||||
*/
|
*/
|
||||||
public final class NotSerializableExceptionWrapper extends ElasticsearchException.WithRestHeadersException {
|
public final class NotSerializableExceptionWrapper extends ElasticsearchException {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final RestStatus status;
|
private final RestStatus status;
|
||||||
|
|
||||||
public NotSerializableExceptionWrapper(Throwable other, Map<String, List<String>> headers) {
|
public NotSerializableExceptionWrapper(Throwable other) {
|
||||||
super(other.getMessage(), other.getCause(), headers);
|
super(other.getMessage(), other.getCause());
|
||||||
this.name = ElasticsearchException.getExceptionName(other);
|
this.name = ElasticsearchException.getExceptionName(other);
|
||||||
this.status = ExceptionsHelper.status(other);
|
this.status = ExceptionsHelper.status(other);
|
||||||
setStackTrace(other.getStackTrace());
|
setStackTrace(other.getStackTrace());
|
||||||
for (Throwable otherSuppressed : other.getSuppressed()) {
|
for (Throwable otherSuppressed : other.getSuppressed()) {
|
||||||
addSuppressed(otherSuppressed);
|
addSuppressed(otherSuppressed);
|
||||||
}
|
}
|
||||||
}
|
if (other instanceof ElasticsearchException) {
|
||||||
|
ElasticsearchException ex = (ElasticsearchException) other;
|
||||||
public NotSerializableExceptionWrapper(WithRestHeadersException other) {
|
for (String key : ex.getHeaderKeys()) {
|
||||||
this(other, other.getHeaders());
|
this.addHeader(key, ex.getHeader(key));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public NotSerializableExceptionWrapper(Throwable other) {
|
|
||||||
this(other, Collections.EMPTY_MAP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotSerializableExceptionWrapper(StreamInput in) throws IOException {
|
public NotSerializableExceptionWrapper(StreamInput in) throws IOException {
|
||||||
|
|
|
@ -511,9 +511,6 @@ public abstract class StreamOutput extends OutputStream {
|
||||||
final String name = throwable.getClass().getName();
|
final String name = throwable.getClass().getName();
|
||||||
if (throwable instanceof ElasticsearchException && ElasticsearchException.isRegistered(name)) {
|
if (throwable instanceof ElasticsearchException && ElasticsearchException.isRegistered(name)) {
|
||||||
ex = (ElasticsearchException) throwable;
|
ex = (ElasticsearchException) throwable;
|
||||||
} else if (throwable instanceof ElasticsearchException.WithRestHeadersException) {
|
|
||||||
// ensure we transport also the headers
|
|
||||||
ex = new NotSerializableExceptionWrapper((ElasticsearchException.WithRestHeadersException)throwable);
|
|
||||||
} else {
|
} else {
|
||||||
ex = new NotSerializableExceptionWrapper(throwable);
|
ex = new NotSerializableExceptionWrapper(throwable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.rest;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.ExceptionsHelper;
|
import org.elasticsearch.ExceptionsHelper;
|
||||||
|
import org.elasticsearch.bootstrap.Elasticsearch;
|
||||||
import org.elasticsearch.common.bytes.BytesArray;
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
|
@ -94,8 +95,8 @@ public class BytesRestResponse extends RestResponse {
|
||||||
this.content = builder.bytes();
|
this.content = builder.bytes();
|
||||||
this.contentType = builder.contentType().restContentType();
|
this.contentType = builder.contentType().restContentType();
|
||||||
}
|
}
|
||||||
if (t instanceof HasRestHeaders) {
|
if (t instanceof ElasticsearchException) {
|
||||||
addHeaders(((HasRestHeaders) t).getHeaders());
|
copyHeaders(((ElasticsearchException) t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to Elasticsearch under one or more contributor
|
|
||||||
* license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright
|
|
||||||
* ownership. Elasticsearch licenses this file to you under
|
|
||||||
* the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
* not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.elasticsearch.rest;
|
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classes that carry rest headers should implement this interface. Specifically, exceptions that
|
|
||||||
* get translated to a rest response, can implement this interface and the headers will be added
|
|
||||||
* the the response.
|
|
||||||
*
|
|
||||||
* @see ElasticsearchException.WithRestHeadersException
|
|
||||||
*/
|
|
||||||
public interface HasRestHeaders {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The rest headers
|
|
||||||
*/
|
|
||||||
Map<String, List<String>> getHeaders();
|
|
||||||
}
|
|
|
@ -20,19 +20,16 @@
|
||||||
package org.elasticsearch.rest;
|
package org.elasticsearch.rest;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class RestResponse implements HasRestHeaders {
|
public abstract class RestResponse {
|
||||||
|
|
||||||
protected Map<String, List<String>> customHeaders;
|
protected Map<String, List<String>> customHeaders;
|
||||||
|
|
||||||
|
@ -53,17 +50,18 @@ public abstract class RestResponse implements HasRestHeaders {
|
||||||
*/
|
*/
|
||||||
public abstract RestStatus status();
|
public abstract RestStatus status();
|
||||||
|
|
||||||
public void addHeaders(Map<String, List<String>> headers) {
|
public void copyHeaders(ElasticsearchException ex) {
|
||||||
|
Set<String> headerKeySet = ex.getHeaderKeys();
|
||||||
if (customHeaders == null) {
|
if (customHeaders == null) {
|
||||||
customHeaders = new HashMap<>(headers.size());
|
customHeaders = new HashMap<>(headerKeySet.size());
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
for (String key : headerKeySet) {
|
||||||
List<String> values = customHeaders.get(entry.getKey());
|
List<String> values = customHeaders.get(key);
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
values = Lists.newArrayList();
|
values = Lists.newArrayList();
|
||||||
customHeaders.put(entry.getKey(), values);
|
customHeaders.put(key, values);
|
||||||
}
|
}
|
||||||
values.addAll(entry.getValue());
|
values.addAll(ex.getHeader(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +83,6 @@ public abstract class RestResponse implements HasRestHeaders {
|
||||||
/**
|
/**
|
||||||
* Returns custom headers that have been added, or null if none have been set.
|
* Returns custom headers that have been added, or null if none have been set.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Map<String, List<String>> getHeaders() {
|
public Map<String, List<String>> getHeaders() {
|
||||||
return customHeaders;
|
return customHeaders;
|
||||||
|
|
|
@ -265,7 +265,7 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase {
|
||||||
new IllegalArgumentException("alalaal"),
|
new IllegalArgumentException("alalaal"),
|
||||||
new NullPointerException("boom"),
|
new NullPointerException("boom"),
|
||||||
new EOFException("dadada"),
|
new EOFException("dadada"),
|
||||||
new SecurityException("nono!"),
|
new ElasticsearchSecurityException("nono!"),
|
||||||
new NumberFormatException("not a number"),
|
new NumberFormatException("not a number"),
|
||||||
new CorruptIndexException("baaaam", "this is my resource"),
|
new CorruptIndexException("baaaam", "this is my resource"),
|
||||||
new IndexFormatTooNewException("tooo new", 1, 1, 1),
|
new IndexFormatTooNewException("tooo new", 1, 1, 1),
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.elasticsearch.cluster.metadata.SnapshotId;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
import org.elasticsearch.cluster.routing.*;
|
import org.elasticsearch.cluster.routing.*;
|
||||||
import org.elasticsearch.common.breaker.CircuitBreakingException;
|
import org.elasticsearch.common.breaker.CircuitBreakingException;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
|
||||||
import org.elasticsearch.common.io.PathUtils;
|
import org.elasticsearch.common.io.PathUtils;
|
||||||
import org.elasticsearch.common.io.stream.*;
|
import org.elasticsearch.common.io.stream.*;
|
||||||
import org.elasticsearch.common.transport.LocalTransportAddress;
|
import org.elasticsearch.common.transport.LocalTransportAddress;
|
||||||
|
@ -583,30 +582,35 @@ public class ExceptionSerializationTests extends ElasticsearchTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWithRestHeadersException() throws IOException {
|
public void testWithRestHeadersException() throws IOException {
|
||||||
ElasticsearchException.WithRestHeadersException ex = serialize(new ElasticsearchException.WithRestHeadersException("msg", new Tuple("foo", new String[]{"foo", "bar"})));
|
ElasticsearchException ex = new ElasticsearchException("msg");
|
||||||
|
ex.addHeader("foo", "foo", "bar");
|
||||||
|
ex = serialize(ex);
|
||||||
assertEquals("msg", ex.getMessage());
|
assertEquals("msg", ex.getMessage());
|
||||||
assertEquals(2, ex.getHeaders().get("foo").size());
|
assertEquals(2, ex.getHeader("foo").size());
|
||||||
assertEquals("foo", ex.getHeaders().get("foo").get(0));
|
assertEquals("foo", ex.getHeader("foo").get(0));
|
||||||
assertEquals("bar", ex.getHeaders().get("foo").get(1));
|
assertEquals("bar", ex.getHeader("foo").get(1));
|
||||||
|
|
||||||
RestStatus status = randomFrom(RestStatus.values());
|
RestStatus status = randomFrom(RestStatus.values());
|
||||||
// ensure we are carrying over the headers even if not serialized
|
// ensure we are carrying over the headers even if not serialized
|
||||||
ElasticsearchException serialize = serialize((ElasticsearchException) new UnknownHeaderException("msg", status, new Tuple("foo", new String[]{"foo", "bar"})));
|
UnknownHeaderException uhe = new UnknownHeaderException("msg", status);
|
||||||
|
uhe.addHeader("foo", "foo", "bar");
|
||||||
|
|
||||||
|
ElasticsearchException serialize = serialize((ElasticsearchException)uhe);
|
||||||
assertTrue(serialize instanceof NotSerializableExceptionWrapper);
|
assertTrue(serialize instanceof NotSerializableExceptionWrapper);
|
||||||
NotSerializableExceptionWrapper e = (NotSerializableExceptionWrapper) serialize;
|
NotSerializableExceptionWrapper e = (NotSerializableExceptionWrapper) serialize;
|
||||||
assertEquals("msg", e.getMessage());
|
assertEquals("msg", e.getMessage());
|
||||||
assertEquals(2, e.getHeaders().get("foo").size());
|
assertEquals(2, e.getHeader("foo").size());
|
||||||
assertEquals("foo", e.getHeaders().get("foo").get(0));
|
assertEquals("foo", e.getHeader("foo").get(0));
|
||||||
assertEquals("bar", e.getHeaders().get("foo").get(1));
|
assertEquals("bar", e.getHeader("foo").get(1));
|
||||||
assertSame(status, e.status());
|
assertSame(status, e.status());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UnknownHeaderException extends ElasticsearchException.WithRestHeadersException {
|
public static class UnknownHeaderException extends ElasticsearchException {
|
||||||
private final RestStatus status;
|
private final RestStatus status;
|
||||||
|
|
||||||
public UnknownHeaderException(String msg, RestStatus status, Tuple<String, String[]>... headers) {
|
public UnknownHeaderException(String msg, RestStatus status) {
|
||||||
super(msg, headers);
|
super(msg);
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,4 +619,11 @@ public class ExceptionSerializationTests extends ElasticsearchTestCase {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testElasticsearchSecurityException() throws IOException {
|
||||||
|
ElasticsearchSecurityException ex = new ElasticsearchSecurityException("user [{}] is not allowed", RestStatus.UNAUTHORIZED, "foo");
|
||||||
|
ElasticsearchSecurityException e = serialize(ex);
|
||||||
|
assertEquals(ex.status(), e.status());
|
||||||
|
assertEquals(RestStatus.UNAUTHORIZED, e.status());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,10 +152,12 @@ public class BytesRestResponseTests extends ElasticsearchTestCase {
|
||||||
assertEquals(expected.trim(), text.trim());
|
assertEquals(expected.trim(), text.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WithHeadersException extends ElasticsearchException.WithRestHeadersException {
|
public static class WithHeadersException extends ElasticsearchException {
|
||||||
|
|
||||||
WithHeadersException() {
|
WithHeadersException() {
|
||||||
super("", header("n1", "v11", "v12"), header("n2", "v21", "v22"));
|
super("");
|
||||||
|
this.addHeader("n1", "v11", "v12");
|
||||||
|
this.addHeader("n2", "v21", "v22");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue