Skip to content

Commit

Permalink
fix: use getContentLengthLong instead getContentLength (#10506)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Denis committed Apr 1, 2021
1 parent 1ea4cef commit 1f1f154
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

package com.vaadin.flow.server;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -25,10 +29,6 @@
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import com.vaadin.flow.internal.CurrentInstance;

/**
Expand Down Expand Up @@ -74,6 +74,19 @@ public interface VaadinRequest {
*/
int getContentLength();

/**
* Returns the length of the request content that can be read from the input
* stream returned by {@link #getInputStream()}.
*
* @see javax.servlet.ServletRequest#getContentLengthLong()
*
* @return a long containing the length of the request body or -1L if the
* length is not known
*/
default long getContentLengthLong() {
return getContentLength();
}

/**
* Returns an input stream from which the request content can be read. The
* request content length can be obtained with {@link #getContentLength()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -237,7 +238,7 @@ private boolean handleMultipartFileUploadFromInputStream(
VaadinSession session, VaadinRequest request,
StreamReceiver streamReceiver, StateNode owner) throws IOException {
boolean success = true;
long contentLength = request.getContentLength();
long contentLength = getContentLength(request);
// Parse the request
FileItemIterator iter;
try {
Expand Down Expand Up @@ -576,13 +577,12 @@ private long updateProgress(VaadinSession session,
* The request.getContentLength() is limited to "int" by the Servlet
* specification. To support larger file uploads manually evaluate the
* Content-Length header which can contain long values.
*
* @deprecated use {@link VaadinRequest#getContentLengthLong()} instead
*/
@Deprecated
protected long getContentLength(VaadinRequest request) {
try {
return Long.parseLong(request.getHeader("Content-Length"));
} catch (NumberFormatException e) {
return -1l;
}
return request.getContentLengthLong();
}

protected boolean isMultipartUpload(VaadinRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2021 Vaadin Ltd.
*
* Licensed 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.
*/
package com.vaadin.flow.server;

import org.junit.Test;
import org.mockito.Mockito;

public class VaadinRequestTest {

public static abstract class TestVaadinRequest implements VaadinRequest {

}

@Test
public void getContentLengthLong_delegateToGetContentLength() {
TestVaadinRequest request = Mockito.spy(TestVaadinRequest.class);
request.getContentLengthLong();
Mockito.verify(request).getContentLength();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2021 Vaadin Ltd.
*
* Licensed 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.
*/
package com.vaadin.flow.server;

import javax.servlet.http.HttpServletRequest;

import org.junit.Test;
import org.mockito.Mockito;

public class VaadinServletRequestTest {

@Test
public void getContentLengthLong_delegateToServletRequestGetContentLengthLong() {
HttpServletRequest servletRequest = Mockito
.mock(HttpServletRequest.class);

VaadinServletRequest request = new VaadinServletRequest(servletRequest,
null);
request.getContentLengthLong();
Mockito.verify(servletRequest).getContentLengthLong();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public class StreamReceiverHandlerTest {
private String contentType;
private List<Part> parts;

private boolean isGetContentLengthLongCalled;

@Before
public void setup() throws Exception {
contentLength = "6";
Expand Down Expand Up @@ -172,6 +174,12 @@ public Collection<Part> getParts()
throws IOException, ServletException {
return parts;
}

@Override
public long getContentLengthLong() {
isGetContentLengthLongCalled = true;
return 0;
}
};
}

Expand Down Expand Up @@ -271,14 +279,15 @@ public void doHandleXhrFilePost_happyPath_setContentTypeNoExplicitSetStatus()
}

@Test
public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500()
public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500_getContentLengthLongCalled()
throws IOException {

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

Mockito.verify(response)
.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
Assert.assertTrue(isGetContentLengthLongCalled);
}

@Test
Expand Down

0 comments on commit 1f1f154

Please sign in to comment.