You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/01/09 00:37:03 UTC
[incubator-servicecomb-java-chassis] branch master updated: SCB-199
bug fix: consumer upload file, did not set correct boundary contentType
This is an automated email from the ASF dual-hosted git repository.
ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 8369fab SCB-199 bug fix: consumer upload file, did not set correct boundary contentType
8369fab is described below
commit 8369fab8767d3983fbeb9b84f9d715cb8e9cade0
Author: wujimin <wu...@huawei.com>
AuthorDate: Thu Jan 4 10:17:34 2018 +0800
SCB-199 bug fix: consumer upload file, did not set correct boundary contentType
---
.../rest/codec/param/RestClientRequestImpl.java | 12 +-
.../codec/param/TestRestClientRequestImpl.java | 46 +++++-
.../client/CodeFirstRestTemplateSpringmvc.java | 17 ++-
.../demo/springmvc/server/CodeFirstSpringmvc.java | 10 +-
.../foundation/common/part/AbstractPart.java | 22 ++-
.../foundation/common/part/FilePart.java | 2 +-
.../foundation/common/part/ResourcePart.java | 2 +-
.../src/main/resources/META-INF/mime.types | 157 +++++++++++++++++++++
.../foundation/common/part/TestAbstractPart.java | 26 +++-
9 files changed, 278 insertions(+), 16 deletions(-)
diff --git a/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java b/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
index 2eda363..67a257b 100644
--- a/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
+++ b/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
@@ -192,7 +192,7 @@ public class RestClientRequestImpl implements RestClientRequest {
attachFile(boundary, uploadsIterator);
});
- Buffer fileHeader = fileBoundaryInfo(boundary, name, filename);
+ Buffer fileHeader = fileBoundaryInfo(boundary, name, part);
request.write(fileHeader);
Pump.pump(fileStream, request).start();
}
@@ -203,12 +203,16 @@ public class RestClientRequestImpl implements RestClientRequest {
.appendString("--" + boundary + "--\r\n");
}
- private Buffer fileBoundaryInfo(String boundary, String name, String filename) {
+ protected Buffer fileBoundaryInfo(String boundary, String name, Part part) {
Buffer buffer = Buffer.buffer();
buffer.appendString("\r\n");
buffer.appendString("--" + boundary + "\r\n");
- buffer.appendString("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n");
- buffer.appendString("Content-Type: multipart/form-data\r\n");
+ buffer.appendString("Content-Disposition: form-data; name=\"")
+ .appendString(name)
+ .appendString("\"; filename=\"")
+ .appendString(part.getSubmittedFileName() != null ? part.getSubmittedFileName() : "null")
+ .appendString("\"\r\n");
+ buffer.appendString("Content-Type: ").appendString(part.getContentType()).appendString("\r\n");
buffer.appendString("Content-Transfer-Encoding: binary\r\n");
buffer.appendString("\r\n");
return buffer;
diff --git a/common/common-rest/src/test/java/io/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java b/common/common-rest/src/test/java/io/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
index f56e711..68a2e1e 100644
--- a/common/common-rest/src/test/java/io/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
+++ b/common/common-rest/src/test/java/io/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
@@ -16,6 +16,9 @@
*/
package io.servicecomb.common.rest.codec.param;
+import javax.servlet.http.Part;
+import javax.ws.rs.core.MediaType;
+
import org.junit.Assert;
import org.junit.Test;
@@ -24,6 +27,7 @@ import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.CaseInsensitiveHeaders;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpHeaders;
+import mockit.Expectations;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;
@@ -66,7 +70,47 @@ public class TestRestClientRequestImpl {
restClientRequest.end();
Buffer buffer = restClientRequest.getBodyBuffer();
Assert.assertEquals("I love servicecomb", buffer.toString());
- Assert.assertEquals("sessionid=abcdefghijklmnopqrstuvwxyz; region=china-north; ",
+ Assert.assertEquals("sessionid=abcdefghijklmnopqrstuvwxyz; region=china-north; ",
restClientRequest.request.headers().get(HttpHeaders.COOKIE));
}
+
+ @Test
+ public void fileBoundaryInfo_nullSubmittedFileName(@Mocked Part part) {
+ new Expectations() {
+ {
+ part.getSubmittedFileName();
+ result = null;
+ part.getContentType();
+ result = "abc";
+ }
+ };
+ RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null);
+ Buffer buffer = restClientRequest.fileBoundaryInfo("boundary", "name", part);
+ Assert.assertEquals("\r\n" +
+ "--boundary\r\n" +
+ "Content-Disposition: form-data; name=\"name\"; filename=\"null\"\r\n" +
+ "Content-Type: abc\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n", buffer.toString());
+ }
+
+ @Test
+ public void fileBoundaryInfo_validSubmittedFileName(@Mocked Part part) {
+ new Expectations() {
+ {
+ part.getSubmittedFileName();
+ result = "a.txt";
+ part.getContentType();
+ result = MediaType.TEXT_PLAIN;
+ }
+ };
+ RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null);
+ Buffer buffer = restClientRequest.fileBoundaryInfo("boundary", "name", part);
+ Assert.assertEquals("\r\n" +
+ "--boundary\r\n" +
+ "Content-Disposition: form-data; name=\"name\"; filename=\"a.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n", buffer.toString());
+ }
}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
index d588c22..485b051 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
@@ -100,7 +100,14 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
File someFile = File.createTempFile("upload2", ".txt");
FileUtils.writeStringToFile(someFile, file2Content);
- String expect = file1.getName() + ":" + file1Content + "\n" + someFile.getName() + ":" + file2Content;
+ String expect = String.format("%s:%s:%s\n"
+ + "%s:%s:%s",
+ file1.getName(),
+ MediaType.TEXT_PLAIN_VALUE,
+ file1Content,
+ someFile.getName(),
+ MediaType.TEXT_PLAIN_VALUE,
+ file2Content);
String result = testRestTemplateUpload(template, cseUrlPrefix, file1, someFile);
TestMgr.check(expect, result);
@@ -108,7 +115,13 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
result = uploadPartAndFile.fileUpload(new FilePart(null, file1), someFile);
TestMgr.check(expect, result);
- expect = "null:" + file1Content + "\n" + someFile.getName() + ":" + file2Content;
+ expect = String.format("null:%s:%s\n"
+ + "%s:%s:%s",
+ MediaType.APPLICATION_OCTET_STREAM_VALUE,
+ file1Content,
+ someFile.getName(),
+ MediaType.TEXT_PLAIN_VALUE,
+ file2Content);
result = uploadStreamAndResource
.fileUpload(new ByteArrayInputStream(file1Content.getBytes(StandardCharsets.UTF_8)),
new PathResource(someFile.getAbsolutePath()));
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 7176abe..cfe4bc9 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -94,8 +94,14 @@ public class CodeFirstSpringmvc {
try (InputStream is1 = file1.getInputStream(); InputStream is2 = file2.getInputStream()) {
String content1 = IOUtils.toString(is1);
String content2 = IOUtils.toString(is2);
- return file1.getOriginalFilename() + ":" + content1 + "\n" +
- file2.getSubmittedFileName() + ":" + content2;
+ return String.format("%s:%s:%s\n"
+ + "%s:%s:%s",
+ file1.getOriginalFilename(),
+ file1.getContentType(),
+ content1,
+ file2.getSubmittedFileName(),
+ file2.getContentType(),
+ content2);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
diff --git a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
index 9a152f8..6011261 100644
--- a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
@@ -21,15 +21,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
+import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.Part;
import javax.ws.rs.core.MediaType;
public class AbstractPart implements Part {
+ private static MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap();
+
protected String name;
- protected String submittedFileName;
+ private String submittedFileName;
- protected String contentType = MediaType.MULTIPART_FORM_DATA;
+ protected String contentType;
@Override
public InputStream getInputStream() throws IOException {
@@ -38,7 +41,7 @@ public class AbstractPart implements Part {
@Override
public String getContentType() {
- return contentType;
+ return contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM;
}
@SuppressWarnings("unchecked")
@@ -57,6 +60,19 @@ public class AbstractPart implements Part {
return submittedFileName;
}
+ public void setSubmittedFileName(String submittedFileName) {
+ this.submittedFileName = submittedFileName;
+ updateContentType();
+ }
+
+ private void updateContentType() {
+ if (contentType != null || submittedFileName == null) {
+ return;
+ }
+
+ contentType = mimetypesFileTypeMap.getContentType(submittedFileName);
+ }
+
@Override
public long getSize() {
throw new Error("not supported method");
diff --git a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
index aed6c6d..72ea50e 100644
--- a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
@@ -34,7 +34,7 @@ public class FilePart extends AbstractPart {
public FilePart(String name, File file) {
this.name = name;
this.file = file;
- this.submittedFileName = this.file.getName();
+ this.setSubmittedFileName(this.file.getName());
}
@Override
diff --git a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
index 22c53e4..a236c44 100644
--- a/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
@@ -28,7 +28,7 @@ public class ResourcePart extends AbstractPart {
public ResourcePart(String name, Resource resource) {
this.name = name;
this.resource = resource;
- this.submittedFileName = resource.getFilename();
+ this.setSubmittedFileName(resource.getFilename());
}
@Override
diff --git a/foundations/foundation-common/src/main/resources/META-INF/mime.types b/foundations/foundation-common/src/main/resources/META-INF/mime.types
new file mode 100644
index 0000000..3e85536
--- /dev/null
+++ b/foundations/foundation-common/src/main/resources/META-INF/mime.types
@@ -0,0 +1,157 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+application/octet-stream bin
+application/astound asd,asn
+application/fastman lcc
+application/java-archive jar
+application/java-serialized-object ser
+application/java-vm class
+application/mac-binhex40 hqx
+application/x-stuffit sit
+application/mbedlet mbd
+application/msword doc,dot,wiz,rtf
+application/oda oda
+application/pdf pdf
+application/postscript ai,eps,ps
+application/studiom smp
+application/timbuktu tbt
+application/vnd.ms-excel xls,xlw,xla,xlc,xlm,xlt
+application/vnd.ms-powerpoint ppt,pps,pot
+application/vnd.ms-project mpp
+application/winhlp hlp
+application/x-javascript js
+application/x-javascript;charset=UTF-8 jsu
+application/x-java-jnlp-file jnlp
+application/x-aim aim
+application/x-asap asp
+application/x-csh csh
+application/x-dvi dvi
+application/x-earthtime etc
+application/x-envoy evy
+application/x-gtar gtar
+application/x-cpio cpio
+application/x-hdf hdf
+application/x-latex latex
+application/x-javascript-config jsc
+application/x-maker fm
+application/x-mif mif,mi
+application/x-mocha mocha,moc
+application/x-msaccess mdb
+application/x-mscardfile crd
+application/x-msclip clp
+application/x-msmediaview m13,m14
+application/x-msmetafile wmf
+application/x-msmoney mny
+application/x-mspublisher pub
+application/x-msschedule scd
+application/x-msterminal trm
+application/x-mswrite wri
+application/x-NET-Install ins
+application/x-netcdf nc,cdf
+application/x-ns-proxy-autoconfig proxy
+application/x-salsa slc
+application/x-sh sh
+application/x-shar shar
+application/x-sprite spr,sprite
+application/x-tar tar
+application/x-tcl tcl
+application/x-perl pl
+application/x-tex tex
+application/x-texinfo texinfo,texi
+application/x-timbuktu tbp
+application/x-tkined tki,tkined
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-troff t,tr,roff
+application/x-wais-source src
+application/zip zip
+application/pre-encrypted enc
+application/x-pkcs7-crl crl
+application/x-fortezza-ckl ckl
+application/xml-dtd dtd
+
+audio/basic au,snd
+audio/echospeech es,esl
+audio/midi midi,mid
+audio/x-aiff aif,aiff,aifc
+audio/x-wav wav
+audio/x-pn-realaudio ra,ram
+audio/x-pac pac
+audio/x-epac pae
+audio/x-liveaudio lam
+
+drawing/x-dwf dwf
+
+image/fif fif
+image/x-icon ico
+image/gif gif
+image/ief ief
+image/ifs ifs
+image/jpeg jpeg,jpg,jpe,jfif,pjpeg,pjp
+image/png png
+image/tiff tiff,tif
+image/vnd dwg,svf
+image/wavelet wi
+image/bmp bmp
+image/x-photo-cd pcd
+image/x-cmu-raster ras
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+
+text/css css
+
+text/html htm,html
+text/plain txt
+text/richtext rtx
+text/tab-separated-values tsv
+text/x-setext etx
+text/x-speech talk
+text/xml xml
+text/xul xul
+
+video/isivideo fvi
+video/mpeg mpeg,mpg,mpe,mpv,vbs,mpegv
+video/x-mpeg2 mpv2,mp2v
+video/msvideo avi
+video/quicktime qt,mov,moov
+video/vivo viv,vivo
+video/wavelet wv
+video/x-sgi-movie movie
+
+x-world/x-svr svr
+x-world/x-vrml wrl
+x-world/x-vrt vrt
+
+x-conference/x-cooltalk ice
+
+magnus-internal/imagemap map
+magnus-internal/parsed-html shtml
+magnus-internal/cgi cgi,exe,bat
+
+application/x-x509-ca-cert cacert
+
+application/x-x509-server-cert scert
+application/x-x509-user-cert ucert
+application/x-x509-email-cert ecert
+
diff --git a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java
index dcd5177..20c581d 100644
--- a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java
+++ b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java
@@ -47,7 +47,7 @@ public class TestAbstractPart {
@Test
public void getContentType() throws IOException {
- Assert.assertEquals(MediaType.MULTIPART_FORM_DATA, part.getContentType());
+ Assert.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType());
String contentType = "abc";
part.contentType(contentType);
@@ -68,11 +68,33 @@ public class TestAbstractPart {
Assert.assertNull(part.getSubmittedFileName());
String submittedFileName = "abc";
- part.submittedFileName = submittedFileName;
+ part.setSubmittedFileName(submittedFileName);
Assert.assertEquals(submittedFileName, part.getSubmittedFileName());
}
@Test
+ public void setSubmittedFileName_contentTypeNotNull() {
+ part.contentType(MediaType.TEXT_PLAIN);
+ part.setSubmittedFileName("a.zip");
+
+ Assert.assertEquals(MediaType.TEXT_PLAIN, part.getContentType());
+ }
+
+ @Test
+ public void setSubmittedFileName_setNull() {
+ part.setSubmittedFileName(null);
+
+ Assert.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType());
+ }
+
+ @Test
+ public void setSubmittedFileName_setNormal() {
+ part.setSubmittedFileName("a.zip");
+
+ Assert.assertEquals("application/zip", part.getContentType());
+ }
+
+ @Test
public void getSize() {
initExpectedException();
--
To stop receiving notification emails like this one, please contact
['"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>'].