【问题标题】:How can I properly set up this endpoint?如何正确设置此端点?
【发布时间】:2021-07-11 07:31:07
【问题描述】:

我正在使用 Javalin 框架制作 URL 缩短器并设置此端点:

app.routes(()->{
            path("",()->{
                get("/:id", ctx->{
                   //do stuff
                   ctx.redirect("somewhere.com");
                });
            });
        });

问题是我需要提供一个 javascript 文件以加载到我的 html 文件中。它尝试从 http://localhost:7000/qrcode.min.js 加载,但最终到达上述端点。从我在文档中读到的内容来看,这是正常行为,Javalin 首先运行端点处理程序,然后(如果它没有找到端点)运行文件处理程序。

那么我该如何解决这个问题?我应该在“/qrcode.min.js”处定义 GET 请求吗?我认为 javalin 上下文处理程序没有让我返回 .js 文件的函数。

【问题讨论】:

  • 是否可以选择将重定向 URL 移动到像 /r/:id 这样的专用路径,这比找到一些解决方法要干净得多。

标签: java spring javalin


【解决方案1】:

作为Matt already suggested in a comment,如果您为任一路径添加前缀,将会更加简洁。这样,您可以使用/r/:id(或/u/:id,使用“u”表示“URL”)并且静态文件不会妨碍您,或者您可以在静态文件前面加上例如/static/,或者为了简洁起见甚至只是 /s/,您的缩短网址不会妨碍您。

但是,如果您更喜欢使用当前的方案,您可以简单地在处理程序中过滤掉 JavaScript 文件(或任何其他非 ID 请求)并提供文件(但是,如果您之前有自动生成的ETags,如果你不想自己处理,你会丢失缓存)。

后一种解决方案如下所示:

app.routes (() -> {
    path ("", () -> {
        get ("/:id", ctx -> {
            String id = ctx.pathParam ("id");
            if (id.endsWith (".js")) {
                String resourcePath = "your/classpath/resources/folder/" + id;
                try {
                    InputStream resultStream = Thread.currentThread ()
                                                 .getContextClassLoader ()
                                                 .getResourceAsStream (resourcePath);

                    if (resultStream == null)
                        throw new NullPointerException ("Script not found");

                    ctx.contentType ("application/javascript");
                    ctx.result (resultStream);
                } catch (NullPointerException e) { // script does not exist
                    e.printStackTrace (); // for development only!
                    ctx.status (404);
                }

                return;
            }
            // do stuff
            ctx.redirect ("somewhere.com");
        });
    });
});

根据您的喜好,您还可以处理 resultStream == null 的情况,我的代码当前正在抛出 NPE 以被外部 try/catch 捕获并完全省略 try/catch。

设置Content-Type 是必不可少的,这样浏览器才能知道您实际上是在使用 JavaScript 代码进行响应。另外,我通常使用Thread.currentThread ().getContextClassLoader (),因为我们希望根据当前的 HTTP 处理程序线程解析资源,理论上,它可能具有与我们当前所在的类不同的类路径/类加载器.

请注意,如上所述,这将不支持客户端缓存,因为处理程序只是忽略随请求发送的所有 ETag 标头* 而是以完整的响应文件,在短时间内有很多请求和大型脚本,肯定会给你的磁盘和 CPU 带来更大的压力。

因此,我实际上建议为静态文件路由添加前缀,让 Javalin/Jetty 处理所有缓存和文件魔术。


* 其实客户端发送的header大部分时间都是If-None-Match。服务器将响应 ETag 以允许在浏览器中进行缓存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    相关资源
    最近更新 更多