Static file server - handling requests without .html suffix #446
-
What will be the equivalent code in Axum for the below golang code, for requests coming without .html suffix ? I have seen static-file-server example code but could not figure out how to add this functionality. Any sample code for this functionality? Thanks package main
import (
"log"
"net/http"
)
func main() {
log.Println("static server started at :8080")
log.Fatal(http.ListenAndServe(":8080", &App{}))
}
type App struct{}
func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Println(r.URL.Path)
http.FileServer(HTMLDir{http.Dir("./static")}).ServeHTTP(w, r)
}
type HTMLDir struct {
d http.Dir
}
func (d HTMLDir) Open(name string) (http.File, error) {
// Try name as supplied
f, err := d.d.Open(name)
if os.IsNotExist(err) {
// If not found, try with .html
if f, err := d.d.Open(name + ".html"); err == nil {
return f, nil
}
}
return f, err
} |
Beta Was this translation helpful? Give feedback.
Answered by
davidpdrsn
Nov 2, 2021
Replies: 1 comment 13 replies
-
This should do it: use axum::{
body::{box_body, Body, BoxBody},
http::{Request, Response, StatusCode, Uri},
handler::get,
Router,
};
use std::net::SocketAddr;
use tower::ServiceExt;
use tower_http::services::ServeDir;
#[tokio::main]
async fn main() {
let app = Router::new().nest("/static", get(handler))
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn handler(uri: Uri) -> Result<Response<BoxBody>, (StatusCode, String)> {
let res = get_static_file(uri.clone()).await?;
if res.status() == StatusCode::NOT_FOUND {
// try with `.html`
// TODO: handle if the Uri has query parameters
match format!("{}.html", uri).parse() {
Ok(uri_html) => get_static_file(uri_html).await,
Err(_) => Err((StatusCode::INTERNAL_SERVER_ERROR, "Invalid URI".to_string())),
}
} else {
Ok(res)
}
}
async fn get_static_file(uri: Uri) -> Result<Response<BoxBody>, (StatusCode, String)> {
let req = Request::builder().uri(uri).body(Body::empty()).unwrap();
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
match ServeDir::new(".").oneshot(req).await {
Ok(res) => Ok(res.map(box_body)),
Err(err) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", err),
)),
}
} The key is that you can call |
Beta Was this translation helpful? Give feedback.
13 replies
Answer selected by
ekanna
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This should do it: