Kotlin Ktor Static Routing Not Working

OK - I'm an idiot. We know this.

I'm developing a site (I'll write about it later... even though it might be up by the time this is published... DEAL WITH IT) and am using it as an opportunity to learn and use Kotlin!

I've been wanting to use it since it was released.

Could I have anytime in the past many years? YES! ... I did. Thanksgiving 2016. Prototyped an app in Kotlin. OMG it was nice.
I lost the argument to develop the actual app in Kotlin... in the end; worked out much better for me to not - BUT - definitely a nice language.

OK, back to why I'm writing this.

I'm doing a website (as mentioned above) and I like the server code to be microservice focused... In comes KTOR.

Routing is a breeze. Overall, really nice. I see a lot of functionality in Kotlin I'm not using right now. Also not structuring it worth anything.

Note: Overall the code for this is a hack job it's definitely not proper code; let alone proper kotlin.

THE API

I got the api up and running with ease! Ok, I bashed my head a little bit using Exposed as my ORM. That might be another post.

The HTML templates I used had a fav icon loading. Or... well... not loading. I created an API that served up the file.
Clearly this is overkill. A router for files... pfffffft... no.

Of course not. KTOR has a way for Serving Static Content.

routing {
    static("assets") {

    }
}

4slljl

OK...
I was trying to use KTOR's static routing and getting back a 404 error. SIGH.... time to fight my tool and not be productive... I hate fighting my tools.

I spent 12 hours beating my head and trying variation after variation of how to configure static.

This was a glorious series of ideas where I'd run out of things to try... head up stairs... get a new idea... head back to the computer. Only did that 3 times. My best... is 6.

Anyway... trying lots of stuff... finally gave up trying to figure it out with my code.

MVE

Minimum Viable Example. I needed the simplest routing that works that I could see WTF I was missing.

There's a lot of stuff it could have been; gradle, components, versions, me, my code, my existing routing... SO MUCH... so... MVE time.

KTOR has a plugin to generate all the boiler plate for the features you want. And sets it up for you. SO NICE.

I used just the routing option. As basic as I could make it.

It works. So... same ... everything, as I'm doing. Pretty sure. My gradle file is right; excellent.

I'm poking at the code and the pathing...

// Static feature. Try to access `/static/ktor_logo.svg`
static("/static") {
    resources("static")
}

and the relevant folders
folders

OK...

This was a couple days ago; so I don't remember EXACTLY what kicked me in the head and got my thinking on straight... I think it was the variable name.
static("/static") the string there, it's a param, with a name. It's called remotePath.

All of my previous efforts were assuming the value passed into static was related to the path on disk.

Nope.
Nuh-uh.
Wrong.
tenor

OK... So; most of the reason why I'm writing this post is that I didn't get it.
I hope no one else has this problem - but I also hope that I can help if you do.

SO! The value passed into static is the REMOTE PATH. Ya know... the browser path.

I think the documentation is lacking examples around the remote and local pathing... or it didn't make sense originally... That happens a lot.

If the MVE didn't work; I was going to build my own version to fill in the missing understanding so I could use the provided one.

So; let's get into some examples of pathing.

Let's have a folder structure that looks something like

- root
- - resources
- - - static
- - - - ktor_logo.svg

and you want your browser to be domain/static/ktor_logo.svg what you... hehe. No.

I don't want my browser path to match the folder path. That's the entire reason I got screwed up.

I want to be obscure; so I want my browser path to be doamin/NotTheFolderPath/ktor_logo.svg.
I'll set up static like

static("/NotTheFolderPath") {
    resources("static")
}

And that's the bit I was missing.

Still Doing It Wrong

I'm still not doing it the best... But I'm hacking things together. Right now "works" is my goal. Once I get my understanding to a level I'm good with, I'll start restructuring things and finding optimizations. Looking specifically for built in ways to optimize and clean up stuff.

Here's my current static

static{
    staticRootFolder = File("html")
    static("js"){
        files("js")
    }
    static("css"){
        files("css")
    }
    static("img"){
        files("img")
    }
    static("fonts"){
        files("fonts")
    }

    file("favicon.ico", "favicon.ico")

    //User Stuff
    file("register", "register.html")
    file("signin", "signin.html")
    file("profile", "profile.html")

    //card
    file("singleSet", "singleSet.html")
    file("collection/set", "userCardSet.html")
    file("collection/parentSet", "userCardParentSet.html")

    //sets
    file("collection/sets", "userSets.html")
}

I don't like all specific files coded in there; but it works for now since I don't want to care about path and file names matching.

I'd like a way to mapp the js, css, blah folders all at once as siblings... or just a "map these strings to same named folders" something like

static.same("js", "css", "img", "fonts")

It might exist; haven't dug into it yet.

Anyway... that's all I got on this.

Show Comments