-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: copy headers from StreamResource to VaadinResponse
Copy all headers set on a StreamResource to VaadinResponse before writing contents. Fixes #203
- Loading branch information
1 parent
7feac4c
commit 3e6de7b
Showing
6 changed files
with
182 additions
and
4 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
...ts-generic/src/main/java/com/vaadin/flow/portal/streamresource/StreamResourceContent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.vaadin.flow.portal.streamresource; | ||
|
||
import java.io.ByteArrayInputStream; | ||
|
||
import com.vaadin.flow.component.html.Anchor; | ||
import com.vaadin.flow.component.orderedlayout.VerticalLayout; | ||
import com.vaadin.flow.server.StreamResource; | ||
|
||
public class StreamResourceContent extends VerticalLayout { | ||
|
||
static final String FILENAME = "export.xlsx"; | ||
|
||
public StreamResourceContent() { | ||
StreamResource downloadResource = new StreamResource(FILENAME, | ||
() -> new ByteArrayInputStream(new byte[0])); | ||
downloadResource.setContentType("application/xls"); | ||
downloadResource.setHeader("Content-Disposition", | ||
"attachment;filename=export.xlsx"); | ||
Anchor link = new Anchor(downloadResource, "Download File"); | ||
link.setId("downloadLink"); | ||
add(link); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...ts-generic/src/main/java/com/vaadin/flow/portal/streamresource/StreamResourcePortlet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.vaadin.flow.portal.streamresource; | ||
|
||
import com.vaadin.flow.portal.VaadinPortlet; | ||
|
||
public class StreamResourcePortlet | ||
extends VaadinPortlet<StreamResourceContent> { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
...s/tests-generic/src/test/java/com/vaadin/flow/portal/streamresource/StreamResourceIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.vaadin.flow.portal.streamresource; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
import org.openqa.selenium.JavascriptExecutor; | ||
|
||
import com.vaadin.flow.component.html.testbench.AnchorElement; | ||
import com.vaadin.flow.portal.AbstractPlutoPortalTest; | ||
|
||
public class StreamResourceIT extends AbstractPlutoPortalTest { | ||
|
||
public StreamResourceIT() { | ||
super("tests-generic", "streamresource"); | ||
} | ||
|
||
@Test | ||
public void downloadStreamResource_responseHeadersAreSent() { | ||
AnchorElement link = getVaadinPortletRootElement() | ||
.$(AnchorElement.class).id("downloadLink"); | ||
String url = link.getAttribute("href"); | ||
getDriver().manage().timeouts().setScriptTimeout(15, TimeUnit.SECONDS); | ||
|
||
Map<String, String> headers = downloadAndGetResponseHeaders(url); | ||
|
||
Assert.assertEquals( | ||
"attachment;filename=" + StreamResourceContent.FILENAME, | ||
headers.getOrDefault("content-disposition", null)); | ||
} | ||
|
||
/* | ||
* Stolen from stackexchange. | ||
* | ||
* It's not possible to use a straight way to download the link externally | ||
* since it will use another session and the link will be invalid in this | ||
* session. So either this pure client side way or external download with | ||
* cookies copy (which allows preserve the session) needs to be used. | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public Map<String, String> downloadAndGetResponseHeaders(String url) { | ||
String script = "var url = arguments[0];" | ||
+ "var callback = arguments[arguments.length - 1];" | ||
+ "var xhr = new XMLHttpRequest();" | ||
+ "xhr.open('GET', url, true);" | ||
+ "xhr.responseType = \"arraybuffer\";" + | ||
// force the HTTP response, response-type header to be array | ||
// buffer | ||
"xhr.onload = function() {" | ||
// Get the raw header string " | ||
+ " var headers = xhr.getAllResponseHeaders();" | ||
// Convert the header string into an array | ||
// of individual headers | ||
+ " var arr = headers.trim().split(/[\\r\\n]+/);" | ||
// Create a map of header names to values | ||
+ " var headerMap = {};" + " arr.forEach(function (line) { " | ||
+ " var parts = line.split(': '); " | ||
+ " var header = parts.shift().toLowerCase(); " | ||
+ " var value = parts.join(': '); " | ||
+ " headerMap[header] = value;" + " }); " | ||
+ " callback(headerMap);" + "};" + "xhr.send();"; | ||
Object response = ((JavascriptExecutor) getDriver()) | ||
.executeAsyncScript(script, url); | ||
return (Map<String, String>) response; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
vaadin-portlet/src/test/java/com/vaadin/flow/portal/PortletStreamResourceHandlerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.vaadin.flow.portal; | ||
|
||
import javax.portlet.MimeResponse; | ||
import javax.portlet.PortletRequest; | ||
import javax.portlet.PortletResponse; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.mockito.Mockito; | ||
|
||
import com.vaadin.flow.component.UI; | ||
import com.vaadin.flow.server.AbstractStreamResource; | ||
import com.vaadin.flow.server.StreamResource; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
public class PortletStreamResourceHandlerTest { | ||
|
||
private PortletStreamResourceHandler handler = new PortletStreamResourceHandler(); | ||
private VaadinPortletSession session; | ||
private VaadinPortletService service; | ||
|
||
@Before | ||
public void init() { | ||
service = Mockito.mock(VaadinPortletService.class); | ||
session = new VaadinPortletSession(service) { | ||
@Override | ||
public boolean hasLock() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public void lock() { | ||
} | ||
|
||
@Override | ||
public void unlock() { | ||
} | ||
|
||
@Override | ||
public void checkHasLock() { | ||
|
||
} | ||
}; | ||
} | ||
|
||
@Test | ||
public void handleRequest_shouldApplyStreamResourceHeaders() | ||
throws IOException { | ||
PortletRequest portletRequest = Mockito.mock(PortletRequest.class); | ||
VaadinPortletRequest request = new VaadinPortletRequest(portletRequest, | ||
service); | ||
MimeResponse portletResponse = Mockito.mock(MimeResponse.class); | ||
VaadinPortletResponse response = new VaadinPortletResponse( | ||
portletResponse, service); | ||
|
||
StreamResource resource = new StreamResource("export.xlsx", | ||
() -> new ByteArrayInputStream(new byte[0])); | ||
resource.setContentType("application/xls"); | ||
String headerName = "Content-Disposition"; | ||
String headerValue = "attachment;filename=export.xlsx"; | ||
resource.setHeader(headerName, headerValue); | ||
handler.handleRequest(session, request, response, resource); | ||
Mockito.verify(portletResponse, Mockito.atLeastOnce()).setProperty(headerName, headerValue); | ||
} | ||
|
||
} |