fix query parameter charset encoding
This commit is contained in:
parent
64ae0f60bf
commit
f3173094e5
7 changed files with 57 additions and 14 deletions
|
@ -1,6 +1,6 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = net
|
name = net
|
||||||
version = 2.0.1
|
version = 2.0.2
|
||||||
|
|
||||||
# test
|
# test
|
||||||
junit.version = 5.5.1
|
junit.version = 5.5.1
|
||||||
|
@ -9,5 +9,3 @@ jackson.version = 2.9.9
|
||||||
|
|
||||||
# doc
|
# doc
|
||||||
asciidoclet.version = 1.5.4
|
asciidoclet.version = 1.5.4
|
||||||
|
|
||||||
org.gradle.warning.mode = all
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ import java.nio.charset.UnmappableCharacterException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes percent-encoded strings.
|
* Decodes percent-encoded strings.
|
||||||
|
*
|
||||||
|
* This class is not thread-safe.
|
||||||
*/
|
*/
|
||||||
public class PercentDecoder {
|
public class PercentDecoder {
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ import java.util.BitSet;
|
||||||
*
|
*
|
||||||
* This is typically done when encoding components of URLs. See {@link PercentEncoders} for pre-configured
|
* This is typically done when encoding components of URLs. See {@link PercentEncoders} for pre-configured
|
||||||
* PercentEncoder instances.
|
* PercentEncoder instances.
|
||||||
|
*
|
||||||
|
* This class is not thread-safe.
|
||||||
*/
|
*/
|
||||||
public class PercentEncoder {
|
public class PercentEncoder {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package org.xbib.net;
|
package org.xbib.net;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.CodingErrorAction;
|
||||||
import java.nio.charset.MalformedInputException;
|
import java.nio.charset.MalformedInputException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.charset.UnmappableCharacterException;
|
import java.nio.charset.UnmappableCharacterException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -25,8 +28,27 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters(int max) {
|
public QueryParameters(int max) {
|
||||||
|
this(StandardCharsets.UTF_8, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryParameters(Charset charset) {
|
||||||
|
this(charset, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryParameters(Charset charset, int max) {
|
||||||
|
this(new PercentDecoder(charset.newDecoder()
|
||||||
|
.onUnmappableCharacter(CodingErrorAction.REPLACE)
|
||||||
|
.onMalformedInput(CodingErrorAction.REPLACE)), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public QueryParameters(PercentDecoder percentDecoder) {
|
||||||
|
this(percentDecoder, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryParameters(PercentDecoder percentDecoder, int max) {
|
||||||
|
this.percentDecoder = percentDecoder;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.percentDecoder = new PercentDecoder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> get(String key) {
|
public List<String> get(String key) {
|
||||||
|
@ -51,14 +73,20 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
|
||||||
return o instanceof QueryParameters && super.equals(o);
|
return o instanceof QueryParameters && super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParameters addPercentEncodedBody(String body) throws MalformedInputException, UnmappableCharacterException {
|
public QueryParameters addPercentEncodedBody(String body) {
|
||||||
String s = body;
|
String s = body;
|
||||||
while (s != null) {
|
while (s != null) {
|
||||||
Pair<String, String> pairs = indexOf(AMPERSAND_CHAR, s);
|
Pair<String, String> pairs = indexOf(AMPERSAND_CHAR, s);
|
||||||
Pair<String, String> pair = indexOf(EQUAL_CHAR, pairs.getFirst());
|
Pair<String, String> pair = indexOf(EQUAL_CHAR, pairs.getFirst());
|
||||||
if (!isNullOrEmpty(pair.getFirst())) {
|
if (!isNullOrEmpty(pair.getFirst())) {
|
||||||
|
try {
|
||||||
add(percentDecoder.decode(pair.getFirst()),
|
add(percentDecoder.decode(pair.getFirst()),
|
||||||
percentDecoder.decode(pair.getSecond()));
|
percentDecoder.decode(pair.getSecond()));
|
||||||
|
} catch (MalformedInputException e) {
|
||||||
|
// never thrown
|
||||||
|
} catch (UnmappableCharacterException e) {
|
||||||
|
// never thrown
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s = pairs.getSecond();
|
s = pairs.getSecond();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.nio.charset.CodingErrorAction;
|
import java.nio.charset.CodingErrorAction;
|
||||||
import java.nio.charset.MalformedInputException;
|
import java.nio.charset.MalformedInputException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -825,7 +826,7 @@ public class URL implements Comparable<URL> {
|
||||||
|
|
||||||
private PercentDecoder percentDecoder;
|
private PercentDecoder percentDecoder;
|
||||||
|
|
||||||
private final QueryParameters queryParams;
|
private QueryParameters queryParams;
|
||||||
|
|
||||||
private final List<PathSegment> pathSegments;
|
private final List<PathSegment> pathSegments;
|
||||||
|
|
||||||
|
@ -854,22 +855,24 @@ public class URL implements Comparable<URL> {
|
||||||
private boolean fatalResolveErrorsEnabled;
|
private boolean fatalResolveErrorsEnabled;
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
this.queryParams = new QueryParameters();
|
|
||||||
this.pathSegments = new ArrayList<>();
|
this.pathSegments = new ArrayList<>();
|
||||||
charset(StandardCharsets.UTF_8, CodingErrorAction.REPLACE);
|
charset(StandardCharsets.UTF_8, CodingErrorAction.REPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the character set of the URL. Default is UTF-8.
|
* Set the character set of the URL. Default is UTF-8.
|
||||||
* @param charset the chaarcter set
|
* @param charset the character set
|
||||||
|
* @param codingErrorAction the coding error action
|
||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
public Builder charset(Charset charset, CodingErrorAction codingErrorAction) {
|
public Builder charset(Charset charset, CodingErrorAction codingErrorAction) {
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
this.codingErrorAction = codingErrorAction;
|
this.codingErrorAction = codingErrorAction;
|
||||||
this.regNameEncoder = PercentEncoders.getRegNameEncoder(charset);
|
this.regNameEncoder = PercentEncoders.getRegNameEncoder(charset);
|
||||||
this.percentDecoder = new PercentDecoder(charset.newDecoder()
|
CharsetDecoder charsetDecoder = charset.newDecoder()
|
||||||
.onUnmappableCharacter(codingErrorAction));
|
.onUnmappableCharacter(codingErrorAction);
|
||||||
|
this.percentDecoder = new PercentDecoder(charsetDecoder);
|
||||||
|
this.queryParams = new QueryParameters(percentDecoder);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,6 +434,16 @@ class URLParserTest {
|
||||||
assertEquals("http://library.fes.de/library/journals/de-part/das-rote-blättla/index.html", url.toString());
|
assertEquals("http://library.fes.de/library/journals/de-part/das-rote-blättla/index.html", url.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPathQueryFragmentFromPath(){
|
||||||
|
URL url = URL.builder()
|
||||||
|
.path("/a/b?c=d#e")
|
||||||
|
.build();
|
||||||
|
assertEquals("/a/b", url.getPath());
|
||||||
|
assertEquals("c=d", url.getQuery());
|
||||||
|
assertEquals("e", url.getFragment());
|
||||||
|
}
|
||||||
|
|
||||||
private void assertUrlCompatibility(String url) throws Exception {
|
private void assertUrlCompatibility(String url) throws Exception {
|
||||||
String s = URL.from(url).toExternalForm();
|
String s = URL.from(url).toExternalForm();
|
||||||
assertEquals(s, URL.from(s).toExternalForm());
|
assertEquals(s, URL.from(s).toExternalForm());
|
||||||
|
|
|
@ -13,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
class ParseBodyTest {
|
class ParseBodyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSimpleParse() throws MalformedInputException, UnmappableCharacterException {
|
void testSimpleParse() {
|
||||||
QueryParameters queryParameters = new QueryParameters();
|
QueryParameters queryParameters = new QueryParameters();
|
||||||
String body = "a=b&c=d&e=f";
|
String body = "a=b&c=d&e=f";
|
||||||
queryParameters.addPercentEncodedBody(body);
|
queryParameters.addPercentEncodedBody(body);
|
||||||
|
@ -23,7 +23,7 @@ class ParseBodyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testManyParse() throws MalformedInputException, UnmappableCharacterException {
|
void testManyParse() {
|
||||||
QueryParameters queryParameters = new QueryParameters(100);
|
QueryParameters queryParameters = new QueryParameters(100);
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
|
|
Loading…
Reference in a new issue