Skip to content

Commit

Permalink
RESTEASY-477 (#799)
Browse files Browse the repository at this point in the history
FormUrlEncodedProvider processes charsets.
  • Loading branch information
ronsigal committed May 11, 2016
1 parent a20d868 commit a551f7b
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 11 deletions.
@@ -0,0 +1,110 @@
package org.jboss.resteasy.test.nextgen.providers;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.spi.ResteasyDeployment;
import org.jboss.resteasy.test.EmbeddedContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import junit.framework.Assert;

/**
* RESTEASY-477
*
* @author <a href="mailto:ron.sigal@jboss.com">Ron Sigal</a>
* @date
*/
public class FormUrlEncodedCharsetTest
{
protected static ResteasyDeployment deployment;
protected static Dispatcher dispatcher;
protected static MediaType testMediaType8 = MediaType.APPLICATION_FORM_URLENCODED_TYPE.withCharset(StandardCharsets.UTF_8.displayName());
protected static MediaType testMediaType16 = MediaType.APPLICATION_FORM_URLENCODED_TYPE.withCharset(StandardCharsets.UTF_16.displayName());
protected static String charsetName;
protected static String alephBetGimel = "אבג";

@Path("test")
public static class TestResource
{
@POST
public Response form(MultivaluedMap<String, String> form) throws UnsupportedEncodingException
{
String s = form.getFirst("name");
System.out.println("s: " + s);
return Response.ok().entity(s).build();
}
}

@Before
public void before() throws Exception
{
deployment = EmbeddedContainer.start();
dispatcher = deployment.getDispatcher();
deployment.getRegistry().addPerRequestResource(TestResource.class);
}

@After
public void after() throws Exception
{
EmbeddedContainer.stop();
dispatcher = null;
deployment = null;
}

@Test
public void testFormDefault() throws UnsupportedEncodingException
{
Client client = ClientBuilder.newClient();;
WebTarget target = client.target("http://localhost:8081/test");
Form form = new Form();
form.param("name", alephBetGimel);
Entity<Form> entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
Response response = target.request().post(entity);
String result = response.readEntity(String.class);
System.out.println("result: " + result);
Assert.assertEquals(result, alephBetGimel);
}

@Test
public void testFormUTF8() throws UnsupportedEncodingException
{
Client client = ClientBuilder.newClient();;
WebTarget target = client.target("http://localhost:8081/test");
Form form = new Form();
form.param("name", alephBetGimel);
Entity<Form> entity = Entity.entity(form, testMediaType8);
Response response = target.request().post(entity);
String result = response.readEntity(String.class);
System.out.println("result: " + result);
Assert.assertEquals(result, alephBetGimel);
}

@Test
public void testFormUTF16() throws UnsupportedEncodingException
{
Client client = ClientBuilder.newClient();;
WebTarget target = client.target("http://localhost:8081/test");
Form form = new Form();
form.param("name", alephBetGimel);
Entity<Form> entity = Entity.entity(form, testMediaType16);
Response response = target.request().post(entity);
String result = response.readEntity(String.class);
System.out.println("result: " + result);
Assert.assertEquals(result, alephBetGimel);
}
}
Expand Up @@ -58,16 +58,25 @@ public MultivaluedMap readFrom(Class<MultivaluedMap> type, Type genericType, Ann
{
if (NoContent.isContentLengthZero(httpHeaders)) return new MultivaluedMapImpl<String, String>();
boolean encoded = FindAnnotation.findAnnotation(annotations, Encoded.class) != null;
if (encoded) return parseForm(entityStream);
else return Encode.decode(parseForm(entityStream));
String charset = mediaType.getParameters().get(MediaType.CHARSET_PARAMETER);
if (charset == null)
{
charset = "UTF-8";
}
if (encoded) return parseForm(entityStream, charset);
else return Encode.decode(parseForm(entityStream, charset), charset);
}

public static MultivaluedMap<String, String> parseForm(InputStream entityStream)
public static MultivaluedMap<String, String> parseForm(InputStream entityStream, String charset)
throws IOException
{
char[] buffer = new char[100];
StringBuffer buf = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(entityStream));
if (charset == null)
{
charset = "UTF-8";
}
BufferedReader reader = new BufferedReader(new InputStreamReader(entityStream, charset));

int wasRead = 0;
do
Expand Down Expand Up @@ -121,23 +130,28 @@ public long getSize(MultivaluedMap stringStringMultivaluedMap, Class<?> type, Ty
public void writeTo(MultivaluedMap data, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException
{
MultivaluedMap<String, String> formData = (MultivaluedMap<String, String>)data;
String charset = mediaType.getParameters().get(MediaType.CHARSET_PARAMETER);
if (charset == null)
{
charset = "UTF-8";
}
boolean encoded = FindAnnotation.findAnnotation(annotations, Encoded.class) != null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(baos, "UTF-8");
OutputStreamWriter writer = new OutputStreamWriter(baos, charset);

boolean first = true;
for (Map.Entry<String, List<String>> entry : formData.entrySet())
{
String encodedName = entry.getKey();
if (!encoded) encodedName = URLEncoder.encode(entry.getKey(), "UTF-8");
if (!encoded) encodedName = URLEncoder.encode(entry.getKey(), charset);

for (String value : entry.getValue())
{
if (first) first = false;
else writer.write("&");
if (!encoded)
{
value = URLEncoder.encode(value, "UTF-8");
value = URLEncoder.encode(value, charset);
}
writer.write(encodedName);
writer.write("=");
Expand Down
Expand Up @@ -45,11 +45,12 @@ public MultivaluedMap<String, String> getFormParameters()
formParameters = Encode.encode(decodedFormParameters);
return formParameters;
}
if (getHttpHeaders().getMediaType().isCompatible(MediaType.valueOf("application/x-www-form-urlencoded")))
MediaType mt = getHttpHeaders().getMediaType();
if (mt.isCompatible(MediaType.valueOf("application/x-www-form-urlencoded")))
{
try
{
formParameters = FormUrlEncodedProvider.parseForm(getInputStream());
formParameters = FormUrlEncodedProvider.parseForm(getInputStream(), mt.getParameters().get(MediaType.CHARSET_PARAMETER));
}
catch (IOException e)
{
Expand Down
Expand Up @@ -72,11 +72,12 @@ public MultivaluedMap<String, String> getMutableHeaders()
public MultivaluedMap<String, String> getPutFormParameters()
{
if (formParameters != null) return formParameters;
if (MediaType.APPLICATION_FORM_URLENCODED_TYPE.isCompatible(getHttpHeaders().getMediaType()))
MediaType mt = getHttpHeaders().getMediaType();
if (MediaType.APPLICATION_FORM_URLENCODED_TYPE.isCompatible(mt))
{
try
{
formParameters = FormUrlEncodedProvider.parseForm(getInputStream());
formParameters = FormUrlEncodedProvider.parseForm(getInputStream(), mt.getParameters().get(MediaType.CHARSET_PARAMETER));
}
catch (IOException e)
{
Expand Down
Expand Up @@ -492,6 +492,38 @@ public static MultivaluedMap<String, String> decode(MultivaluedMap<String, Strin
}
return decoded;
}

/**
* decode an encoded map
*
* @param map
* @param charset
* @return
*/
public static MultivaluedMap<String, String> decode(MultivaluedMap<String, String> map, String charset)
{
if (charset == null)
{
charset = UTF_8;
}
MultivaluedMapImpl<String, String> decoded = new MultivaluedMapImpl<String, String>();
for (Map.Entry<String, List<String>> entry : map.entrySet())
{
List<String> values = entry.getValue();
for (String value : values)
{
try
{
decoded.add(URLDecoder.decode(entry.getKey(), charset), URLDecoder.decode(value, charset));
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
}
return decoded;
}

public static MultivaluedMap<String, String> encode(MultivaluedMap<String, String> map)
{
Expand Down

0 comments on commit a551f7b

Please sign in to comment.