switch to HTTP parameter map
This commit is contained in:
parent
d42f928113
commit
97d6f4dc6a
11 changed files with 711 additions and 212 deletions
|
@ -1,6 +1,6 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = netty-http
|
name = netty-http
|
||||||
version = 4.1.51.3
|
version = 4.1.51.4
|
||||||
|
|
||||||
gradle.wrapper.version = 6.4.1
|
gradle.wrapper.version = 6.4.1
|
||||||
netty.version = 4.1.51.Final
|
netty.version = 4.1.51.Final
|
||||||
|
|
|
@ -609,10 +609,7 @@ public final class Request {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
// add our URI parameters to the URL
|
// add our URI parameters to the URL
|
||||||
URL.Builder mutator = url.mutator();
|
URL.Builder mutator = url.mutator();
|
||||||
uriParameters.forEach((k, v) -> v.forEach(vv -> {
|
uriParameters.forEach(e -> mutator.queryParam(e.getKey(), e.getValue()));
|
||||||
// no percent encoding
|
|
||||||
mutator.queryParam(k, vv);
|
|
||||||
}));
|
|
||||||
// calling build() performs percent encoding
|
// calling build() performs percent encoding
|
||||||
url = mutator.build();
|
url = mutator.build();
|
||||||
String scheme = url.getScheme();
|
String scheme = url.getScheme();
|
||||||
|
|
|
@ -4,9 +4,8 @@ import io.netty.handler.codec.http.HttpHeaderValues;
|
||||||
import org.xbib.net.PercentDecoder;
|
import org.xbib.net.PercentDecoder;
|
||||||
import org.xbib.net.PercentEncoder;
|
import org.xbib.net.PercentEncoder;
|
||||||
import org.xbib.net.PercentEncoders;
|
import org.xbib.net.PercentEncoders;
|
||||||
|
import org.xbib.netty.http.common.util.CaseInsensitiveParameters;
|
||||||
import org.xbib.netty.http.common.util.LimitedSet;
|
import org.xbib.netty.http.common.util.LimitedSet;
|
||||||
import org.xbib.netty.http.common.util.LimitedTreeMap;
|
|
||||||
|
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.MalformedInputException;
|
import java.nio.charset.MalformedInputException;
|
||||||
|
@ -15,11 +14,8 @@ import java.nio.charset.UnmappableCharacterException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.SortedSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A limited multi-map of HTTP request parameters. Each key references a
|
* A limited multi-map of HTTP request parameters. Each key references a
|
||||||
|
@ -31,26 +27,22 @@ import java.util.SortedSet;
|
||||||
* being useful for message signing; it's not a general purpose collection class
|
* being useful for message signing; it's not a general purpose collection class
|
||||||
* to handle request parameters.
|
* to handle request parameters.
|
||||||
*/
|
*/
|
||||||
public class HttpParameters implements Map<String, SortedSet<String>> {
|
public class HttpParameters extends /*LinkedHashSetMultiMap<String, String>*/ CaseInsensitiveParameters {
|
||||||
|
|
||||||
private static final String EQUALS = "=";
|
private static final String EQUALS = "=";
|
||||||
|
|
||||||
private static final String AMPERSAND = "&";
|
private static final String AMPERSAND = "&";
|
||||||
|
|
||||||
private final int maxParam;
|
|
||||||
|
|
||||||
private final int sizeLimit;
|
private final int sizeLimit;
|
||||||
|
|
||||||
private final int elementSizeLimit;
|
private final int elementSizeLimit;
|
||||||
|
|
||||||
private final LimitedTreeMap<String, String> map;
|
|
||||||
|
|
||||||
private final PercentEncoder percentEncoder;
|
private final PercentEncoder percentEncoder;
|
||||||
|
|
||||||
private final PercentDecoder percentDecoder;
|
|
||||||
|
|
||||||
private final CharSequence contentType;
|
private final CharSequence contentType;
|
||||||
|
|
||||||
|
private final Charset encoding;
|
||||||
|
|
||||||
public HttpParameters() {
|
public HttpParameters() {
|
||||||
this(1024, 1024, 65536,
|
this(1024, 1024, 65536,
|
||||||
HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED, StandardCharsets.UTF_8);
|
HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED, StandardCharsets.UTF_8);
|
||||||
|
@ -68,96 +60,28 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
|
|
||||||
public HttpParameters(int maxParam, int sizeLimit, int elementSizeLimit,
|
public HttpParameters(int maxParam, int sizeLimit, int elementSizeLimit,
|
||||||
CharSequence contentType, Charset charset) {
|
CharSequence contentType, Charset charset) {
|
||||||
this.maxParam = maxParam;
|
|
||||||
this.sizeLimit = sizeLimit;
|
this.sizeLimit = sizeLimit;
|
||||||
this.elementSizeLimit = elementSizeLimit;
|
this.elementSizeLimit = elementSizeLimit;
|
||||||
this.map = new LimitedTreeMap<>(maxParam);
|
|
||||||
this.percentEncoder = PercentEncoders.getQueryEncoder(charset);
|
this.percentEncoder = PercentEncoders.getQueryEncoder(charset);
|
||||||
this.percentDecoder = new PercentDecoder();
|
PercentDecoder percentDecoder = new PercentDecoder();
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
|
this.encoding = charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public CharSequence getContentType() {
|
||||||
public SortedSet<String> put(String key, SortedSet<String> value) {
|
return contentType;
|
||||||
return map.put(key, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Charset getEncoding() {
|
||||||
public SortedSet<String> get(Object key) {
|
return encoding;
|
||||||
return map.get(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Collection<String> put(String key, Collection<String> values, boolean percentEncode) {
|
||||||
public void putAll(Map<? extends String, ? extends SortedSet<String>> m) {
|
remove(key);
|
||||||
map.putAll(m);
|
for (String v : values) {
|
||||||
}
|
add(key, v, percentEncode);
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsKey(Object key) {
|
|
||||||
return map.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Object value) {
|
|
||||||
if (value instanceof String) {
|
|
||||||
for (Set<String> values : map.values()) {
|
|
||||||
if (values.contains(value)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
int count = 0;
|
|
||||||
for (String key : map.keySet()) {
|
|
||||||
count += map.get(key).size();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
map.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SortedSet<String> remove(Object key) {
|
|
||||||
return map.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> keySet() {
|
|
||||||
return map.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<SortedSet<String>> values() {
|
|
||||||
return map.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Entry<String, SortedSet<String>>> entrySet() {
|
|
||||||
return map.entrySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortedSet<String> put(String key, SortedSet<String> values, boolean percentEncode) {
|
|
||||||
if (percentEncode) {
|
|
||||||
remove(key);
|
|
||||||
for (String v : values) {
|
|
||||||
add(key, v, percentEncode);
|
|
||||||
}
|
|
||||||
return get(key);
|
|
||||||
} else {
|
|
||||||
return map.put(key, values);
|
|
||||||
}
|
}
|
||||||
|
return getAll(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,14 +91,26 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
* @param value the parameter value
|
* @param value the parameter value
|
||||||
* @return the value
|
* @return the value
|
||||||
*/
|
*/
|
||||||
public String addRaw(String key, String value) {
|
public HttpParameters addRaw(String key, String value) {
|
||||||
return add(key, value, false);
|
return add(key, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String add(String key, String value) {
|
public HttpParameters add(String key, String value) {
|
||||||
return add(key, value, true);
|
return add(key, value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to allow for storing null values. {@link #put} doesn't
|
||||||
|
* allow null values, because that would be ambiguous.
|
||||||
|
*
|
||||||
|
* @param key the parameter name
|
||||||
|
* @param nullString can be anything, but probably... null?
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public HttpParameters addNull(String key, String nullString) {
|
||||||
|
return addRaw(key, nullString);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a single value for the parameter specified by
|
* Convenience method to add a single value for the parameter specified by
|
||||||
* 'key'.
|
* 'key'.
|
||||||
|
@ -185,36 +121,15 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
* inserted into the map
|
* inserted into the map
|
||||||
* @return the value
|
* @return the value
|
||||||
*/
|
*/
|
||||||
private String add(String key, String value, boolean percentEncode) {
|
private HttpParameters add(String key, String value, boolean percentEncode) {
|
||||||
String v = null;
|
|
||||||
try {
|
try {
|
||||||
String k = percentEncode ? percentEncoder.encode(key) : key;
|
String k = percentEncode ? percentEncoder.encode(key) : key;
|
||||||
SortedSet<String> values = map.get(k);
|
String v = percentEncode ? percentEncoder.encode(value) : value;
|
||||||
if (values == null) {
|
super.add(k, v);
|
||||||
values = new LimitedSet<>(sizeLimit, elementSizeLimit);
|
|
||||||
map.put(k, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
v = percentEncode ? percentEncoder.encode(value) : value;
|
|
||||||
values.add(v);
|
|
||||||
}
|
|
||||||
} catch (CharacterCodingException e) {
|
} catch (CharacterCodingException e) {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
return v;
|
return this;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method to allow for storing null values. {@link #put} doesn't
|
|
||||||
* allow null values, because that would be ambiguous.
|
|
||||||
*
|
|
||||||
* @param key the parameter name
|
|
||||||
* @param nullString can be anything, but probably... null?
|
|
||||||
* @return null
|
|
||||||
*/
|
|
||||||
public String addNull(String key, String nullString) {
|
|
||||||
return addRaw(key, nullString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAll(String[] keyValuePairs, boolean percentEncode) {
|
public void addAll(String[] keyValuePairs, boolean percentEncode) {
|
||||||
|
@ -223,16 +138,6 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAll(Map<? extends String, ? extends SortedSet<String>> m, boolean percentEncode) {
|
|
||||||
if (percentEncode) {
|
|
||||||
for (String key : m.keySet()) {
|
|
||||||
put(key, m.get(key), true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
map.putAll(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to merge a {@code Map<String, List<String>>}.
|
* Convenience method to merge a {@code Map<String, List<String>>}.
|
||||||
*
|
*
|
||||||
|
@ -240,53 +145,20 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
*/
|
*/
|
||||||
public void addMap(Map<String, List<String>> m) {
|
public void addMap(Map<String, List<String>> m) {
|
||||||
for (String key : m.keySet()) {
|
for (String key : m.keySet()) {
|
||||||
SortedSet<String> vals = get(key);
|
Collection<String> vals = getAll(key);
|
||||||
if (vals == null) {
|
if (vals == null) {
|
||||||
vals = new LimitedSet<>(sizeLimit, elementSizeLimit);
|
vals = new LimitedSet<>(sizeLimit, elementSizeLimit);
|
||||||
put(key, vals);
|
for (String v : vals) {
|
||||||
|
super.add(key, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vals.addAll(m.get(key));
|
vals.addAll(m.get(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFirst(String key) {
|
|
||||||
SortedSet<String> values = map.get(key);
|
|
||||||
if (values == null || values.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return values.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first value from the set of all values for the given
|
|
||||||
* parameter name. If the key passed to this method contains special
|
|
||||||
* characters, you must first percent encode it, otherwise the lookup will fail
|
|
||||||
* (that's because upon storing values in this map, keys get
|
|
||||||
* percent-encoded).
|
|
||||||
*
|
|
||||||
* @param key the parameter name (must be percent encoded if it contains unsafe
|
|
||||||
* characters!)
|
|
||||||
* @return the first value found for this parameter
|
|
||||||
* @throws MalformedInputException if input is malformed
|
|
||||||
* @throws UnmappableCharacterException if characters are unmappable
|
|
||||||
*/
|
|
||||||
public String getFirstDecoded(String key)
|
|
||||||
throws MalformedInputException, UnmappableCharacterException {
|
|
||||||
SortedSet<String> values = map.get(key);
|
|
||||||
if (values == null || values.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String value = values.first();
|
|
||||||
return percentDecoder.decode(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CharSequence getContentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAsQueryString(boolean percentEncode) throws MalformedInputException, UnmappableCharacterException {
|
public String getAsQueryString(boolean percentEncode) throws MalformedInputException, UnmappableCharacterException {
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
for (String key : keySet()) {
|
for (String key : super.names()) {
|
||||||
list.add(getAsQueryString(key, percentEncode));
|
list.add(getAsQueryString(key, percentEncode));
|
||||||
}
|
}
|
||||||
return String.join(AMPERSAND, list);
|
return String.join(AMPERSAND, list);
|
||||||
|
@ -320,7 +192,7 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
public String getAsQueryString(String key, boolean percentEncode)
|
public String getAsQueryString(String key, boolean percentEncode)
|
||||||
throws MalformedInputException, UnmappableCharacterException {
|
throws MalformedInputException, UnmappableCharacterException {
|
||||||
String k = percentEncode ? percentEncoder.encode(key) : key;
|
String k = percentEncode ? percentEncoder.encode(key) : key;
|
||||||
SortedSet<String> values = map.get(k);
|
Collection<String> values = getAll(k);
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
return k + EQUALS;
|
return k + EQUALS;
|
||||||
}
|
}
|
||||||
|
@ -336,26 +208,4 @@ public class HttpParameters implements Map<String, SortedSet<String>> {
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAsHeaderElement(String key) {
|
|
||||||
String value = getFirst(key);
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return key + "=\"" + value + "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpParameters getOAuthParameters() {
|
|
||||||
HttpParameters oauthParams =
|
|
||||||
new HttpParameters(maxParam, sizeLimit, elementSizeLimit, contentType, StandardCharsets.UTF_8);
|
|
||||||
entrySet().stream().filter(entry -> entry.getKey().startsWith("oauth_") || entry.getKey().startsWith("x_oauth_"))
|
|
||||||
.forEach(entry -> oauthParams.put(entry.getKey(), entry.getValue()));
|
|
||||||
return oauthParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new LinkedHashMap<>(this).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
package org.xbib.netty.http.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract multi map.
|
||||||
|
*
|
||||||
|
* @param <K> the key type parameter
|
||||||
|
* @param <V> the value type parameter
|
||||||
|
*/
|
||||||
|
abstract class AbstractMultiMap<K, V> implements MultiMap<K, V> {
|
||||||
|
|
||||||
|
private final Map<K, Collection<V>> map;
|
||||||
|
|
||||||
|
AbstractMultiMap() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractMultiMap(MultiMap<K, V> map) {
|
||||||
|
this.map = newMap();
|
||||||
|
if (map != null) {
|
||||||
|
putAll(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(K key) {
|
||||||
|
return map.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<K> keySet() {
|
||||||
|
return map.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean put(K key, V value) {
|
||||||
|
Collection<V> set = map.get(key);
|
||||||
|
if (set == null) {
|
||||||
|
set = newValues();
|
||||||
|
set.add(value);
|
||||||
|
map.put(key, set);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
set.add(value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(K key, Iterable<V> values) {
|
||||||
|
if (values == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Collection<V> set = map.computeIfAbsent(key, k -> newValues());
|
||||||
|
for (V v : values) {
|
||||||
|
set.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<V> get(K key) {
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<V> remove(K key) {
|
||||||
|
return map.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(K key, V value) {
|
||||||
|
Collection<V> set = map.get(key);
|
||||||
|
return set != null && set.remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(MultiMap<K, V> map) {
|
||||||
|
if (map != null) {
|
||||||
|
for (K key : map.keySet()) {
|
||||||
|
putAll(key, map.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<K, Collection<V>> asMap() {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(K key) {
|
||||||
|
Collection<V> v = get(key);
|
||||||
|
return v != null ? v.iterator().next().toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(K key, String defaultValue) {
|
||||||
|
Collection<V> collection = get(key);
|
||||||
|
Iterator<V> iterator = collection != null ? collection.iterator() : null;
|
||||||
|
V v = iterator != null ? iterator.next() : null;
|
||||||
|
return v != null ? v.toString() : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getInteger(K key, int defaultValue) {
|
||||||
|
Collection<V> collection = get(key);
|
||||||
|
Iterator<V> iterator = collection != null ? collection.iterator() : null;
|
||||||
|
V v = iterator != null ? iterator.next() : null;
|
||||||
|
return v != null ? Integer.parseInt(v.toString()) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getBoolean(K key, boolean defaultValue) {
|
||||||
|
Collection<V> collection = get(key);
|
||||||
|
Iterator<V> iterator = collection != null ? collection.iterator() : null;
|
||||||
|
V v = iterator != null ? iterator.next() : null;
|
||||||
|
return v != null ? Boolean.parseBoolean(v.toString()) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof AbstractMultiMap && map.equals(((AbstractMultiMap) obj).map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return map.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return map.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Collection<V> newValues();
|
||||||
|
|
||||||
|
abstract Map<K, Collection<V>> newMap();
|
||||||
|
}
|
|
@ -0,0 +1,358 @@
|
||||||
|
package org.xbib.netty.http.common.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This multi-map implementation has case insensitive keys
|
||||||
|
* and can be used to hold some HTTP headers prior to making an HTTP request.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CaseInsensitiveParameters implements ParameterMap {
|
||||||
|
|
||||||
|
private static final int BUCKET_SIZE = 17;
|
||||||
|
|
||||||
|
private static int hash(String name) {
|
||||||
|
int h = 0;
|
||||||
|
for (int i = name.length() - 1; i >= 0; i--) {
|
||||||
|
char c = name.charAt(i);
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
c += 32;
|
||||||
|
}
|
||||||
|
h = 31 * h + c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h > 0) {
|
||||||
|
return h;
|
||||||
|
} else if (h == Integer.MIN_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
} else {
|
||||||
|
return -h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParameterMap set0(Iterable<Map.Entry<String, String>> map) {
|
||||||
|
clear();
|
||||||
|
for (Map.Entry<String, String> entry : map) {
|
||||||
|
add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap setAll(ParameterMap headers) {
|
||||||
|
return set0(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return names().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean eq(String name1, String name2) {
|
||||||
|
int nameLen = name1.length();
|
||||||
|
if (nameLen != name2.length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = nameLen - 1; i >= 0; i--) {
|
||||||
|
char c1 = name1.charAt(i);
|
||||||
|
char c2 = name2.charAt(i);
|
||||||
|
if (c1 != c2) {
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z') {
|
||||||
|
c1 += 32;
|
||||||
|
}
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z') {
|
||||||
|
c2 += 32;
|
||||||
|
}
|
||||||
|
if (c1 != c2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int index(int hash) {
|
||||||
|
return hash % BUCKET_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final MapEntry[] entries = new MapEntry[BUCKET_SIZE];
|
||||||
|
|
||||||
|
private final MapEntry head = new MapEntry(-1, null, null);
|
||||||
|
|
||||||
|
public CaseInsensitiveParameters() {
|
||||||
|
head.before = head.after = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap add(final String name, final String strVal) {
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
add0(h, i, name, strVal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap add(String name, Iterable<String> values) {
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
for (String vstr : values) {
|
||||||
|
add0(h, i, name, vstr);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap addAll(ParameterMap headers) {
|
||||||
|
for (Map.Entry<String, String> entry : headers.entries()) {
|
||||||
|
add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap addAll(Map<String, String> map) {
|
||||||
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||||
|
add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap remove(final String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
remove0(h, i, name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap set(final String name, final String strVal) {
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
remove0(h, i, name);
|
||||||
|
add0(h, i, name, strVal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap set(final String name, final Iterable<String> values) {
|
||||||
|
Objects.requireNonNull(values, "values");
|
||||||
|
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
|
||||||
|
remove0(h, i, name);
|
||||||
|
for (String v : values) {
|
||||||
|
if (v == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
add0(h, i, name, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterMap clear() {
|
||||||
|
Arrays.fill(entries, null);
|
||||||
|
head.before = head.after = head;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(final String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
MapEntry e = entries[i];
|
||||||
|
String value = null;
|
||||||
|
while (e != null) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
value = e.getValue();
|
||||||
|
}
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getAll(final String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
LinkedList<String> values = new LinkedList<>();
|
||||||
|
int h = hash(name);
|
||||||
|
int i = index(h);
|
||||||
|
MapEntry e = entries[i];
|
||||||
|
while (e != null) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
values.addFirst(e.getValue());
|
||||||
|
}
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forEach(Consumer<? super Map.Entry<String, String>> action) {
|
||||||
|
MapEntry e = head.after;
|
||||||
|
while (e != head) {
|
||||||
|
action.accept(e);
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map.Entry<String, String>> entries() {
|
||||||
|
List<Map.Entry<String, String>> all = new LinkedList<>();
|
||||||
|
MapEntry e = head.after;
|
||||||
|
while (e != head) {
|
||||||
|
all.add(e);
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String, String>> iterator() {
|
||||||
|
return entries().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(String name) {
|
||||||
|
return get(name) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return head == head.after;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> names() {
|
||||||
|
List<String> names = new LinkedList<>();
|
||||||
|
MapEntry e = head.after;
|
||||||
|
while (e != head) {
|
||||||
|
if (!names.contains(e.getKey())) {
|
||||||
|
names.add(e.getKey());
|
||||||
|
}
|
||||||
|
e = e.after;
|
||||||
|
}
|
||||||
|
names.sort(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Map.Entry<String, String> entry : this) {
|
||||||
|
sb.append(entry).append('\n');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add0(int h, int i, final String name, final String value) {
|
||||||
|
MapEntry e = entries[i];
|
||||||
|
MapEntry newEntry;
|
||||||
|
entries[i] = newEntry = new MapEntry(h, name, value);
|
||||||
|
newEntry.next = e;
|
||||||
|
newEntry.addBefore(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove0(int h, int i, String name) {
|
||||||
|
MapEntry e = entries[i];
|
||||||
|
if (e == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
|
e.remove();
|
||||||
|
MapEntry next = e.next;
|
||||||
|
if (next != null) {
|
||||||
|
entries[i] = next;
|
||||||
|
e = next;
|
||||||
|
} else {
|
||||||
|
entries[i] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
MapEntry next = e.next;
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (next.hash == h && eq(name, next.key)) {
|
||||||
|
e.next = next.next;
|
||||||
|
next.remove();
|
||||||
|
} else {
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class MapEntry implements Map.Entry<String, String> {
|
||||||
|
|
||||||
|
final int hash;
|
||||||
|
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
String value;
|
||||||
|
|
||||||
|
MapEntry next;
|
||||||
|
|
||||||
|
MapEntry before, after;
|
||||||
|
|
||||||
|
MapEntry(int hash, String key, String value) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove() {
|
||||||
|
before.after = after;
|
||||||
|
after.before = before;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBefore(MapEntry e) {
|
||||||
|
after = e;
|
||||||
|
before = e.before;
|
||||||
|
before.after = this;
|
||||||
|
after.before = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String setValue(String value) {
|
||||||
|
Objects.requireNonNull(value, "value");
|
||||||
|
String oldValue = this.value;
|
||||||
|
this.value = value;
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getKey() + ": " + getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.xbib.netty.http.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Linked multi map.
|
||||||
|
*
|
||||||
|
* @param <K> the key type parameter
|
||||||
|
* @param <V> the value type parameter
|
||||||
|
*/
|
||||||
|
public class LinkedHashSetMultiMap<K, V> extends AbstractMultiMap<K, V> {
|
||||||
|
|
||||||
|
public LinkedHashSetMultiMap() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Collection<V> newValues() {
|
||||||
|
return new LinkedHashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Map<K, Collection<V>> newMap() {
|
||||||
|
return new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.xbib.netty.http.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MultiMap interface.
|
||||||
|
*
|
||||||
|
* @param <K> the key type parameter
|
||||||
|
* @param <V> the value type parameter
|
||||||
|
*/
|
||||||
|
public interface MultiMap<K, V> {
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
int size();
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
boolean containsKey(K key);
|
||||||
|
|
||||||
|
Collection<V> get(K key);
|
||||||
|
|
||||||
|
Set<K> keySet();
|
||||||
|
|
||||||
|
boolean put(K key, V value);
|
||||||
|
|
||||||
|
void putAll(K key, Iterable<V> values);
|
||||||
|
|
||||||
|
void putAll(MultiMap<K, V> map);
|
||||||
|
|
||||||
|
Collection<V> remove(K key);
|
||||||
|
|
||||||
|
boolean remove(K key, V value);
|
||||||
|
|
||||||
|
Map<K, Collection<V>> asMap();
|
||||||
|
|
||||||
|
String getString(K key);
|
||||||
|
|
||||||
|
String getString(K key, String defaultValue);
|
||||||
|
|
||||||
|
Integer getInteger(K key, int defaultValue);
|
||||||
|
|
||||||
|
Boolean getBoolean(K key, boolean defaultValue);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.xbib.netty.http.common.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ParameterMap extends Iterable<Map.Entry<String, String>> {
|
||||||
|
|
||||||
|
String get(String name);
|
||||||
|
|
||||||
|
List<String> getAll(String name);
|
||||||
|
|
||||||
|
List<Map.Entry<String, String>> entries();
|
||||||
|
|
||||||
|
boolean contains(String name);
|
||||||
|
|
||||||
|
default boolean contains(String name, String value, boolean caseInsensitive) {
|
||||||
|
return getAll(name).stream()
|
||||||
|
.anyMatch(val -> caseInsensitive ? val.equalsIgnoreCase(value) : val.equals(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
List<String> names();
|
||||||
|
|
||||||
|
ParameterMap add(String name, String value);
|
||||||
|
|
||||||
|
ParameterMap add(String name, Iterable<String> values);
|
||||||
|
|
||||||
|
ParameterMap addAll(ParameterMap map);
|
||||||
|
|
||||||
|
ParameterMap addAll(Map<String, String> map);
|
||||||
|
|
||||||
|
ParameterMap set(String name, String value);
|
||||||
|
|
||||||
|
ParameterMap set(String name, Iterable<String> values);
|
||||||
|
|
||||||
|
ParameterMap setAll(ParameterMap map);
|
||||||
|
|
||||||
|
ParameterMap remove(String name);
|
||||||
|
|
||||||
|
ParameterMap clear();
|
||||||
|
|
||||||
|
int size();
|
||||||
|
}
|
|
@ -11,13 +11,32 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
class HttpParametersTest {
|
class HttpParametersTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testParameters() throws MalformedInputException, UnmappableCharacterException {
|
void testSimpleParameter() throws MalformedInputException, UnmappableCharacterException {
|
||||||
HttpParameters httpParameters = new HttpParameters();
|
HttpParameters httpParameters = new HttpParameters();
|
||||||
httpParameters.addRaw("a", "b");
|
httpParameters.addRaw("a", "b");
|
||||||
String query = httpParameters.getAsQueryString(false);
|
String query = httpParameters.getAsQueryString(false);
|
||||||
assertEquals("a=b", query);
|
assertEquals("a=b", query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleParameters() throws MalformedInputException, UnmappableCharacterException {
|
||||||
|
HttpParameters httpParameters = new HttpParameters();
|
||||||
|
httpParameters.addRaw("a", "b");
|
||||||
|
httpParameters.addRaw("c", "d");
|
||||||
|
String query = httpParameters.getAsQueryString(false);
|
||||||
|
assertEquals("a=b&c=d", query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultiParameters() throws MalformedInputException, UnmappableCharacterException {
|
||||||
|
HttpParameters httpParameters = new HttpParameters();
|
||||||
|
httpParameters.addRaw("a", "b");
|
||||||
|
httpParameters.addRaw("a", "c");
|
||||||
|
httpParameters.addRaw("a", "d");
|
||||||
|
String query = httpParameters.getAsQueryString(false);
|
||||||
|
assertEquals("a=b&a=c&a=d", query);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUtf8() throws MalformedInputException, UnmappableCharacterException {
|
void testUtf8() throws MalformedInputException, UnmappableCharacterException {
|
||||||
HttpParameters httpParameters = new HttpParameters("text/plain; charset=utf-8");
|
HttpParameters httpParameters = new HttpParameters("text/plain; charset=utf-8");
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.xbib.netty.http.common.HttpParameters;
|
||||||
import org.xbib.netty.http.common.HttpResponse;
|
import org.xbib.netty.http.common.HttpResponse;
|
||||||
import org.xbib.netty.http.server.HttpServerDomain;
|
import org.xbib.netty.http.server.HttpServerDomain;
|
||||||
import org.xbib.netty.http.server.Server;
|
import org.xbib.netty.http.server.Server;
|
||||||
import org.xbib.netty.http.server.api.ServerResponse;
|
|
||||||
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -36,10 +35,10 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withspace"))) {
|
if ("Hello World".equals(parameters.get("withspace"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
@ -86,10 +85,10 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withspace"))) {
|
if ("Hello World".equals(parameters.get("withspace"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
@ -137,13 +136,13 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withplus"))) {
|
if ("Hello World".equals(parameters.get("withplus"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
if ("my value".equals(parameters.getFirst("my param"))) {
|
if ("my value".equals(parameters.get("my param"))) {
|
||||||
success4.set(true);
|
success4.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
@ -194,13 +193,13 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withoutplus"))) {
|
if ("Hello World".equals(parameters.get("withoutplus"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
if ("my value".equals(parameters.getFirst("my param"))) {
|
if ("my value".equals(parameters.get("my param"))) {
|
||||||
success4.set(true);
|
success4.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
@ -251,10 +250,10 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending OK");
|
||||||
if ("myÿvalue".equals(parameters.getFirst("my param"))) {
|
if ("myÿvalue".equals(parameters.get("my param"))) {
|
||||||
success1.set(true);
|
success1.set(true);
|
||||||
}
|
}
|
||||||
if ("bÿc".equals(parameters.getFirst("a"))) {
|
if ("bÿc".equals(parameters.get("a"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
|
|
@ -36,10 +36,10 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + " , sending, OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + " , sending, OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withspace"))) {
|
if ("Hello World".equals(parameters.get("withspace"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
@ -86,10 +86,10 @@ class PostTest {
|
||||||
.singleEndpoint("/post", "/**", (req, resp) -> {
|
.singleEndpoint("/post", "/**", (req, resp) -> {
|
||||||
HttpParameters parameters = req.getParameters();
|
HttpParameters parameters = req.getParameters();
|
||||||
logger.log(Level.INFO, "got request " + parameters.toString() + " , sending, OK");
|
logger.log(Level.INFO, "got request " + parameters.toString() + " , sending, OK");
|
||||||
if ("Hello World".equals(parameters.getFirst("withspace"))) {
|
if ("Hello World".equals(parameters.get("withspace"))) {
|
||||||
success2.set(true);
|
success2.set(true);
|
||||||
}
|
}
|
||||||
if ("Jörg".equals(parameters.getFirst("name"))) {
|
if ("Jörg".equals(parameters.get("name"))) {
|
||||||
success3.set(true);
|
success3.set(true);
|
||||||
}
|
}
|
||||||
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
resp.getBuilder().setStatus(HttpResponseStatus.OK).build().flush();
|
||||||
|
|
Loading…
Reference in a new issue