Serve favicon.ico and other static files with VertX - kotlin

I'm trying to serve a favicon and some fonts.
object Lion : AbstractVerticle() {
#JvmStatic
#Throws(IOException::class)
fun main(args: Array<String>) {
val vertx = Vertx.vertx()
val router = Router.router(vertx)
router.route().handler(CorsHandler.create("*")
.allowedMethod(HttpMethod.GET)
.allowedMethod(HttpMethod.POST)
.allowedMethod(HttpMethod.OPTIONS)
.allowedHeader("X-PINGARUNER")
.allowedHeader("Content-Type"))
// some json GET / POST routes here
router.route().handler(FaviconHandler.create());
router.route().handler(StaticHandler.create())
vertx.createHttpServer().requestHandler { router.accept(it) }.listen(9090)
}
The FaviconHandler throws an exception causing an "Internal Server Error" when I go to http://localhost:9090/favicon.ico
My favicon is located in src/main/resources/webroot/favicon.ico
Oct 22, 2016 11:16:42 PM io.vertx.ext.web.impl.RoutingContextImplBase
SEVERE: Unexpected exception in route
java.lang.RuntimeException: java.lang.NullPointerException
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.init(FaviconHandlerImpl.java:148)
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.handle(FaviconHandlerImpl.java:155)
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.handle(FaviconHandlerImpl.java:33)
at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:215)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
at io.vertx.ext.web.handler.impl.CorsHandlerImpl.handle(CorsHandlerImpl.java:121)
at io.vertx.ext.web.handler.impl.CorsHandlerImpl.handle(CorsHandlerImpl.java:38)
at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:215)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
at io.vertx.ext.web.impl.RouterImpl.accept(RouterImpl.java:79)
at Lion$main$8.handle(Lion.kt:90)
at Lion$main$8.handle(Lion.kt:43)
at io.vertx.core.http.impl.ServerConnection.handleRequest(ServerConnection.java:286)
at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:412)
at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:139)
at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.lambda$createConnAndHandle$1(HttpServerImpl.java:712)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:314)
at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:190)
at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.createConnAndHandle(HttpServerImpl.java:706)
at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:570)
at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:522)
at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:76)
at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:122)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350)
at io.vertx.core.http.impl.HttpServerImpl$Http1xOrHttp2Handler.http1(HttpServerImpl.java:1019)
at io.vertx.core.http.impl.HttpServerImpl$Http1xOrHttp2Handler.channelRead(HttpServerImpl.java:990)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:129)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:610)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:551)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:465)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:437)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl$Icon.<init>(FaviconHandlerImpl.java:61)
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl$Icon.<init>(FaviconHandlerImpl.java:40)
at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.init(FaviconHandlerImpl.java:143)
... 48 more
Removing the FaviconHandler and normal html, js and css files are serving fine, but fonts are failing to serve.
Failed to decode downloaded font: http://localhost:9090/fonts/glyphicons-halflings-regular.woff
/#/tcr:1 OTS parsing error: incorrect file size in WOFF header
When I go directly to that font-url, the browser is trying to download the font as a regular file.
This seems like a potential solution, but I'm seeing something that is not my favicon, just a 16x16 square with distorted lines in it, the fonts are still trying to download and still giving the error in the browser console.
router.route("/favicon.ico").handler {
it.response().putHeader("Content-Type", "image/x-icon").sendFile("webroot/favicon.ico")
}
router.route("/fonts/glyphicons-halflings-regular.woff").handler {
it.response().putHeader("Content-Type", "application/font-woff").sendFile("webroot/fonts/glyphicons-halflings-regular.woff")
}
So to sum up, how do I make the StaticHandler serve .woff and .ico files correctly with the correct MimeTypes and not have it download those files?
Solution:
First problem I had was that maven shade wasn't copying all the font files into jar for some reason.
Explicitly copying the font files on build and disabling resource filtering for fonts seems to have fixed the font issue.
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>${basedir}/src/main/resources/fonts</directory>
<filtering>false</filtering>
</resource>
</resources>
Then serving the fonts from the resource directory instead of the font directory fixed it (VertX just wouldn't serve from the font directory for some reason even though the files are there)
router.route("/fonts/glyphicons-halflings-regular.woff2").handler {
it.response().sendFile("glyphicons-halflings-regular.woff2")
}
router.route("/fonts/glyphicons-halflings-regular.woff").handler {
it.response().sendFile("glyphicons-halflings-regular.woff")
}
router.route("/fonts/glyphicons-halflings-regular.ttf").handler {
it.response().sendFile("glyphicons-halflings-regular.ttf")
}
router.route().handler(StaticHandler.create().setCachingEnabled(true));
Favicon is probably being cached, still investigating, favicon is not that critical to fix at the moment.
router.route("/favicon.ico").handler(FaviconHandler.create("favicon.ico"))

Favicon.ico:
Simply move your favicon.ico file up a level into the resources folder directly:
/src/main/resources/favicon.ico
Alternatively change your FaviconHandler to pass in the path and filename:
router.route().handler(FaviconHandler.create(FaviconHandler.create("webroot/favicon.ico")))
Your code assumes that FaviconHandler also respects the webroot set in StaticHandler but it does not. That is purely a property of StaticHandler and therefore FaviconHandler looks for the resource in resources/ unless you specify a relative path. When that resource isn't found, it uses the result of getResourceAsStream("favicon.ico") which is null and crashes.
If you look at the unit test for the FaviconHandlerImpl you will see that they place the favicon.ico file in the root of resources instead of webroot.
WOFF Files:
As for your font files you are looking in the wrong place for the problem. It has nothing to do with MIME types.
More likely is that you corrupted the WOFF files on accident. This could have happened when you committed them with GIT and it thought they were text files and it broke the line endings thereby corrupting them. Or you used Maven Filter plugin and it did the same, corrupting them. Or you uploaded/downloaded them via FTP as text files, same problem.
See other posts about this: https://stackoverflow.com/a/33792610/3679676

You don't specify your favicon path, so Vertx tries to locate the default one:
if (path == null) {
icon = new Icon(Utils.readResourceToBuffer("favicon.ico"));
}
Your favicon is located at resources/webroot/favicon.ico, but Vertx looks for it at resources/favicon.ico
So you can either specify FaviconHandler.create("webroot/favicon.ico") or move it one directory up.
Regarding WOFF files, I was unable to reproduce the problem, as WOFF returns with application/x-font-woff, which seems correct.

Related

node red cannot GET /myfile from directory

I would like to ask.
I have file in C:\users\nxf68958\.Node-red\report.html
And when I would like to open this file by: localhost:1880/report.html
I get:
Cannot GET /report.html
in Log I have: "Nov 09:52:00 - [info] User directory : \Users\nxf68958\.node-red"
I am using:
NR: 3.0.2
Node: 18.12.0
It worked perfectly on older versions of: NR: 2.2 and Node: 16.13.
Then I actualized and it stopped working.
In settings.js is option: "fileWorkingDirectory" I tried to change it, but without change.
What I am doing wrong?
Thank you
Node-RED will not serve static files by default, you have to explicitly enable it by settings the httpStatic option in the settings.js file.
Settings the httpStatic value to point to the userDir (which is what you have basically done by setting it to __dirname) is a bad idea from a security point of view because this means anybody can download your flows.json and flows_creds.json files and the files like settings.js and .config.runtime.json (which holds the default encryption key for the creds file).
fileWorkDirectory is purely to set the default working directory for the code nodes that interact with the filesystem, it will have no effect on what files are served by the HTTP server.

Relative and absolute path problems in .net core app when published

I have got this problem with a program when I publish it to the server, the problem arises because it is published to a folder on the server rather than the root.
In the pages there are bits of code like this in the .cshtml files
#section head {
<link rel="stylesheet" href="/css/login.scss" />
}
If I publish this it interprets it as the file being at www.website.com/css/login.scss instead of www.website.com/folder/css/login.scss
I tried to use ~ infront of the link but that causes the whole program to crash with an Error 500, logging says this:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HM3MGHFA29RH", Request id "0HM3MGHFA29RH:00000001": An unhandled exception was thrown by the application.
System.IO.FileNotFoundException: No files found matching "/folder/css/login.scss" exist in "C:\inetpub\wwwroot\website\folder\wwwroot\"
Adding the ~ makes the program think the file is in the wrong location, I don't know how to resolve this without publishing the project to a root of a website which I want to avoid. I've tried all kinds of methods but am getting nowhere.

F4 IDE gives "Invalid Uri scheme for local file" when running Fantom app

I started a very simple project using Xored's F4 IDE for Fantom. The first few times I ran it there was no error, but I started adding dependencies (fanbatis) and at some point the error below starting showing up every time I run a test or a dummy Hello World app.
[23:44:18 22-Nov-13] [err] [pathenv] Cannot parse path: C:\dev\f4workspace\auth\bin\fan
sys::ArgErr: Invalid Uri scheme for local file: c:\dev\f4workspace\auth\bin\fan/
fan.sys.LocalFile.uriToFile (LocalFile.java:64)
fan.sys.File.make (File.java:26)
util::PathEnv.parsePath (PathEnv.fan:47)
fan.sys.List.each (List.java:555)
util::PathEnv.parsePath (PathEnv.fan:43)
util::PathEnv.make$ (PathEnv.fan:22)
util::PathEnv.make (PathEnv.fan:20)
java.lang.reflect.Method.invoke (Unknown)
fan.sys.Method.invoke (Method.java:559)
fan.sys.Method$MethodFunc.callList (Method.java:198)
fan.sys.Type.make (Type.java:246)
fan.sys.ClassType.make (ClassType.java:110)
fan.sys.Type.make (Type.java:236)
fan.sys.Sys.initEnv (Sys.java:447)
fan.sys.Sys. (Sys.java:224)
fanx.tools.Fan.execute (Fan.java:28)
fanx.tools.Fan.run (Fan.java:298)
fanx.tools.Fan.main (Fan.java:336)
Hello, World!
It is more a nuisance at the moment because the tests and the dummy app still run. I created another project, copying all the source code adding class by class and testing after each change and the error never occurred. Any ideas please?
That's an interesting issue!
tl/dr: you have an empty project 'auth' in your workspace, either create some dummy class inside it or go to Run -> Run configurations, find your launch config and uncheck project without sources on 'Projects' tab.
In order to keep your Fantom installation clean from projects in a workspace, F4 puts built pods into project/bin/fan/lib/fan. When F4 launches projects from workspace, it uses PathEnv and builds FAN_ENV_PATH by joining paths to Fantom installation and bin/ folders in projects in workspace.
When Fantom runtime analyzes FAN_ENV_PATH, at first it interprets a path as native OS path, but if dir does not exist, it attempts to interpret it as file URI, here's relevant part of PathEnv source:
path.split(File.pathSep[0]).each |item|
{
if (item.isEmpty) return
dir := File.os(item).normalize
if (!dir.exists) dir = File(item.toUri.plusSlash, false).normalize
if (!dir.exists) { log.warn("Dir not found: $dir"); return }
The problem code is item.toUri – On Mac OS X and Linux this is parsed as an URI without scheme with path only, so if directory does not exist, this code just prints a warning in a console.
But on Windows, because of disk name in path, disk name is interpreted as scheme:
fansh> "C:\\Users".toUri { echo(path); echo(scheme) }
[\Users]
c
fansh> "/Users".toUri { echo(path); echo(scheme) }
[Users]
null
And then File constructor fails, because expects either 'file' scheme, or null scheme:
public static java.io.File uriToFile(Uri uri)
{
if (uri.scheme() != null && !uri.scheme().equals("file"))
throw ArgErr.make("Invalid Uri scheme for local file: " + uri);
return new java.io.File(uriToPath(uri));
}
I've created an issue here, so that F4 would automatically skip empty projects when building FAN_ENV_PATH – https://github.com/xored/f4/issues/25.
I thought the problem had something to do with the forward slash at the end of path as shown in this line of the error message
Invalid Uri scheme for local file: c:\dev\f4workspace\auth\bin\fan/
However, I found that such path didn't exist. I manually created both the bin and the fan folders and the error disappeared. To be honest I don't really know why F4 needs and checks for that folder because so far it hasn't written any file in it.

open_basedir restriction when parsing LESS files

I got a warning when parsing my "Twitter BootStrap" files and saving them on disk in my less-cache folder.
Warning: is_file(): open_basedir restriction in effect. File(/../../lib/bootstrap/less/reset.less.less) is not within the allowed path(s): (/var/www/vhosts/example.com/:/tmp/) in /var/www/vhosts/example.com/httpdocs/wp-content/modules/wp-less/lessc/lessc.inc.php on line 80
I'm using (for example) #import "../../lib/bootstrap/less/reset.less"; in the main file that I'm parsing.
The funky thing is, that the first stylesheet gets the extension two times: reset.less.less - the other ones not. Another thing that keeps me wondering, is why the heck there's a leading / in front of the files.
Some data about the environment and server:
PHP 5.3.3
Wordpress 3.4.2
The WP-LESS Plugin (yes, I commit to this repo), which uses the LESSc library - which throws the error from here.
php.ini
include_path = ".:..:"
upload_temp_dir _no value/not set_
open_basedir = "/var/www/vhosts/example.com/:/tmp/"
Thanks for any help in advance!

What are possible causes for differing behaviors in jsFiddle and in local context

Upon invsetigating 'mu is too short's answer to this question, I noticed that I get different behaviour in jsFiddle than in my local context for the exact same script. Any clues as to why that is?
Note:
I am not getting any javascript errors in Firefox's error console in the local context.
UPDATE:
I tried grabbing the HTML from fiddle.jshell.net/ambiguous/ZEx6M/1/show/light to a local file and loading that local file in Chromium browser and I got the following errors in the javascript console:
GET file:///css/normalize.css undefined (undefined) /css/normalize.css
GET file:///css/result-light.css undefined (undefined) /css/result-light.css
Resource interpreted as Script but transferred with MIME type application/empty jquery.scrollTo-1.4.2.js:-1
Resource interpreted as Script but transferred with MIME type text/plain jquery.viewport.js:-1
I can get rid of these javascript errors by downloading the files and modifying the <script> tags, but it doesn't solve the problem. The page still scrolls down to the very bottom. Also these errors appear even in the working (jsFiddle) version.
I also tried the same process in Konqueror. Result: the script does absolutely nothing.
Don't use separate files for CSS and javascript. Just bring everything into HTML file (using inline javascript and inline CSS) and you should be OK.
Or, run a web server locally to serve the javascript file (with the correct MIME type) and use relative paths to CSS.