Skip to content

Instantly share code, notes, and snippets.

@xerial
Forked from seratch/app.scala
Last active September 3, 2015 07:32
Show Gist options
  • Save xerial/49611e70ccd2f00f2407 to your computer and use it in GitHub Desktop.
Save xerial/49611e70ccd2f00f2407 to your computer and use it in GitHub Desktop.
AutoRouting idea
import skinny.micro._
import skinny.micro.contrib.AutoRouting
// @path("/articles")
class Articles extend WebApp with AutoRouting {
// curl /articles/123?withComments=false
@get @path("/:id")
def show(id: Long, withComments: Option[Boolean]): ActionResult = ???
@get @path("/:articleId/comments")
def showComments(articleId: Long): ActionResult = ???
// curl -XPOST /articles/search -d'keyword=scala'
@post def search(keyword: Option[String]): ActionResult = ???
// curl /articles/analysisResult?yyyymm=201509
@get def analysisResult(
// how to bind this?
yyyymm: Try[(Int, Int)]): ActionResult = ???
/* TODOs:
- @POST or @post (down cased naming looks more Scala-ish)
- distinguish query params and form params?
- convert CamelCase/snake_case style (key name, path name)?
- bind validation rules to each param binder?
*/
}
import xerial.lens.ObjectSchema
class RequestDispatcher {
// Prepare mappings from a path to ObjectSchema of an WebApp class
private val webAppMapping = {
// ObjectSchema contains a list of methods
for(cl <- webAppClasses; schema <- ObjectSchema.of(cl)) yield {
val basePath = m.findAnnotaionOf[path].map(_.value)getOrElse("/" + schema.name)
basePath -> schema
}.toMap[String, ObjectSchema]
}
def handleGet(Request request) = {
val path = request.getPath() // e.g., /articles/123?withComments=false
val appBase = extractAppBase(path) // appBase = "articles"
webAppMapping.get(appBase) match {
case None => reportUnknownAppError(request) /// report error
case Some(webApp) =>
val m = webApp.methods.find( ... ) // TODO Create a look up table ((request path, parameter combination) -> WebApp method)
val methodCallBuilder = new MethodCallBuilder(m, getInstanceOf(webApp))
for((k, v) <- request.getQueryParameters()){ // k1=v1&k2=v2& ...
methodRequstBuilder.set(k, v) // TODO: conversion check. If failed, call parameter binding error handler
}
try {
methodCallBuilder.execute match { // invoke Articles.show
case r:ActionResult => r
case _ => reportError(request)
}
}
catch {
case e:Exception =>
// error report
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment