Skip to content

Instantly share code, notes, and snippets.

@hamnis
Last active December 15, 2015 23:59
Show Gist options
  • Save hamnis/5344262 to your computer and use it in GitHub Desktop.
Save hamnis/5344262 to your computer and use it in GitHub Desktop.
package ems
import javax.servlet.http.HttpServletRequest
import org.joda.time.DateTime
import unfiltered.directives._
import Directives._
import unfiltered.request._
import unfiltered.response._
import unfilteredx._
trait EmsDirectives {
def baseURIBuilder = request[HttpServletRequest].map(r => BaseURIBuilder(r))
def requestURIBuilder = request[Any].map(r => RequestURIBuilder(r))
def requestURI = request[Any].map(r => RequestURI(r))
def ifModifiedSince(dt: DateTime) = when {
case IfModifiedSince(date) if (dt.withMillisOfSecond(0).toDate == date) => ()
}
def ifUnmodifiedSince(dt: DateTime) = when{
case IfUnmodifiedSinceString("*") => ()
case IfUnmodifiedSince(date) if (dt.withMillisOfSecond(0).toDate == date) => ()
}.orElse(PreconditionRequired ~> ResponseString("You must include a 'If-Unmodified-Since' header in your request"))
def contentType(ct: String) = when {
case RequestContentType(`ct`) => ()
}.orElse(UnsupportedMediaType)
}
[error] /Users/maedhros/Projects/git/javabin/ems/server/src/main/scala/ems/ResourceHelper2.scala:58: type mismatch;
[error] found : Unit => unfiltered.directives.Directive[Nothing,Nothing,unfiltered.response.ResponseFunction[Any]]
[error] required: Unit => unfiltered.directives.Directive[TT,RR,unfiltered.response.ResponseFunction[Any]]
[error] _ <- contentType(CollectionJsonResponse.contentType)
package ems
import model.Entity
import security.User
import storage.MongoDBStorage
import unfiltered.response._
import unfiltered.request._
import unfilteredx._
import net.hamnaberg.json.collection._
import unfiltered.directives._
import Directives._
trait ResourceHelper2 extends EmsDirectives {
def storage: MongoDBStorage
private [ems] def handleObject[T <: Entity[T]](obj: Option[T],
fromTemplate: (Template) => T,
saveEntity: (T) => Either[Exception, T],
toItem: (T) => Item)(enrich: JsonCollection => JsonCollection = identity)(implicit user: User) = {
val resp = (i: T) => DateResponseHeader("Last-Modified", i.lastModified.getMillis) ~> CollectionJsonResponse(enrich(JsonCollection(toItem(i))))
val get = for {
_ <- GET
a <- getOrElse(obj, NotFound)
_ <- ifModifiedSince(a.lastModified).orElse(resp(a))
} yield NotModified
val put = for {
_ <- PUT
_ <- authenticated(user)
_ <- contentType(CollectionJsonResponse.contentType)
a <- getOrElse(obj, NotFound)
_ <- ifUnmodifiedSince(a.lastModified)
} yield saveFromTemplate(fromTemplate, saveEntity)
get | put
}
private def saveFromTemplate[T <: Entity[T]](fromTemplate: (Template) => T, saveEntity: (T) => Either[Exception, T]) = {
withTemplate {
t => {
val e = fromTemplate(t)
saveEntity(e).fold(
ex => InternalServerError ~> ResponseString(ex.getMessage),
_ => NoContent
)
}
}
}
private [ems] def withTemplate(f: (Template) => ResponseFunction[Any]) = {
for {
href <- requestURI
_ <- contentType(CollectionJsonResponse.contentType)
template <- inputStream.map(is => NativeJsonCollectionParser.parseTemplate(is))
} yield {
template.fold(
e => BadRequest ~>
CollectionJsonResponse(
JsonCollection(
href,
Error("Error with request", None, Option(e.getMessage))
)
),
f
)
}
}
private [ems] def createObject[A](fromTemplate: (Template) => A,
saveObject: (A) => Either[Exception, A],
segments: (A) => Seq[String])
(implicit user: User) = {
val post = for {
_ <- POST
_ <- authenticated(user)
_ <- contentType(CollectionJsonResponse.contentType)
rb <- baseURIBuilder
} yield {
withTemplate {
t =>
val e = fromTemplate(t)
saveObject(e).fold(
ex => InternalServerError ~> ResponseString(ex.getMessage),
stored => Created ~> Location(rb.segments(segments(stored) : _*).build().toString)
)
}
}
post
}
private [ems] def authenticated(user: User) = {
getOrElse(Some(user).filter(_.authenticated), Forbidden)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment