如何正确设置此端点?
How can I properly set up this endpoint?
我正在使用 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 上下文处理程序没有让我 return .js 文件的功能。
与 Matt already suggested in a comment 一样,如果您为任一路径添加前缀,它会更清晰。这样,您可以使用 /r/:id
(或 /u/:id
,其中“u”表示“URL”),并且静态文件不会妨碍您,或者您可以在静态文件前加上例如/static/
,或者为了简洁起见,甚至只是 /s/
,您缩短的 URL 不会妨碍您。
但是,如果您更愿意坚持当前的方案,您可以简单地在处理程序中过滤掉 JavaScript 文件(或任何其他 non-id 请求),而是提供文件(但是,如果您以前有 auto-generated 个 ETag,如果您不想自己处理,就会丢失缓存)。
后一种解决方案如下所示:
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 处理程序线程解析资源,理论上,它可以有不同的 class path/class 加载程序比我们目前所在的 class。
请注意,如上所述,这将不支持 client-side 缓存,因为处理程序会简单地忽略随请求 一起发送的所有 ETag
header* 而不是响应 完整的文件 ,在短时间内有很多请求和大型脚本,肯定会给您的磁盘和 CPU 带来更多压力。
因此,我实际上建议为静态文件路由添加前缀,让 Javalin/Jetty 处理所有缓存和文件魔法。
* 其实客户端发送的header大部分时间都是If-None-Match
。服务器将以 ETag
响应以允许在浏览器中进行缓存。
我正在使用 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 上下文处理程序没有让我 return .js 文件的功能。
与 Matt already suggested in a comment 一样,如果您为任一路径添加前缀,它会更清晰。这样,您可以使用 /r/:id
(或 /u/:id
,其中“u”表示“URL”),并且静态文件不会妨碍您,或者您可以在静态文件前加上例如/static/
,或者为了简洁起见,甚至只是 /s/
,您缩短的 URL 不会妨碍您。
但是,如果您更愿意坚持当前的方案,您可以简单地在处理程序中过滤掉 JavaScript 文件(或任何其他 non-id 请求),而是提供文件(但是,如果您以前有 auto-generated 个 ETag,如果您不想自己处理,就会丢失缓存)。
后一种解决方案如下所示:
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 处理程序线程解析资源,理论上,它可以有不同的 class path/class 加载程序比我们目前所在的 class。
请注意,如上所述,这将不支持 client-side 缓存,因为处理程序会简单地忽略随请求 一起发送的所有 ETag
header* 而不是响应 完整的文件 ,在短时间内有很多请求和大型脚本,肯定会给您的磁盘和 CPU 带来更多压力。
因此,我实际上建议为静态文件路由添加前缀,让 Javalin/Jetty 处理所有缓存和文件魔法。
* 其实客户端发送的header大部分时间都是If-None-Match
。服务器将以 ETag
响应以允许在浏览器中进行缓存。