how to load assets,such as .css, .js file, in finatra?

786 views Asked by At

I try return a html file by finatra, the file itself loaded success but all assets can't, contains css, ico and js. Browser response 404:can't load resources.
find the document at bottom of the page:
-com.twitter.finatra.config.assetPath='/public': path to assets

I put public folder under src/main/resources/public, failed also. :-(

my code simple as:

class Login extends Controller {

  get("/signin") { request: Request =>
    val content = Source.fromURL(getClass.getResource("/forwardend/signin.html")).mkString
    response.created.html(content).toFuture
  }
}
3

There are 3 answers

0
LoranceChen On BEST ANSWER

I have solve it with some struggle :)
The way is add a controller to deal with all assets. The code as:

import com.twitter.finagle.http.Request
import com.twitter.finatra.http.Controller

class Resources extends Controller {
  get("/assets/:*") { request: Request =>
    response.ok.file("/public/" + request.params("*"))
  }
}

refer :http://twitter.github.io/finatra/user-guide/files/#file-server
Besides,I try to use below code to change assets path,to make it more pretty,but failed. So I must setting file path with a "/public/" as prefix. If it have a better choice, please point out,thanks.

  System.setProperty("com.twitter.finatra.config.assetPath", "src/main/resources/public")
  System.setProperty("local.doc.root", "src/main/resources/public")  

UPDATE
System.setProperty doesn't work. @Christopher thanks remind me.
A way to setting a Flag("doc.root",...) or Flag("local.doc.root",...) is as follow:
1. define a Module

object AssetsPathConfigModule extends TwitterModule {
  val keyFileDoc = flag("local.doc.root", "./finatra/src/main/scala/com/myfinatra/public", "The key to use.") // file path
  val keyDoc = flag("doc.root", "/com/myfinatra/public/", "class path") // class path

//@Singleton
  @Provides
  def providesThirdPartyFoo: FileResolver = {
    new FileResolver("", keyDoc())
//  or new FileResolver(keyFileDoc(),"")
  }
}

2.add the module to HttpServer's modules seq

class HelloWorldServer extends HttpServer {
  override val modules = Seq(
    ...,
    AssetsPathConfigModule
  )
  ...
}
  1. Resources could be write as

    class Resources extends Controller { get("/assets/:") { request: Request => response.ok.file(request.params("")) } }

0
ThinkBonobo On

The guides were a bit confusing for me. They are very useful when you want to change settings but I wanted to know how to work with default settings using an example.

let's say your file is stored in: '/src/main/resources/public/hello.jpg'

You can load this directly using fileIO with the following

getClass.getClassLoader.getResource("samplecards/bcbs_anonymous.jpg").getPath can be used to return the path of the resource. you can use this information or this code segment accordingly with regular fileIO in scala.

If you're looking to make a finatra response, you can use the following for the example case:

get(GetImage) {
  request: ImageRequest => {
    response.ok.file(s"/public/hello.jpg")
  }
}

The file requires a string and seems to default that string relative to {project_folder}/target/scala-x.xx/classes/ in the project folder which is populated with your static assets from the resources folder in src.

1
Christopher On

"com.twitter.finatra.config.assetPath" is for Finatra v1.x and not Finatra 2.x (the latest) which it looks like you are trying to use.

The latest Finatra user-guide details how to serve files: http://twitter.github.io/finatra/user-guide/files/.

If your files are on the classpath, Finatra will find them and you can load them by the path on the classpath, e.g.,

get("/file") { request: Request =>
  response.ok.file("/file123.txt")
}

If your files are "namespaced" on the classpath, e.g., you put them all under a directory, "/resources" relative to the base classpath you can have Finatra look for them there as well by setting the "-doc.root" flag. This would me you could reference the file as "/file123.txt" rather than "/resources/file123.txt" in your controller (since Finatra knows the directory/namespace).

If you are testing and want to point to files that are somewhere local to your filesystem you can set the "-local.doc.root" flag to the directory containing the assets.