B4J Question [Server] [WebApp] Set custom server root via configuration

b4x-de

Active Member
Licensed User
Longtime User
Hi,

when adding a Handler its path starts always in the server root by using „/“, i.e. srvr.AddHandler("/Configuration/*", "ConfigurationHandler", False). While the Server is running independently everything works fine. I can access it via: http://localhost:12345/Configuration

But I need to set a different root for this server, because in production it is not running independently. (It runs behind a webserver that is rewriting all requests to the jetty server.) Therefore I need to access the WebApp i.e. via http://localhost:12345/prod/app1/Configuration without changing the source code of the app and recompile it. For production use I need to be free to move it to any root if needed.

Is there any configuration setting I can use to set a custom root dir for the jetty server the webapps are based on? How does it work with B4jServer and B4j?

Thanks,
Thomas
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Nothing special. Create a settings file that stores the path prefix and configure it before you run the server.

B4X:
Dim settings As Map = File.ReadMap(File.DirApp, "settings.txt")
Dim prefix As String = settings.Get("prefix")
srvr.AddHandler(prefix & "/Configuration/*", ...

The file should look like this:
B4X:
prefix=prod/app1
 
Upvote 0

b4x-de

Active Member
Licensed User
Longtime User
The solution Erel suggests works for the Hanlder itself. But if the handler serves content that contains links to other resources it does not work properly. Consider the following example of an html form that sends data to a handler. You will find this line in html:

HTML:
<form id="example" method="post" action="/Configuration/Login">
<!-- ... -->
</form>

The action="/Configuration/Login" will cause an error. Because it is not affected by setting the path dynamically with
srvr.AddHandler(prefix & "/Configuration/",...).

Another example is using Mini Template example we are replacing placeholders in a prepared html template. In any case of a reference to other resources like css or javascript files it fails if these files are expected in the root. If you look at this example:

HTML:
<link href="/css/basic.css" rel="stylesheet" type="text/css"/>

I tried to solve the second issue by using the resourceBase-Option for DefaultServlet, following the instructions here:
https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/servlet/DefaultServlet.html

B4X:
Dim strPath As String = "/prod/app1"
Dim opt As Map
opt.Initialize
opt.Put("resourceBase", strPath)

srvr.SetStaticFilesOptions(opt)

But the code does not work.
I’m unable to access static resources from http://localhost:51042/prod/app1

Even if the code would work, the first issue with form action would not be solved.

I’m not sure whether this is a good strategy at all. I would prefer a solution that using the mechanism jetty provides for configuration of a Context Path: https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-contexts

If I could access the setContextPath-Method of the Handler I could set the path for the DefaultServlet-Handler (for serving static content) and of all other Hanlders I created by code. But I can’t figure out how to do this.


Update
Even when setting contextPath and setResourceBase like this, all references inside static html pages (i.e. css, js, form action) still fail:

B4X:
Dim joServer As JavaObject = srvr
joServer.GetFieldJO("context").RunMethodJO("setContextPath", Array("/prod/app1"))
joServer.GetFieldJO("context").RunMethodJO("setResourceBase", Array("/prod/app1"))

Update 2

Finally I tried to use a RewriteHandler to rewrite all traffic to the new root:

B4X:
    Dim joServer As JavaObject = srvr
    Dim joRewriteHandler As JavaObject
    Dim joRewritePatterRule As JavaObject
    
    joRewriteHandler.InitializeNewInstance("org.eclipse.jetty.rewrite.handler.RewriteHandler", Null)
    joRewritePatterRule.InitializeNewInstance("org.eclipse.jetty.rewrite.handler.RedirectPatternRule", Array("/", strPath))
    
    joRewriteHandler.RunMethod("setRewritePathInfo", Array(True))
    joRewriteHandler.RunMethod("setRewriteRequestURI", Array(True))
    joRewriteHandler.RunMethod("addRule", Array(joRewritePatterRule))
    joServer.GetFieldJO("context").RunMethod("setHandler", Array(joRewriteHandler))

But this code does not work. I results in: java.lang.RuntimeException: Method: setRewritePathInfo​​​ not found in: org.eclipse.jetty.rewrite.handler.RewriteHandler But in jetty API you will find setRewritePathInfo(boolean), here: https://www.eclipse.org/jetty/javad...writeHandler.html#setRewritePathInfo(boolean)

The most flexible way would be, if we could add a web.xml configuration file to the Files folder to configure jetty with all the options needed.

Thanks,
Thomas
 
Last edited:
Upvote 0
Top