flow icon indicating copy to clipboard operation
flow copied to clipboard

23.1.0 Dynamic Image Resource not resolved (works with 23.0.11)

Open mrgreywater opened this issue 3 years ago • 5 comments

Description of the bug

I'm running multiple Vaadin Spring Servlets, and the root servlet running at path /* cannot properly resolve image resources since version 23.1.0.

I'm registering Images like so: return new Image(new StreamResource(name, () -> new ByteArrayInputStream(data)), name); resulting in a call to StreamResourceRegistry::registerSource where the resource is put in the session registry.

In 23.0.11 StreamRequestHandler::handleRequest properly figures out the correct session registry the resource was registered to, and displays the image. In 23.1.0 a different session registry than the one where the resource was added to is found for the request resulting in response.sendError(HttpServletResponse.SC_NOT_FOUND, "Resource is not found for path=" + pathInfo);

Expected behavior

Dynamic Image Resource resolves as it did in 23.0.11.

Minimal reproducible example

Would probably take a workday to create one to be honest.

Basically I have three SpringServlets (without rootMapping)

One SpringServlet with the mapping "/*" A second SpringServlet with the mapping "/1/*" And a third SpringServlet with the mapping "/2/*"

The second and third SpringServlet can use dynamic resources fine, the first one cannot load them since 23.1.0

May be related to #13795

Versions

  • Vaadin / Flow version: 23.1.0
  • Java version: OpenJDK 17
  • OS version: Windows 11
  • Browser version (if applicable): -
  • Application Server (if applicable): -
  • IDE (if applicable): Intellij IDEA

mrgreywater avatar Jun 10 '22 14:06 mrgreywater

I have the feeling the problem may be that here https://github.com/vaadin/flow/commit/f570561#diff-75fc0cfcc226080cc330db93bedfbe5b6e1c5dc81908a7c7adf6be1e84ee6e15R85 /Vaadin/* is added as mapping for each servlet, which maybe makes the request get handled by a different servlet than the resource was registered to, as multiple servlets include the same /Vaadin/* mapping. I really don't have enough knowledge of how vaadin does it's route mapping internally to know for sure though.

mrgreywater avatar Jun 10 '22 15:06 mrgreywater

All dynamic resource requests are still supposed to go to /somepath/VAADIN/…. and not /VAADIN/…

If they go to VAADIN in the root of the context, it certainly won’t work correctly

Artur- avatar Jun 10 '22 16:06 Artur-

@Artur- I think there's a misunderstanding the only place where dynamic resources don't seem to work is the servlet for the root path /*:

Before in version 23.0.11: Dynamic resource from SpringServlet with mapping /* -> /VAADIN/dynamic/resource/0/04438ac2-0cd2-4753-b845-e6a5dbf3cee1/LOGO_BIG -> resolved correctly Dynamic resource from SpringServlet with mapping /1/* -> /1/VAADIN/dynamic/resource/0/0c11e399-0d66-48a6-aae3-c3871bd425e8/LOGO_SMALL-> resolved correctly

Now in version 23.1.0 Dynamic resource from SpringServlet with mapping /* -> /VAADIN/dynamic/resource/0/ee4dca8d-d4a2-4630-a010-320822f6c569/LOGO_BIG -> 404 Dynamic resource from SpringServlet with mapping /1/* -> /1/VAADIN/dynamic/resource/0/cdb0edf1-9fe4-4fe0-b7db-68bbc52b67e3/LOGO_SMALL-> resolved correctly

mrgreywater avatar Jun 10 '22 16:06 mrgreywater

Alright so a guess about the problem. The VaadinSession instance is tied to the servlet so it will be different for the /* and the /VAADIN/* servlet. The UI instance is part of the /* VaadinSession and the resource is registered there, the request goes to the /VAADIN/* servlet and that VaadinSession has no resources registered at all.

->

If you have a /* Vaadin servlet mapping, there should never be a separate /VAADIN/* servlet as it won't work. The /* servlet will handle everything needed.

If you handle your servlet registrations manually you probably never want the Vaadin servlet registration logic to even run.

Artur- avatar Jun 10 '22 17:06 Artur-

Okay, so I removed my custom registered root servlet. It seems to work properly now. But I'd rather use my own custom SpringServlet, and not the default Vaadin one. How would I go about disabling the default Vaadin root servlet registration logic as you proposed?

I originally implemented the root servlet (and the other dynamic servlets) according to the docs here: https://vaadin.com/docs/latest/flow/integrations/spring/spring-mvc . There is an example how to register a root servlet. But as it is documented there it breaks dynamic resources now (before it worked fine). As I understand it, it seems to cause some mapping overlap of /VAADIN.

mrgreywater avatar Jun 10 '22 17:06 mrgreywater

Hi, I was having similar issue after upgrading Vaadin to 23.2.4 and migrated Spring security while trying to display dynamic content on an iFrame, which is caused by ‘x-frame-options’ set to ‘deny’ in Spring.

MoKamal avatar Oct 28 '22 13:10 MoKamal