You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by aw...@apache.org on 2009/04/08 06:53:42 UTC
svn commit: r763104 - in /incubator/shindig/trunk/java/common/src:
main/java/org/apache/shindig/protocol/JsonRpcServlet.java
test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
Author: awiner
Date: Wed Apr 8 04:53:41 2009
New Revision: 763104
URL: http://svn.apache.org/viewvc?rev=763104&view=rev
Log:
SHINDIG-1009: content-type check should only be perfomed on "request" field of multipart/form-data
- Patch from Sachin Shenoy, with some minor changes to the test
Modified:
incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java?rev=763104&r1=763103&r2=763104&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java Wed Apr 8 04:53:41 2009
@@ -101,13 +101,12 @@
if (formParser.isMultipartContent(servletRequest)) {
for (FormDataItem item : formParser.parse(servletRequest)) {
- if (item.isFormField() && content == null) {
+ if (item.isFormField() && REQUEST_PARAM.equals(item.getFieldName()) && content == null) {
// As per spec, in case of a multipart/form-data content, there will be one form field
// with field name as "request". It will contain the json request. Any further form
// field or file item will not be parsed out, but will be exposed via getFormItem
- // method of RequestItem. Here we are lenient where a mime part which has content type
- // application/json will be considered as request.
- if (!REQUEST_PARAM.equals(item.getFieldName())) {
+ // method of RequestItem.
+ if (!StringUtils.isEmpty(item.getContentType())) {
checkContentTypes(ContentTypes.ALLOWED_JSON_CONTENT_TYPES, item.getContentType());
}
content = IOUtils.toString(item.getInputStream());
Modified: incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java?rev=763104&r1=763103&r2=763104&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java (original)
+++ incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java Wed Apr 8 04:53:41 2009
@@ -17,29 +17,24 @@
*/
package org.apache.shindig.protocol;
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Guice;
-
-import junit.framework.TestCase;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.classextension.EasyMock.reset;
import org.apache.shindig.common.JsonAssert;
import org.apache.shindig.common.testing.FakeGadgetToken;
import org.apache.shindig.protocol.conversion.BeanJsonConverter;
import org.apache.shindig.protocol.multipart.FormDataItem;
import org.apache.shindig.protocol.multipart.MultipartFormParser;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
import org.easymock.IMocksControl;
import org.easymock.classextension.EasyMock;
-import static org.easymock.classextension.EasyMock.reset;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -47,6 +42,12 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import junit.framework.TestCase;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.inject.Guice;
+
/**
*
*/
@@ -56,7 +57,8 @@
.setOwnerId("john.doe").setViewerId("john.doe");
private static final String IMAGE_FIELDNAME = "profile-photo";
- private static final byte[] IMAGE_DATA = "image data".getBytes();
+ private static final String IMAGE_DATA = "image data";
+ private static final byte[] IMAGE_DATA_BYTES = IMAGE_DATA.getBytes();
private static final String IMAGE_TYPE = "image/jpeg";
private HttpServletRequest req;
@@ -132,12 +134,12 @@
res.setCharacterEncoding("UTF-8");
res.setContentType(ContentTypes.OUTPUT_JSON_CONTENT_TYPE);
- List<FormDataItem> formItems = new ArrayList<FormDataItem>();
- String request = "{method:test.get,id:id,params:" +
- "{userId:5,groupId:@self,image-ref:@" + IMAGE_FIELDNAME + "}}";
+ List<FormDataItem> formItems = Lists.newArrayList();
+ String request = "{method:'test.get',id:'id',params:" +
+ "{userId:5,groupId:'@self',image-ref:'@" + IMAGE_FIELDNAME + "'}}";
formItems.add(mockFormDataItem(JsonRpcServlet.REQUEST_PARAM,
ContentTypes.OUTPUT_JSON_CONTENT_TYPE, request.getBytes(), true));
- formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA, false));
+ formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA_BYTES, false));
expect(multipartFormParser.isMultipartContent(req)).andReturn(true);
expect(multipartFormParser.parse(req)).andReturn(formItems);
expect(res.getWriter()).andReturn(writer);
@@ -147,15 +149,15 @@
servlet.service(req, res);
mockControl.verify();
- JsonAssert.assertJsonEquals("{id: 'id', data: {image-data:'" + new String(IMAGE_DATA) +
+ JsonAssert.assertJsonEquals("{id: 'id', data: {image-data:'" + IMAGE_DATA +
"', image-type:'" + IMAGE_TYPE + "', image-ref:'@" + IMAGE_FIELDNAME + "'}}", getOutput());
}
/**
- * Tests whether mime part with content type appliction/json is picked up as
- * request even when its fieldname is not "request".
+ * Test that it passes even when content-type is not set for "request" parameter. This would
+ * be the case where the request is published via webform.
*/
- public void testPostMultipartFormDataWithNoExplicitRequestField() throws Exception {
+ public void testPostMultipartFormDataWithRequestFieldHavingNoContentType() throws Exception {
reset(multipartFormParser);
handler.setMock(new TestHandler() {
@@ -174,12 +176,11 @@
res.setCharacterEncoding("UTF-8");
res.setContentType(ContentTypes.OUTPUT_JSON_CONTENT_TYPE);
- List<FormDataItem> formItems = new ArrayList<FormDataItem>();
- String request = "{method:test.get,id:id,params:" +
- "{userId:5,groupId:@self,image-ref:@" + IMAGE_FIELDNAME + "}}";
- formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA, false));
- formItems.add(mockFormDataItem("json", ContentTypes.OUTPUT_JSON_CONTENT_TYPE,
- request.getBytes(), true));
+ List<FormDataItem> formItems = Lists.newArrayList();
+ String request = "{method:'test.get',id:'id',params:" +
+ "{userId:5,groupId:'@self',image-ref:'@" + IMAGE_FIELDNAME + "'}}";
+ formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA_BYTES, false));
+ formItems.add(mockFormDataItem("request", null, request.getBytes(), true));
expect(multipartFormParser.isMultipartContent(req)).andReturn(true);
expect(multipartFormParser.parse(req)).andReturn(formItems);
expect(res.getWriter()).andReturn(writer);
@@ -189,11 +190,99 @@
servlet.service(req, res);
mockControl.verify();
- JsonAssert.assertJsonEquals("{id: 'id', data: {image-data:'" + new String(IMAGE_DATA) +
+ JsonAssert.assertJsonEquals("{id: 'id', data: {image-data:'" + IMAGE_DATA +
"', image-type:'" + IMAGE_TYPE + "', image-ref:'@" + IMAGE_FIELDNAME + "'}}", getOutput());
}
+ /**
+ * Test that any form-data other than "request" does not undergo any content type check.
+ */
+ public void testPostMultipartFormDataOnlyRequestFieldHasContentTypeChecked()
+ throws Exception {
+ reset(multipartFormParser);
+
+ handler.setMock(new TestHandler() {
+ @Override
+ public Object get(RequestItem req) {
+ FormDataItem item = req.getFormMimePart(IMAGE_FIELDNAME);
+ return ImmutableMap.of("image-data", new String(item.get()),
+ "image-type", item.getContentType(),
+ "image-ref", req.getParameter("image-ref"));
+ }
+ });
+ expect(req.getMethod()).andStubReturn("POST");
+ expect(req.getAttribute(isA(String.class))).andReturn(FAKE_GADGET_TOKEN);
+ expect(req.getCharacterEncoding()).andStubReturn("UTF-8");
+ expect(req.getContentType()).andStubReturn(ContentTypes.MULTIPART_FORM_CONTENT_TYPE);
+ res.setCharacterEncoding("UTF-8");
+ res.setContentType(ContentTypes.OUTPUT_JSON_CONTENT_TYPE);
+
+ List<FormDataItem> formItems = Lists.newArrayList();
+ String request = "{method:'test.get',id:'id',params:" +
+ "{userId:5,groupId:'@self',image-ref:'@" + IMAGE_FIELDNAME + "'}}";
+ formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA_BYTES, false));
+ formItems.add(mockFormDataItem("oauth_hash", "application/octet-stream",
+ "oauth-hash".getBytes(), true));
+ formItems.add(mockFormDataItem("request", null, request.getBytes(), true));
+ formItems.add(mockFormDataItem("oauth_signature", "application/octet-stream",
+ "oauth_signature".getBytes(), true));
+ expect(multipartFormParser.isMultipartContent(req)).andReturn(true);
+ expect(multipartFormParser.parse(req)).andReturn(formItems);
+ expect(res.getWriter()).andReturn(writer);
+ expectLastCall();
+
+ mockControl.replay();
+ servlet.service(req, res);
+ mockControl.verify();
+
+ JsonAssert.assertJsonEquals("{id: 'id', data: {image-data:'" + IMAGE_DATA +
+ "', image-type:'" + IMAGE_TYPE + "', image-ref:'@" + IMAGE_FIELDNAME + "'}}", getOutput());
+ }
+
+ /**
+ * Test that "request" field undergoes contentType check, and error is thrown if wrong content
+ * type is present.
+ */
+ public void testPostMultipartFormDataRequestFieldIsSubjectedToContentTypeCheck()
+ throws Exception {
+ reset(multipartFormParser);
+
+ handler.setMock(new TestHandler() {
+ @Override
+ public Object get(RequestItem req) {
+ FormDataItem item = req.getFormMimePart(IMAGE_FIELDNAME);
+ return ImmutableMap.of("image-data", item.get(),
+ "image-type", item.getContentType(),
+ "image-ref", req.getParameter("image-ref"));
+ }
+ });
+ expect(req.getMethod()).andStubReturn("POST");
+ expect(req.getAttribute(isA(String.class))).andReturn(FAKE_GADGET_TOKEN);
+ expect(req.getCharacterEncoding()).andStubReturn("UTF-8");
+ expect(req.getContentType()).andStubReturn(ContentTypes.MULTIPART_FORM_CONTENT_TYPE);
+ res.setCharacterEncoding("UTF-8");
+ res.setContentType(ContentTypes.OUTPUT_JSON_CONTENT_TYPE);
+
+ List<FormDataItem> formItems = Lists.newArrayList();
+ String request = "{method:'test.get',id:'id',params:" +
+ "{userId:5,groupId:'@self',image-ref:'@" + IMAGE_FIELDNAME + "'}}";
+ formItems.add(mockFormDataItem(IMAGE_FIELDNAME, IMAGE_TYPE, IMAGE_DATA_BYTES, false));
+ formItems.add(mockFormDataItem("request", "application/octet-stream", request.getBytes(),
+ true));
+ expect(multipartFormParser.isMultipartContent(req)).andReturn(true);
+ expect(multipartFormParser.parse(req)).andReturn(formItems);
+ expect(res.getWriter()).andReturn(writer);
+ expectLastCall();
+
+ mockControl.replay();
+ servlet.service(req, res);
+ mockControl.verify();
+
+ String output = getOutput();
+ assertTrue(-1 != output.indexOf("Unsupported Content-Type application/octet-stream"));
+ }
+
public void testInvalidService() throws Exception {
setupRequest("{method:junk.get,id:id,params:{userId:5,groupId:@self}}");