Background
I need to create a couple of endpoints for an API service project. These API can accept encrypted and un-encrypted one (for development). Both parameters then are passed into a same function. For example:
-
/api/movie/get
with encrypted parameter (for production) -
/dev/movie/get
with un-encrypted parameter (for development)
Current implementation in actix_web
I use actix_web and routes (not macro) to provide path routing. Modified from the sample code below
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
// prefixes all resources and routes attached to it...
web::scope("/app")
// ...so this handles requests for `GET /app/index.html`
.route("/index.html", web::get().to(index)),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
For each API endpoint, I had to create 2 functions, such as:
/// for encrypted one
/// PATH: /api/movie/get
pub async fn handle_get_movie(
app_data: Data<AppState>,
Json(payload): Json<EncryptedPayload>,
) -> Result<impl Responder, Error> {
// decrypt the content
// this is the only difference between un-encrypted and encrypted endpoint
let params = payload
.unload::<GetMovieInf>()
.map_err(|_| MainError::Malformatted)?;
// other codes here....
Ok(Json(ReplyInf {ok: true}))
}
/// for un-encrypted one
/// PATH: /dev/movie/get
pub async fn handle_get_movie(
app_data: Data<AppState>,
Json(payload): Json<UnencryptedPayload>,
) -> Result<impl Responder, Error> {
// other codes here. These codes are exactly identical with the above function...
Ok(Json(ReplyInf {ok: true}))
}
Questions
Since both functions are similar, does it possible to combine them both into a single function ? a function "overload" maybe ?
The problem is this line Json(payload): Json<UnencryptedPayload>
in the parameter function. I tried to use generics like Json<T>
. this doesn't work.
I can use the environment variable to control which should be active (EncryptedPayload
or UnencryptedPayload
). I can use one path for each endpoint (eg: /api/movie/get
) and don't have to write the same functionality twice.