Closed rockerBOO closed 11 months ago
I think you should be able to do this without any of the internals.
For an example, say you have your index.html
and other static assets in priv/
(this is relatively standard convention). You can get this with erlang.priv_directory
. You can use this to reference your file path:
// don't do this in your request handler
let assert Ok(priv) = erlang.priv_directory("your_app_here")
case request.path_segments(req) {
// I think this should cover the cases for this?
[], ["/index.html"] -> {
let index = string.join(priv, "/index.html")
mist.send_file(index, offset: 0, limit: None)
|> result.map(...)
|> result.lazy_unwrap(...)
}
// other segments
}
The result.map
value is the File
which you can just pass directly to response.set_body
. I guess if you need some data from the file, you might need some other bits from that type. But at least for getting the content type, I don't think it's required.
If the file isn't found (or one of the other errors), the result.lazy_unwrap
case will have the errors. You can use that similarly to the example in the README to return a 404.
Having typed this up, I'm not sure if it was particularly helpful. The mist.send_file
method should handle all of the stuff you need without having to reach into the internals.
I think maybe the confusion was around detecting the index path, particularly where to handle that? You'd likely want to do that up front in your "routing" case statement (as in that example). So you'd have something like:
case request.path_segments(req) {
// this needs to be special cased, since it's different from your normal "static asset" path
[], ["/index.html"] -> serve_index_file(req)
// this could be used to just pass through `file_path` to `mist.send_file` for CSS, JS, HTML, etc
["static", ..file_path] -> serve_static_file(file_path)
// this is just a dumb example for showing more routing stuff
["api", ..api_path] -> api_router(req, api_path)
}
Let me know if you have any other questions, or if I misunderstood what you were trying to achieve here!
Yes, that works great! Thank you! I was trying to do too much in my serve_file and forgot about the router above. This works a lot better and clearer. Your other examples are great ideas as well.
This is what I ended up with but still needs some more work.
import gleam/erlang
import filepath
pub fn main() {
let assert Ok(priv) = erlang.priv_directory("my_app_name")
let assert Ok(_) =
fn(req: Request(Connection)) -> Response(ResponseData) {
case request.path_segments(req) {
["index.html"] -> serve_index_file(req, priv)
[] -> serve_index_file(req, priv)
_ -> "..."
}
}
|> mist.new
|> mist.port(3030)
|> mist.start_http
process.sleep_forever()
}
fn serve_index_file(_req: Request(Connection), priv: String) -> Response(ResponseData) {
let index = filepath.join(priv, "index.html")
mist.send_file(index, offset: 0, limit: None)
|> result.map(fn(file) {
response.new(200)
|> response.prepend_header("content-type", "text/html")
|> response.set_body(file)
})
|> result.lazy_unwrap(fn() {
response.new(404)
|> response.set_body(mist.Bytes(bytes_builder.new()))
})
}
Thank you again!
I was looking to have
/
load up'index.html
but not sure how to achieve it without going into the internals. Also I am sort of new to gleam so I couldn't get this to work properly just yet.Here is my attempt at trying to get "/" to load "index.html" in the
serve_file
from the READMEAdditionally I thought of doing it the gleam way of defining the pattern but couldn't get it working (not sure if it works in gleam?).
Thank you for this library!