I want to set up a Spray route to serve web content out of a directory.
For example, the below URLs should resolve to the same file.
http://mywebsite.com/path/to/thing
http://mywebsite.com/path/to/thing/
http://mywebsite.com/path/to/thing/index.html
Should serve the index.html file from the filesystem at ./web/path/to/thing/index.html
The following route works if "index.html" is explicitly specified but not otherwise.
pathPrefix("") {
getFromDirectory("./web/")
}
How do i represent this in Spray routing?
Assuming you have already matched up to "thing" with pathPrefix, I think you want pathEndOrSingleSlash, described here. I didn't think that Spray-routing would match an implicit "index.html", but in any case you can compose directives easily if you need to:
(pathEndOrSingleSlash | path("index.html")) { ... }
UPDATE:
OK, from your comment I am thinking that you just want to take whatever path was specified and serve up the file from that directory. Something like this (untested)?
path(Segment) { rawPath =>
getFromFile("web/" + if (rawPath endsWith "/") rawPath + "index.html" else rawPath)
}
Related
I am new to scalajs, I have a finch endpoint in my backend project serving a scalatag html generated from frontend project
val apiEndpoints: Endpoint[Response] = get("index") {
val res = Response()
res.setContentString(scalaTagUI.toString())
Future(res)
}
in my Html I have the script tag
script(attr("type"):="text/javascript", attr("src"):="./target/scala-2.12/classes/assets/frontend-jsdeps.js")
The /index is working but it can't access the javascript files giving 404 - I can see the fastopt.js in my target/scala-2.12.....
The solution at the end was simple - I have added a specific endpoint in finch exclusively for js/css files. Differently if you use something like jetty you would add a folder like "webapp" containing js/css to your server context.
Anyway It works now but I wonder if is there a different maybe cleaner approach.
I have a url
http://localhost:8080/api/search/lookup?limit=3000&m=airid.appname.mapping{appname=*}
path("api"/"search"/"lookup?limit=3000&m=appname.server.mapping") is unavailable
how to match the entire url including parameters and values?
The part of the url after the '?' is referred to as the query string and is technically not part of the path:
a query string is the part of a uniform resource locator (URL)
containing data that does not fit conveniently into a hierarchical
path structure
Therefore, you cannot access it using the path directive. If you want the entire uri then you need extractUri:
val myRoute = extractUri { uri =>
//rest of Route logic
}
I have about 400 url that will change in the new version and for some reasons I can't repeat the same type of url structure in the new website.
My question is, can I give a url list to nginx (yeah I know the 400 ones), and tell him simply that each one of them are going to another url?
Like I said the url structure will be different so I can't use any type of pattern.
Thanks in advance.
The map directive
If you have a very long list of entries, it could be a good idea to keep them outside of the nginx configuration file - using a .map file.
First you need to add a map directive inside your nginx.conf file - keep in mind that your .conf file could be named in another way (e.g. default.conf).
nginx.conf
map_hash_bucket_size 256; # see http://nginx.org/en/docs/hash.html
map $request_uri $new_uri {
include /etc/nginx/oldnew.map; # or any file readable by nginx
}
server {
listen 80;
server_name your_server_name;
if ($new_uri) {
return 301 $new_uri;
}
...
}
Then, the map directive will map any $request_uri to the matching $new_uri found inside the oldnew.map file.
/etc/nginx/oldnew.map:
/my-old-url /my-new-url;
/old.html /new.html;
Be sure to end each line with a ";" char!
Additional configuration
If you need to redirect all URLs to another host, you can use:
return 301 http://example.org$new_uri;
Or, if you also need to redirect to another port, you can use:
return 301 http://example.org:8080$new_uri;
Probably the easiest way to do that is to wrap map directive around your list. The configuration in this case would look like this:
map $request_uri $new_uri {
default "";
/old/page1.html /new/page1.html;
/old/page2.html /new/page2.html;
...
}
server {
...
if ($new_uri != "") {
rewrite ^(.*)$ $new_uri permanent;
}
...
}
Say I have the following url:
/baseurl
I'd like play to match and route on this url. I'd like to satisfy all these patterns:
/baseurl
/baseurl/
/baseurl/*
/baseurl/*/*
So basically I don't care what comes after '/baseurl'. I don't want to explicitly have to pass a variable to my action for the part coming in after '/baseurl' because I don't care about it: I just want it all routed to the same controller (for a single page app). I also am ok if I have to do this with multiple route lines.
I'd put something like this pretty high in the routes file:
GET /baseurl/*path/ controllers.Application.untrail(path: String)
(and the variations thereof)
And then in controllers.Application:
def untrail(path: String) = Action {
MovedPermanently("/baseurl")
}
I have a bunch of routes with the same prefix:
# with prefixes
GET /api/v1.0/action1 controllers.Api.action1
GET /api/v1.0/action2 controllers.Api.action2
GET /api/v1.0/action3 controllers.Api.action3
GET /api/v1.0/action4 controllers.Api.action4
# normal urls
GET /action1 controllers.Home.action1
GET /action2 controllers.Home.action2
I want to get rid of repetition of /api/v1.0/. The urls must remain the same, I just want to not write them manually for each url in route file. In Rails it's possible. If there any way to do that?
Either you implement your own router for these actions following James Ropers' post, as mentioned by Rich. Doing so, allows you add the following to your route file:
-> /api/v1.0 YourPathBindableController
Alternatively you can use a plugin, such as navigator, which offers you advanced routing. Your navigator route file would then contain something like:
// Namespace ...
namespace("api"){
namespace("v1"){
GET on "index" to Application.index _
}
}
// ... or with reverse routing support
val api = new Namespace("api"){
val v2 = new Namespace("v2"){
val about = GET on "about" to Application.about _
}
}