使用弹簧启动与vaadin时的js文件404 [英] 404 for js files when using spring boot with vaadin

查看:214
本文介绍了使用弹簧启动与vaadin时的js文件404的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用spring-boot的vaadin项目中使用spring security时遇到问题。所以我使用PdfViewer Addon来显示PDF文件。但我收到以下错误消息:

 错误:未找到
消息:没有可用消息
路径:/ APP / PUBLISHED / pdf.worker.js
状态:404

,我的spring安全配置如下所示:

  @Override 
protected void configure(HttpSecurity http抛出异常{
http
.headers()
.defaultsDisabled()
.frameOptions()。sameOrigin()。和()
.csrf()。 disable()//使用Vaadin的CSRF保护
.authorizeRequests()。antMatchers(/)。permitAll()
.antMatchers(/ vaadinServlet / HEARTBEAT / **)。permitAll()
.antMatchers(/ vaadinServlet / UIDL / **)。permitAll()
.antMatchers(/ vaadinServlet / APP / PUBLISHED / **)。permitAll()
.antMatchers( login?debug)。permitAll()
.antMatchers(/ #!pwdreset / *)。permitAll()
.antMatchers(/ pwdreset / *)。permitAll()
.and()
.authorizeRequests()
。和()
.formLogin()。loginPage(/#!login)。permitAll()
.and()
.logout()。logoutUrl(/#!login? logout)。logoutSuccessUrl(/)。permitAll()。和()
.sessionManagement()。sessionFixation()。newSession();

}

@Override
public void configure(WebSecurity web)抛出异常{
web.ignoring()。antMatchers(/ resources / * *,/ VAADIN / **);
}

因此,检查Chrome中加载的文件我看到一个文件夹 / vaadinServlet / APP / PUBLISHED / 并且还有所有需要的文件。



使用没有Spring Security的Addon工作正常,所以任何人都不知道?






更新



似乎不合适与spring spring相关,因为我在一个新的简单项目中测试Addon时会遇到类似的行为。弹簧启动似乎有问题。



要重现此问题,您需要(



失败的调用的 Initiator 列实际上是



在常规的Vaadin环境中, /APP/PUBLISHED/pdf.worker.js 可以开箱即用,但我们现在处于稍微改变的状态所以我们需要一些调整。最重要的是,我们可以使用与Vaadin自动配置相似的方法,并将 /APP/PUBLISHED/pdf.worker.js 请求重定向到 /vaadinServlet/APP/PUBLISHED/pdf.worker.js 并最终解决了这个问题。为简洁起见,可以在本文开头看到重定向控制器。




I have a problem when using spring security in a vaadin project with spring-boot. So I'am using a PdfViewer Addon to display PDF Files. But I'm getting the following error message:

error:"Not Found"
message:"No message available"
path:"/APP/PUBLISHED/pdf.worker.js"
status:404

and my spring security configuration looks like this:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .defaultsDisabled()
                .frameOptions().sameOrigin().and()
                .csrf().disable() // Use Vaadin's CSRF protection
                .authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
                .antMatchers("/vaadinServlet/UIDL/**").permitAll()
                .antMatchers("/vaadinServlet/APP/PUBLISHED/**").permitAll()
                .antMatchers("login?debug").permitAll()
                .antMatchers("/#!pwdreset/*").permitAll()
                .antMatchers("/pwdreset/*").permitAll()
                .and()
                .authorizeRequests()
                .and()
                .formLogin().loginPage("/#!login").permitAll()
                .and()
                .logout().logoutUrl("/#!login?logout").logoutSuccessUrl("/").permitAll().and()
                .sessionManagement().sessionFixation().newSession();

    }

@Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**", "/VAADIN/**");
    }

So checking the loaded files in Chrome I see a folder /vaadinServlet/APP/PUBLISHED/ and there are all the files needed.

Using the Addon without Spring Security works fine, so anyone any idea?


Update

It doesn't seem to be related to spring security, because I get a similar behavior while testing the Addon in a new simple project. It seems to be a problem with spring boot.

To reproduce this issue you need (full project for download):

  • basic spring boot + vaadin app skeleton
  • simple PDF and under /webapp/files
  • PdfViewer add-on in your pom and widgetset compiled
  • the below simple UI

@Theme("mytheme")
@SpringUI
@Widgetset("org.test.AppWidgetSet")
public class MyUI extends UI {
    @Override
    protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();
        String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
        File file = new File(basepath.concat("/files/test.pdf"));
        if (file.exists()) {
            PdfViewer pdfViewer = new PdfViewer(file);
            Label info = new Label("File was found!");
            layout.addComponents(info, pdfViewer);
        } else {
            Label info = new Label("no file found!");
            layout.addComponent(info);
        }
        setContent(layout);
    }
}

  • open chrome & developer tools with the Network tab selected, access the app and you should see one request for pdf.worker.js fail.

解决方案

TL;DR; version:

A second request is being triggered by pdf.js to download pdf.worker.js, but it does not match the path /vaadinServlet/APP/PUBLISHED/pdf.worker.js handled by the auto-configured VaadinServlet, it's just /APP/PUBLISHED/pdf.worker.js.

The simplest solution I could come up with, is a controller which forwards the request to the VaadinServlet:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PdfJsRedirectController {
    private static final String WORKER_JS_INCORRECT_PATH = "/APP/PUBLISHED/pdf.worker.js";
    private static final String WORKER_JS_CORRECT_FORWARD_PATH = "forward:/vaadinServlet/APP/PUBLISHED/pdf.worker.js";

    @RequestMapping(value = WORKER_JS_INCORRECT_PATH)
    public String forwardWorkerJsRequestToVaadin() {
        return WORKER_JS_CORRECT_FORWARD_PATH;
    }
}


Detailed version:

So, I've spent some time debugging this, and it turns out to be a combination of unfortunate configs:

  • spring dispatcher servlet listening
  • vaadin spring servlet listening
  • a pdf.js bugfix/woraround

What happens is, spring registers a DispatcherServlet serving requests for /*. and Vaadin registers a VaadinSpringServlet for the /vaadinServlet/* & /VAADIN paths:

ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
ServletRegistrationBean  : Mapping servlet: 'springVaadinServlet' to [/vaadinServlet/*, /VAADIN/*]

To co-exist with the dispatcher servlet and be able to serve requests also on "/*", Vaadin also registers a forwarding-controller for the UI paths. For example requests on /MyUI will be forwarded to /vaadinServlet/MyUI (see the VaadinServletConfiguration sources for more details).

Until now everything works fine and you should not have any issues. Just like you said, looking at the chrome dev-tools all the js files are there, so what's wrong? If you look closley at the requests made when you access your app, you'll notice that actually there are 2 requests for pdf.worker.js - the first one that is successful, and the one which gives you the 404:

The Initiator column for the the call that fails, is actually pdf.js:2344 and if you set a breakpoint you can actually see that workerSrc=/APP/PUBLISHED/pdf.worker.js, value which is defined in pl.pdfviewer.client.ui.PdfViewer.java. You may have to scroll horizontally a bit to be able to see the code, so I've formatted it below:

public native void loadResourcePdf(String fileName, VPdfViewer instance)/*-{
    var pdfviewer = instance.@pl.pdfviewer.client.ui.VPdfViewer::jsObject;
    pdfviewer.work = false;
    if ((pdfviewer.fileName == null || pdfviewer.fileName != fileName) && fileName != null) {
        $wnd.PDFJS.disableStream = true;
======> $wnd.PDFJS.workerSrc = 'APP/PUBLISHED/pdf.worker.js';
        $wnd.PDFJS.getDocument(fileName).then(function (pdf) {
            pdfviewer.pdfFile = pdf;
            pdfviewer.fileName = fileName;
            pdfviewer.pageCount = pdf.numPages;
            if (pdfviewer.pageNumber == 0 && pdf.numPages > 0) {
                pdfviewer.pageNumber = 1;
            }
            pdfviewer.showPdfPage(pdfviewer.pageNumber);
        });
    }

}-*/;

In a regular Vaadin environment, /APP/PUBLISHED/pdf.worker.js would work out of the box, but we're now in a slightly altered one so we need some adjustments. Bottom line, we can use a similar approach to what Vaadin auto-configuration is doing, and redirect the /APP/PUBLISHED/pdf.worker.js request to /vaadinServlet/APP/PUBLISHED/pdf.worker.js and finally overcome the issue. For the sake of brevity, the redirect controller can be seen at the beginning of this post.

这篇关于使用弹簧启动与vaadin时的js文件404的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆