Actix – 两个冲突的路由

huangapple go评论97阅读模式
英文:

Actix - two conflicting routes

问题

I have two services,

  1. #[put("/{bucket_name}")]
  2. pub async fn create_bucket(
  3. bucket_name: web::Path<String>,
  4. data: web::Data<crate::AppState>,
  5. ) -> Result<HttpResponse, Error> {

and

  1. #[put("/{bucket}/{object_name}")]
  2. pub async fn put_object(
  3. bucket: web::Path<String>,
  4. object_name: web::Path<String>,
  5. data: web::Data<crate::AppState>,
  6. _req: HttpRequest,
  7. mut payload: web::Payload,
  8. ) -> Result<HttpResponse, Error> {

However, the second doesn't work, as it is not found. What can I do to handle both PUT but for different functions?

Currently it produces the following errors:

  1. 2023-05-20T13:12:07.324986Z INFO actix_web::middleware::logger: ::1 "PUT /sardor HTTP/1.1" 409 219 "-" "aws-cli/2.11.20 Python/3.11.3 Darwin/22.5.0 source/arm64 prompt/off command/s3.mb" 0.000900
  2. 2023-05-20T13:12:13.496646Z INFO actix_web::middleware::logger: ::1 "PUT /sardo/5.png HTTP/1.1" 404 40 "-" "aws-cli/2.11.20 Python/3.11.3 Darwin/22.5.0 source/arm64 prompt/off command/s3.cp" 0.000621

Registering services:

  1. let server = HttpServer::new(move || {
  2. App::new()
  3. .wrap(middleware::Logger::default())
  4. .service(apis::put_object::put_object)
  5. .service(apis::create_bucket::create_bucket)
  6. .service(apis::list_buckets::list_buckets)
  7. .default_service(web::route().to(not_found))
  8. .app_data(web::Data::new(AppState {
  9. working_folder: config.working_folder.clone(),
  10. }))
  11. });
英文:

I have two services,

  1. #[put(&quot;/{bucket_name}&quot;)]
  2. pub async fn create_bucket(
  3. bucket_name: web::Path&lt;String&gt;,
  4. data: web::Data&lt;crate::AppState&gt;,
  5. ) -&gt; Result&lt;HttpResponse, Error&gt; {

and

  1. #[put(&quot;/{bucket}/{object_name}&quot;)]
  2. pub async fn put_object(
  3. bucket: web::Path&lt;String&gt;,
  4. object_name: web::Path&lt;String&gt;,
  5. data: web::Data&lt;crate::AppState&gt;,
  6. _req: HttpRequest,
  7. mut payload: web::Payload,
  8. ) -&gt; Result&lt;HttpResponse, Error&gt; {

However, the second doesn't work, as it is not found. What can I do to handle both PUT but for different functions?

Currently it produces the following errors:

  1. 2023-05-20T13:12:07.324986Z INFO actix_web::middleware::logger: ::1 &quot;PUT /sardor HTTP/1.1&quot; 409 219 &quot;-&quot; &quot;aws-cli/2.11.20 Python/3.11.3 Darwin/22.5.0 source/arm64 prompt/off command/s3.mb&quot; 0.000900
  2. 2023-05-20T13:12:13.496646Z INFO actix_web::middleware::logger: ::1 &quot;PUT /sardo/5.png HTTP/1.1&quot; 404 40 &quot;-&quot; &quot;aws-cli/2.11.20 Python/3.11.3 Darwin/22.5.0 source/arm64 prompt/off command/s3.cp&quot; 0.000621

Registering services:

  1. let server = HttpServer::new(move || {
  2. App::new()
  3. .wrap(middleware::Logger::default())
  4. .service(apis::put_object::put_object)
  5. .service(apis::create_bucket::create_bucket)
  6. .service(apis::list_buckets::list_buckets)
  7. .default_service(web::route().to(not_found))
  8. .app_data(web::Data::new(AppState {
  9. working_folder: config.working_folder.clone(),
  10. }))
  11. });

答案1

得分: 1

I have done a different way, created one handler which handles all PUT /{}*, and inside I match them myself.

  1. #[put("/{tail}*")]
  2. pub async fn handle_put(_: web::Path<String>, req: HttpRequest) -> Result<HttpResponse, Error> {
  3. let mut path = Path::new(Url::new(req.uri().clone()));
  4. let mut message = String::new();
  5. let routes = [
  6. ("/{bucket}/{object_name}", "bucket and object"),
  7. ("/{bucket}", "bucket"),
  8. ];
  9. for (pattern, description) in &routes {
  10. if ResourceDef::new(*pattern).capture_match_info(&mut path) {
  11. match (path.get("bucket"), path.get("object_name")) {
  12. (Some(bucket), Some(object_name)) if *description == "bucket and object" => {
  13. message = format!("bucket: {}, object_name: {}", bucket, object_name);
  14. }
  15. (Some(bucket), None) if *description == "bucket" => {
  16. message = format!("bucket: {}", bucket);
  17. }
  18. _ => return Ok(HttpResponse::InternalServerError().finish()),
  19. }
  20. break;
  21. }
  22. }
  23. if message.is_empty() {
  24. Ok(HttpResponse::NotFound().finish())
  25. } else {
  26. Ok(HttpResponse::Ok().body(message))
  27. }
  28. }

(Note: I've removed the HTML encoding from the code snippet for clarity.)

英文:

I have done a different way, created one handler which handles all PUT /{}*, and inside I match them myself.

  1. #[put(&quot;/{tail}*&quot;)]
  2. pub async fn handle_put(_: web::Path&lt;String&gt;, req: HttpRequest) -&gt; Result&lt;HttpResponse, Error&gt; {
  3. let mut path = Path::new(Url::new(req.uri().clone()));
  4. let mut message = String::new();
  5. let routes = [
  6. (&quot;/{bucket}/{object_name}&quot;, &quot;bucket and object&quot;),
  7. (&quot;/{bucket}&quot;, &quot;bucket&quot;),
  8. ];
  9. for (pattern, description) in &amp;routes {
  10. if ResourceDef::new(*pattern).capture_match_info(&amp;mut path) {
  11. match (path.get(&quot;bucket&quot;), path.get(&quot;object_name&quot;)) {
  12. (Some(bucket), Some(object_name)) if *description == &quot;bucket and object&quot; =&gt; {
  13. message = format!(&quot;bucket: {}, object_name: {}&quot;, bucket, object_name);
  14. }
  15. (Some(bucket), None) if *description == &quot;bucket&quot; =&gt; {
  16. message = format!(&quot;bucket: {}&quot;, bucket);
  17. }
  18. _ =&gt; return Ok(HttpResponse::InternalServerError().finish()),
  19. }
  20. break;
  21. }
  22. }
  23. if message.is_empty() {
  24. Ok(HttpResponse::NotFound().finish())
  25. } else {
  26. Ok(HttpResponse::Ok().body(message))
  27. }
  28. }

huangapple
  • 本文由 发表于 2023年5月20日 21:04:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定