2017-01-05 3 views
0

Ich wollte das wiederverwendbare generische Routing in Scala Akka-HTTP erstellen, so dass ich dasselbe generische Routing für den Rest des Routings verwenden konnte, das ich definierte.Wie kann ich generisches Routing in scala akka-http definieren

Bis jetzt konnte ich Routing als unten definieren, die perfekt funktioniert.

class TestApi(val modules: Configuration with PersistenceService)(implicit executionContext: ExecutionContext) extends BaseApi with CirceSupport { 
    override val oauth2DataHandler = modules.oauth2DataHandler 

    val userDao = new TestService 
    val testApi = pathPrefix("auth") { 
    path("users") { 
     pathEndOrSingleSlash { 
     get { 
      authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { 
      //auth => complete(userService.getAll().map(_.asJson)) 
      auth => complete(userDao.getAll().map(_.asJson)) 
      } 
     } 
     } 
    } ~ 
    path("allUsers") { 
     pathEndOrSingleSlash { 
     post { 
      entity(as[UserEntity1]) { userUpdate => 
      authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { 
       //auth => complete(userService.getAll().map(_.asJson)) 
       auth => complete(userDao.getAll().map(_.asJson)) 
      } 
      } 
     } 
     } 
    } 
    } ~ 
    path("user"/"upload"/"file") { 
     pathEndOrSingleSlash { 
     post { 
      entity(as[Multipart.FormData]) { fileData => 
      authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { 
       auth => { 
       val fileName = UUID.randomUUID().toString 
       val temp = System.getProperty("java.io.tmpdir") 
       val filePath = "/var/www/html" + "/" + fileName 
       complete (
        FileHandler.processFile(filePath,fileData).map { fileSize => 
        ("success", fileSize) 
        //HttpResponse(StatusCodes.OK, entity = s"File successfully uploaded. File size is $fileSize") 
        }.recover { 
        case ex: Exception => ("error", 0) //HttpResponse(StatusCodes.InternalServerError, entity = "Error in file uploading") 
        }.map(_.asJson) 
       ) 
       } 
      } 
      } 
     } 
     } 
    } 
} 

Hier im Code finde ich pathEndOrSingleSlash und

authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) {    
    auth => ... 
} 

repetative.

Ich möchte etwas wie unten, um mit zu arbeiten.

get(url, function) 
post(url, function) 
put(url, function) 

Damit ich den Wiederholungscode wiederverwenden konnte. Wie kann ich das generische Routing wie definiert erreichen?

Antwort

1

Sie können die Anweisungen authenticateOAuth2Async, path und mithilfe der funktionalen Zusammensetzung extrahieren. Sie können eine Funktion höherer Ordnung schreiben, die den „gemeinsamen“ Rahmen bieten wird, und ruft dann eine Funktion, die die besondere Funktionalität bietet:

def commonRoute(p : String, subRoute : AuthInfo[OauthAccount] => Route) = 
    authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { auth => 
    path(p) { 
     pathendOrSingleSlash { 
     subRoute(auth) 
     } 
    } 
    } 

Dies kann dann auf Ihre speziellen Fällen angewendet werden:

//example code doesn't use the auth variable anywhere, thus the "_ =>" 
val getRoute : AuthInfo[OauthAccount] => Route = 
    _ => 
    get { 
     complete(userDao.getAll().map(_.asJson)) 
    } 

val postAllUsersRoute : AuthInfo[OauthAccount] => Route = 
    _ => 
    post { 
     entity(as[UserEntity1]) { userUpdate => 
     complete(userDao.getAll().map(_.asJson) 
     } 
    } 

und dann kombiniert Ihre endgültige Route zu bilden:

val testApi = pathPrefix("auth") { 
    commonRoute("users", getRoute) ~ commonRoute("allUsers", postAllUersRoute) 
} 
+0

Thank you! Es funktioniert perfekt. Aber es funktioniert nicht für Path mit folgender Syntax: "user"/"edit"/IntVal, da Ihr Code String verwendet. Ich habe es mit PathMatcher0 versucht, aber vielleicht ist das nicht nur der Fall. – Sujit

+0

Gern geschehen. Wenn du nicht 'IntVal' brauchst, was ist dann mit' commonRoute (("user"/"edit" /IntVal).toString, ...) '? Wenn Sie das IntVal brauchen, dann müssen Sie den Pfadpart möglicherweise abstrahieren, ähnlich wie ich den authentifizierten Teil abstrahierte ... –

+0

Ich werde versuchen, Sie wissen zu lassen – Sujit

Verwandte Themen