Skip to content

Commit e942bd1

Browse files
vaadin-botDenis
andauthored
fix: use getContentLengthLong instead getContentLength (#10506) (#10540)
Use Servlet 3.1 ServletRequest::getContentLengthLong to get the content size as a long value for the big files upload, because getContentLength may return -1 (file size is bigger than int capacity). Fixes #10392 Co-authored-by: Denis <denis@vaadin.com>
1 parent ce71f80 commit e942bd1

5 files changed

Lines changed: 102 additions & 11 deletions

File tree

flow-server/src/main/java/com/vaadin/flow/server/VaadinRequest.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package com.vaadin.flow.server;
1818

19+
import javax.servlet.ServletRequest;
20+
import javax.servlet.http.Cookie;
21+
import javax.servlet.http.HttpServletRequest;
22+
1923
import java.io.BufferedReader;
2024
import java.io.IOException;
2125
import java.io.InputStream;
@@ -25,10 +29,6 @@
2529
import java.util.Locale;
2630
import java.util.Map;
2731

28-
import javax.servlet.ServletRequest;
29-
import javax.servlet.http.Cookie;
30-
import javax.servlet.http.HttpServletRequest;
31-
3232
import com.vaadin.flow.internal.CurrentInstance;
3333

3434
/**
@@ -74,6 +74,19 @@ public interface VaadinRequest {
7474
*/
7575
int getContentLength();
7676

77+
/**
78+
* Returns the length of the request content that can be read from the input
79+
* stream returned by {@link #getInputStream()}.
80+
*
81+
* @see javax.servlet.ServletRequest#getContentLengthLong()
82+
*
83+
* @return a long containing the length of the request body or -1L if the
84+
* length is not known
85+
*/
86+
default long getContentLengthLong() {
87+
return getContentLength();
88+
}
89+
7790
/**
7891
* Returns an input stream from which the request content can be read. The
7992
* request content length can be obtained with {@link #getContentLength()}

flow-server/src/main/java/com/vaadin/flow/server/communication/StreamReceiverHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import javax.servlet.http.HttpServletRequest;
1919
import javax.servlet.http.HttpServletResponse;
2020
import javax.servlet.http.Part;
21+
2122
import java.io.BufferedWriter;
2223
import java.io.IOException;
2324
import java.io.InputStream;
@@ -237,7 +238,7 @@ private boolean handleMultipartFileUploadFromInputStream(VaadinSession session,
237238
VaadinRequest request, StreamReceiver streamReceiver,
238239
StateNode owner) throws IOException {
239240
boolean success = true;
240-
long contentLength = request.getContentLength();
241+
long contentLength = getContentLength(request);
241242
// Parse the request
242243
FileItemIterator iter;
243244
try {
@@ -554,13 +555,12 @@ private long updateProgress(VaadinSession session,
554555
* The request.getContentLength() is limited to "int" by the Servlet
555556
* specification. To support larger file uploads manually evaluate the
556557
* Content-Length header which can contain long values.
558+
*
559+
* @deprecated use {@link VaadinRequest#getContentLengthLong()} instead
557560
*/
561+
@Deprecated
558562
protected long getContentLength(VaadinRequest request) {
559-
try {
560-
return Long.parseLong(request.getHeader("Content-Length"));
561-
} catch (NumberFormatException e) {
562-
return -1l;
563-
}
563+
return request.getContentLengthLong();
564564
}
565565

566566
protected boolean isMultipartUpload(VaadinRequest request) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2000-2021 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.server;
17+
18+
import org.junit.Test;
19+
import org.mockito.Mockito;
20+
21+
public class VaadinRequestTest {
22+
23+
public static abstract class TestVaadinRequest implements VaadinRequest {
24+
25+
}
26+
27+
@Test
28+
public void getContentLengthLong_delegateToGetContentLength() {
29+
TestVaadinRequest request = Mockito.spy(TestVaadinRequest.class);
30+
request.getContentLengthLong();
31+
Mockito.verify(request).getContentLength();
32+
}
33+
34+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2000-2021 Vaadin Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package com.vaadin.flow.server;
17+
18+
import javax.servlet.http.HttpServletRequest;
19+
20+
import org.junit.Test;
21+
import org.mockito.Mockito;
22+
23+
public class VaadinServletRequestTest {
24+
25+
@Test
26+
public void getContentLengthLong_delegateToServletRequestGetContentLengthLong() {
27+
HttpServletRequest servletRequest = Mockito
28+
.mock(HttpServletRequest.class);
29+
30+
VaadinServletRequest request = new VaadinServletRequest(servletRequest,
31+
null);
32+
request.getContentLengthLong();
33+
Mockito.verify(servletRequest).getContentLengthLong();
34+
}
35+
}

flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ public class StreamReceiverHandlerTest {
8686
private String contentType;
8787
private List<Part> parts;
8888

89+
private boolean isGetContentLengthLongCalled;
90+
8991
@Before
9092
public void setup() throws Exception {
9193
contentLength = "6";
@@ -175,6 +177,12 @@ public Collection<Part> getParts()
175177
throws IOException, ServletException {
176178
return parts;
177179
}
180+
181+
@Override
182+
public long getContentLengthLong() {
183+
isGetContentLengthLongCalled = true;
184+
return 0;
185+
}
178186
};
179187
}
180188

@@ -274,14 +282,15 @@ public void doHandleXhrFilePost_happyPath_setContentTypeNoExplicitSetStatus()
274282
}
275283

276284
@Test
277-
public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500()
285+
public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500_getContentLengthLongCalled()
278286
throws IOException {
279287

280288
handler.doHandleMultipartFileUpload(session, request, response,
281289
streamReceiver, stateNode);
282290

283291
Mockito.verify(response)
284292
.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
293+
Assert.assertTrue(isGetContentLengthLongCalled);
285294
}
286295

287296
@Test

0 commit comments

Comments
 (0)