Skip to content

Commit 0925b7e

Browse files
committed
Make the decompressor extensible and allow for a plugin to define a step in the pipeline to analyze request headers
Signed-off-by: Craig Perkins <cwperx@amazon.com>
1 parent 8807d7a commit 0925b7e

16 files changed

Lines changed: 649 additions & 224 deletions

File tree

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.http.netty4;
10+
11+
import org.opensearch.rest.RestRequest;
12+
13+
import java.util.AbstractMap;
14+
import java.util.Collection;
15+
import java.util.Collections;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Set;
19+
import java.util.stream.Collectors;
20+
21+
import io.netty.handler.codec.http.HttpHeaders;
22+
import io.netty.handler.codec.http.HttpMethod;
23+
import io.netty.handler.codec.http.HttpRequest;
24+
25+
public class AbstractNetty4HttpRequest {
26+
27+
protected HttpHeadersMap headers;
28+
protected Exception inboundException;
29+
30+
protected RestRequest.Method getHttpMethod(HttpRequest request) {
31+
HttpMethod httpMethod = request.method();
32+
if (httpMethod == HttpMethod.GET) return RestRequest.Method.GET;
33+
34+
if (httpMethod == HttpMethod.POST) return RestRequest.Method.POST;
35+
36+
if (httpMethod == HttpMethod.PUT) return RestRequest.Method.PUT;
37+
38+
if (httpMethod == HttpMethod.DELETE) return RestRequest.Method.DELETE;
39+
40+
if (httpMethod == HttpMethod.HEAD) {
41+
return RestRequest.Method.HEAD;
42+
}
43+
44+
if (httpMethod == HttpMethod.OPTIONS) {
45+
return RestRequest.Method.OPTIONS;
46+
}
47+
48+
if (httpMethod == HttpMethod.PATCH) {
49+
return RestRequest.Method.PATCH;
50+
}
51+
52+
if (httpMethod == HttpMethod.TRACE) {
53+
return RestRequest.Method.TRACE;
54+
}
55+
56+
if (httpMethod == HttpMethod.CONNECT) {
57+
return RestRequest.Method.CONNECT;
58+
}
59+
60+
throw new IllegalArgumentException("Unexpected http method: " + httpMethod);
61+
}
62+
63+
/**
64+
* A wrapper of {@link HttpHeaders} that implements a map to prevent copying unnecessarily. This class does not support modifications
65+
* and due to the underlying implementation, it performs case insensitive lookups of key to values.
66+
*
67+
* It is important to note that this implementation does have some downsides in that each invocation of the
68+
* {@link #values()} and {@link #entrySet()} methods will perform a copy of the values in the HttpHeaders rather than returning a
69+
* view of the underlying values.
70+
*/
71+
protected static class HttpHeadersMap implements Map<String, List<String>> {
72+
73+
private final HttpHeaders httpHeaders;
74+
75+
HttpHeadersMap(HttpHeaders httpHeaders) {
76+
this.httpHeaders = httpHeaders;
77+
}
78+
79+
@Override
80+
public int size() {
81+
return httpHeaders.size();
82+
}
83+
84+
@Override
85+
public boolean isEmpty() {
86+
return httpHeaders.isEmpty();
87+
}
88+
89+
@Override
90+
public boolean containsKey(Object key) {
91+
return key instanceof String && httpHeaders.contains((String) key);
92+
}
93+
94+
@Override
95+
public boolean containsValue(Object value) {
96+
return value instanceof List && httpHeaders.names().stream().map(httpHeaders::getAll).anyMatch(value::equals);
97+
}
98+
99+
@Override
100+
public List<String> get(Object key) {
101+
return key instanceof String ? httpHeaders.getAll((String) key) : null;
102+
}
103+
104+
@Override
105+
public List<String> put(String key, List<String> value) {
106+
throw new UnsupportedOperationException("modifications are not supported");
107+
}
108+
109+
@Override
110+
public List<String> remove(Object key) {
111+
throw new UnsupportedOperationException("modifications are not supported");
112+
}
113+
114+
@Override
115+
public void putAll(Map<? extends String, ? extends List<String>> m) {
116+
throw new UnsupportedOperationException("modifications are not supported");
117+
}
118+
119+
@Override
120+
public void clear() {
121+
throw new UnsupportedOperationException("modifications are not supported");
122+
}
123+
124+
@Override
125+
public Set<String> keySet() {
126+
return httpHeaders.names();
127+
}
128+
129+
@Override
130+
public Collection<List<String>> values() {
131+
return httpHeaders.names().stream().map(k -> Collections.unmodifiableList(httpHeaders.getAll(k))).collect(Collectors.toList());
132+
}
133+
134+
@Override
135+
public Set<Entry<String, List<String>>> entrySet() {
136+
return httpHeaders.names()
137+
.stream()
138+
.map(k -> new AbstractMap.SimpleImmutableEntry<>(k, httpHeaders.getAll(k)))
139+
.collect(Collectors.toSet());
140+
}
141+
}
142+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.http.netty4;
10+
11+
import org.opensearch.core.common.bytes.BytesArray;
12+
import org.opensearch.core.common.bytes.BytesReference;
13+
import org.opensearch.core.rest.RestStatus;
14+
import org.opensearch.http.HttpRequest;
15+
import org.opensearch.rest.RestRequest;
16+
17+
import java.util.Collections;
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.Set;
21+
22+
import io.netty.handler.codec.http.DefaultHttpRequest;
23+
import io.netty.handler.codec.http.HttpHeaderNames;
24+
import io.netty.handler.codec.http.cookie.Cookie;
25+
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
26+
import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
27+
28+
public class Netty4DefaultHttpRequest extends AbstractNetty4HttpRequest implements HttpRequest {
29+
30+
private final DefaultHttpRequest request;
31+
32+
public Netty4DefaultHttpRequest(DefaultHttpRequest request) {
33+
this(request, new HttpHeadersMap(request.headers()), null);
34+
}
35+
36+
private Netty4DefaultHttpRequest(DefaultHttpRequest request, HttpHeadersMap headers, Exception inboundException) {
37+
this.request = request;
38+
this.headers = headers;
39+
this.inboundException = inboundException;
40+
}
41+
42+
@Override
43+
public RestRequest.Method method() {
44+
return getHttpMethod(request);
45+
}
46+
47+
@Override
48+
public String uri() {
49+
return request.uri();
50+
}
51+
52+
@Override
53+
public BytesReference content() {
54+
// throw new RuntimeException("Not implemented");
55+
return BytesArray.EMPTY;
56+
}
57+
58+
@Override
59+
public final Map<String, List<String>> getHeaders() {
60+
return headers;
61+
}
62+
63+
@Override
64+
public List<String> strictCookies() {
65+
String cookieString = request.headers().get(HttpHeaderNames.COOKIE);
66+
if (cookieString != null) {
67+
Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(cookieString);
68+
if (!cookies.isEmpty()) {
69+
return ServerCookieEncoder.STRICT.encode(cookies);
70+
}
71+
}
72+
return Collections.emptyList();
73+
}
74+
75+
@Override
76+
public HttpVersion protocolVersion() {
77+
if (request.protocolVersion().equals(io.netty.handler.codec.http.HttpVersion.HTTP_1_0)) {
78+
return HttpRequest.HttpVersion.HTTP_1_0;
79+
} else if (request.protocolVersion().equals(io.netty.handler.codec.http.HttpVersion.HTTP_1_1)) {
80+
return HttpRequest.HttpVersion.HTTP_1_1;
81+
} else {
82+
throw new IllegalArgumentException("Unexpected http protocol version: " + request.protocolVersion());
83+
}
84+
}
85+
86+
@Override
87+
public HttpRequest removeHeader(String header) {
88+
return null;
89+
}
90+
91+
@Override
92+
public Netty4HttpResponse createResponse(RestStatus status, BytesReference content) {
93+
return new Netty4HttpResponse(request.headers(), request.protocolVersion(), status, content);
94+
}
95+
96+
@Override
97+
public Exception getInboundException() {
98+
return inboundException;
99+
}
100+
101+
@Override
102+
public void release() {
103+
// do nothing
104+
}
105+
106+
@Override
107+
public HttpRequest releaseAndCopy() {
108+
return this;
109+
}
110+
111+
public DefaultHttpRequest nettyRequest() {
112+
return request;
113+
}
114+
}

0 commit comments

Comments
 (0)