* Fixed a problem where query parameter components are not correctly encoded / decoded

* Changed the default charset of the query parameters to UTF-8
* Allowed a user to specify the charset of QueryStringEncoder/Decoder
This commit is contained in:
Trustin Lee 2009-02-26 06:34:07 +00:00
parent 63cb4a023f
commit 29b0af4f07
2 changed files with 78 additions and 23 deletions

View File

@ -21,7 +21,10 @@
*/
package org.jboss.netty.handler.codec.http;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -30,22 +33,50 @@ import java.util.Map;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Andy Taylor (andy.taylor@jboss.org)
* @author Trustin Lee (tlee@redhat.com)
* @version $Rev$, $Date$
*
* @apiviz.stereotype utility
*/
public class QueryStringDecoder {
static final String DEFAULT_CHARSET = "UTF-8";
private final String charset;
private final String uri;
private String path;
private final Map<String, List<String>> params = new HashMap<String, List<String>>();
public QueryStringDecoder(String uri) {
this.uri = uri;
this(uri, DEFAULT_CHARSET);
}
public QueryStringDecoder(URI uri){
public QueryStringDecoder(String uri, String charset) {
if (uri == null) {
throw new NullPointerException("uri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
this.uri = uri;
this.charset = charset;
}
public QueryStringDecoder(URI uri) {
this(uri, DEFAULT_CHARSET);
}
public QueryStringDecoder(URI uri, String charset){
if (uri == null) {
throw new NullPointerException("uri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
this.uri = uri.toASCIIString();
this.charset = charset;
}
public String getPath() {
@ -83,22 +114,25 @@ public class QueryStringDecoder {
String[] params = s.split("&");
for (String param : params) {
String[] split = param.split("=");
String key = removeSpaceDelimeters(split[0]);
String key = decodeComponent(split[0]);
List<String> values = this.params.get(key);
if(values == null) {
values = new ArrayList<String>();
this.params.put(key,values);
}
if (split.length > 1) {
values.add(removeSpaceDelimeters(split[1]));
values.add(decodeComponent(split[1]));
} else {
values.add("");
}
}
}
// FIXME Use URLDecoder or something equivalent
private String removeSpaceDelimeters(String s) {
return s.replaceAll("%20", " ");
private String decodeComponent(String s) {
try {
return URLDecoder.decode(s, charset);
} catch (UnsupportedEncodingException e) {
throw new UnsupportedCharsetException(charset);
}
}
}

View File

@ -21,33 +21,50 @@
*/
package org.jboss.netty.handler.codec.http;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Andy Taylor (andy.taylor@jboss.org)
* @author Trustin Lee (tlee@redhat.com)
* @version $Rev$, $Date$
*
* @apiviz.stereotype utility
*/
public class QueryStringEncoder {
private final String url;
private final String charset;
private final String uri;
private final List<Param> params = new ArrayList<Param>();
public QueryStringEncoder(String url) {
this.url = url;
public QueryStringEncoder(String uri) {
this(uri, QueryStringDecoder.DEFAULT_CHARSET);
}
public QueryStringEncoder(String uri, String charset) {
if (uri == null) {
throw new NullPointerException("uri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
this.uri = uri;
this.charset = charset;
}
public void addParam(String name, String value) {
if(name == null) {
throw new NullPointerException("name is null");
if (name == null) {
throw new NullPointerException("name");
}
if(value == null) {
throw new NullPointerException("value is null");
if (value == null) {
throw new NullPointerException("value");
}
params.add(new Param(name, value));
}
@ -58,14 +75,15 @@ public class QueryStringEncoder {
@Override
public String toString() {
if (params.size() == 0) {
return url;
}
else {
StringBuilder sb = new StringBuilder(url).append("?");
if (params.isEmpty()) {
return uri;
} else {
StringBuilder sb = new StringBuilder(uri).append("?");
for (int i = 0; i < params.size(); i++) {
Param param = params.get(i);
sb.append(replaceSpaces(param.name)).append("=").append(replaceSpaces(param.value));
sb.append(encodeComponent(param.name));
sb.append("=");
sb.append(encodeComponent(param.value));
if(i != params.size() - 1) {
sb.append("&");
}
@ -74,9 +92,12 @@ public class QueryStringEncoder {
}
}
// FIXME Use URLEncoder or something equivalent
private String replaceSpaces(String s) {
return s.replaceAll(" ", "%20");
private String encodeComponent(String s) {
try {
return URLEncoder.encode(s, charset).replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
throw new UnsupportedCharsetException(charset);
}
}
private static final class Param {