-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move code from http4s repo and change name to rho
https://github.com/http4s/http4s/tree/topic/awsomeDSL/5 commit: a13d9453f82517d59c238549e049b04439b56c10
- Loading branch information
1 parent
e677578
commit 96748fe
Showing
29 changed files
with
3,110 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
target/ | ||
/.lib/ | ||
|
||
*~ | ||
/.ensime | ||
/.idea/ | ||
/.idea_modules/ | ||
|
||
.cache | ||
.classpath | ||
.project | ||
.settings/ | ||
atlassian-ide-plugin.xml | ||
*.sublime-* | ||
.tags | ||
.tags_sorted_by_file | ||
.ensime_lucene |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
This software is licensed under the Apache 2 license, quoted below. | ||
|
||
Copyright 2013-2014 http4s [http://www.http4s.org] | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
use this file except in compliance with the License. You may obtain a copy of | ||
the License at | ||
|
||
[http://www.apache.org/licenses/LICENSE-2.0] | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
License for the specific language governing permissions and limitations under | ||
the License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import sbt._ | ||
import Keys._ | ||
|
||
object MyBuild extends Build { | ||
import Dependencies._ | ||
|
||
lazy val buildSettings = Defaults.defaultSettings ++ | ||
Seq( | ||
scalaVersion := "2.11.1", | ||
resolvers += Resolver.sonatypeRepo("snapshots"), | ||
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases", | ||
fork in run := true, | ||
libraryDependencies ++= Seq( | ||
http4sCore, | ||
http4sDSL, | ||
http4sBlaze, | ||
specs2 % "test" | ||
) ++ swaggerDeps | ||
) | ||
|
||
lazy val myProject = Project( | ||
id = "http4s-rho", | ||
base = file("."), | ||
settings = buildSettings ++ Seq(version := "0.1.0-SNAPSHOT") | ||
) | ||
|
||
} | ||
|
||
|
||
object Dependencies { | ||
lazy val http4sVersion = "0.2.0-SNAPSHOT" | ||
|
||
lazy val http4sCore = "org.http4s" %% "http4s-core" % http4sVersion | ||
lazy val http4sDSL = "org.http4s" %% "http4s-dsl" % http4sVersion | ||
lazy val http4sBlaze = "org.http4s" %% "http4s-blaze" % http4sVersion | ||
lazy val http4sJetty = "org.http4s" %% "http4s-servlet" % http4sVersion | ||
lazy val config = "com.typesafe" % "config" % "1.0.0" | ||
lazy val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.0.9" | ||
lazy val scalaloggingSlf4j = "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2" | ||
lazy val specs2 = "org.specs2" %% "specs2" % "2.3.11" | ||
|
||
lazy val swaggerDeps = Seq( | ||
"org.json4s" %% "json4s-jackson" % "3.2.10", | ||
"org.json4s" %% "json4s-ext" % "3.2.10" | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import sbt._ | ||
import Keys._ | ||
|
||
object MyBuild extends Build { | ||
import Dependencies._ | ||
|
||
lazy val buildSettings = Defaults.defaultSettings ++ | ||
Seq( | ||
scalaVersion := "2.11.1", | ||
resolvers += Resolver.sonatypeRepo("snapshots"), | ||
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases", | ||
libraryDependencies ++= Seq( | ||
http4sCore, | ||
http4sDSL, | ||
http4sBlaze | ||
) ++ swaggerDeps | ||
) | ||
|
||
lazy val myProject = Project( | ||
id = "http4s-rho", | ||
base = file("."), | ||
settings = buildSettings ++ Seq(version := "0.1.0-SNAPSHOT") | ||
) | ||
|
||
} | ||
|
||
|
||
object Dependencies { | ||
lazy val http4sVersion = "0.2.0-SNAPSHOT" | ||
|
||
lazy val http4sCore = "org.http4s" %% "http4s-core" % http4sVersion | ||
lazy val http4sDSL = "org.http4s" %% "http4s-dsl" % http4sVersion | ||
lazy val http4sBlaze = "org.http4s" %% "http4s-blaze" % http4sVersion | ||
lazy val http4sJetty = "org.http4s" %% "http4s-servlet" % http4sVersion | ||
lazy val config = "com.typesafe" % "config" % "1.0.0" | ||
lazy val logbackClassic = "ch.qos.logback" % "logback-classic" % "1.0.9" | ||
lazy val scalaloggingSlf4j = "com.typesafe.scala-logging" %% "scala-logging-slf4j" % "2.1.2" | ||
lazy val specs2 = "org.specs2" %% "specs2" % "2.3.11" | ||
|
||
lazy val swaggerDeps = Seq( | ||
"org.json4s" %% "json4s-jackson" % "3.2.10", | ||
"org.json4s" %% "json4s-ext" % "3.2.10" | ||
) | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/org/http4s/rho/swagger/annotations/ApiEnum.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.http4s.rho.swagger.annotations; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target({ElementType.TYPE}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface ApiEnum { | ||
public String[] values() default {}; | ||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/org/http4s/rho/swagger/annotations/ApiModel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package org.http4s.rho.swagger.annotations; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* A bean class used in the REST-api. | ||
* Suppose you have an interface | ||
* <code>@PUT @ApiOperation(...) void foo(FooBean fooBean)</code>, there is | ||
* no direct way to see what fields <code>FooBean</code> would have. This | ||
* annotation is meant to give a description of <code>FooBean</code> and | ||
* then have the fields of it be annotated with | ||
* <code>@ApiModelProperty</code>. | ||
* | ||
* @author Heiko W. Rupp | ||
*/ | ||
@Target({ElementType.TYPE}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface ApiModel { | ||
/** Provide a synopsis of this class */ | ||
String value() default ""; | ||
/** Provide a longer description of the class */ | ||
String description() default ""; | ||
/** Provide a superclass for the model to allow describing inheritence */ | ||
Class<?> parent() default Void.class; | ||
/** for models with a base class, a discriminator can be provided for polymorphic use cases */ | ||
String discriminator() default ""; | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/org/http4s/rho/swagger/annotations/ApiModelProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package org.http4s.rho.swagger.annotations; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** ApiProperty can be put on a Method to allow swagger to understand the json fields datatype and more. */ | ||
@Target({ElementType.METHOD, ElementType.FIELD}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface ApiModelProperty { | ||
/** Provide a human readable synopsis of this property */ | ||
String description() default ""; | ||
|
||
/** | ||
* If the values that can be set are restricted, they can be set here. In the form of a comma separated list | ||
* <code>registered, active, closed</code>. | ||
* | ||
* @return the allowable values | ||
*/ | ||
String allowableValues() default ""; | ||
|
||
/** | ||
* specify an optional access value for filtering in a Filter | ||
* implementation. This | ||
* allows you to hide certain parameters if a user doesn't have access to them | ||
*/ | ||
String access() default ""; | ||
|
||
/** long description of the property */ | ||
String notes() default ""; | ||
|
||
/** | ||
* Whether or not the property is required, defaults to true. | ||
* | ||
* @return true if required, false otherwise | ||
*/ | ||
boolean required() default true; | ||
|
||
/** | ||
* allows explicitly ordering the property in the model. Since reflection has no guarantee on | ||
* ordering, you should specify property order to keep models consistent across different VM implementations and versions. | ||
*/ | ||
int position() default 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.http4s.rho | ||
|
||
import shapeless.HList | ||
|
||
/** | ||
* Created by Bryce Anderson on 5/4/14. | ||
*/ | ||
trait CompileService[A] { | ||
def compile[T <: HList, F, O](action: CoolAction[T, F, O]): A | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package org.http4s | ||
package rho | ||
|
||
import scalaz.concurrent.Task | ||
import shapeless.{HNil, HList} | ||
import scalaz.{-\/, \/-, \/} | ||
import org.http4s.rho.bits.HListToFunc | ||
import scala.collection.mutable | ||
|
||
/** | ||
* Created by Bryce Anderson on 4/30/14. | ||
*/ | ||
trait CoolService extends HttpService with ExecutableCompiler with bits.PathTree { | ||
|
||
private val methods: mutable.Map[Method, Node] = mutable.HashMap.empty | ||
|
||
implicit protected def compilerSrvc = new CompileService[Unit] { | ||
override def compile[T <: HList, F, O](action: CoolAction[T, F, O]): Unit = append(action) | ||
} | ||
|
||
private def missingMethod = sys.error("Somehow an unknown Method type was found!") | ||
|
||
private def getMethod(method: Method) = methods.get(method).getOrElse(missingMethod) | ||
|
||
protected def append[T <: HList, F, O](action: CoolAction[T, F, O]): Unit = { | ||
val m = action.router.method | ||
val newLeaf = makeLeaf(action) | ||
val newNode = methods.get(m).getOrElse(HeadNode()).append(action.router.path, newLeaf) | ||
methods(m) = newNode | ||
} | ||
|
||
private def getResult(req: Request): Option[()=>Task[Response]] = { | ||
val path = req.requestUri.path.split("/").toList | ||
getMethod(req.requestMethod).walk(req, path, HNil) match { | ||
case null => None | ||
case \/-(t) => Some(t) | ||
case -\/(s) => Some(()=>onBadRequest(s)) | ||
} | ||
} | ||
|
||
override def isDefinedAt(x: Request): Boolean = getResult(x).isDefined | ||
|
||
override def apply(v1: Request): Task[Response] = getResult(v1) | ||
.map(_.apply()) | ||
.getOrElse{throw new MatchError("Route not defined")} | ||
|
||
override def applyOrElse[A1 <: Request, B1 >: Task[Response]](x: A1, default: (A1) => B1): B1 = { | ||
getResult(x) match { | ||
case Some(f) => f() | ||
case None => default(x) | ||
} | ||
} | ||
|
||
override def toString(): String = s"CoolService($methods)" | ||
} | ||
|
||
case class CoolAction[T <: HList, F, O](private[rho] val router: RouteExecutable[T], | ||
private[rho] val f: F, | ||
private[rho] val hf: HListToFunc[T, O, F]) { | ||
final def method: Method = router.method | ||
final def path: PathRule[_ <: HList] = router.path | ||
final def validators: HeaderRule[_ <: HList] = router.validators | ||
final def responseEncodings: Seq[MediaType] = hf.encodings | ||
final def responseType: Option[Manifest[O]] = hf.manifest | ||
final def decoders: Seq[MediaType] = router match { | ||
case r: CodecRouter[_,_] => r.decoder.consumes | ||
case _ => Nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package org.http4s | ||
package rho | ||
|
||
import scalaz.concurrent.Task | ||
import shapeless.HNil | ||
import scalaz.{-\/, \/-, \/} | ||
|
||
/** | ||
* Created by Bryce Anderson on 4/27/14. | ||
*/ | ||
|
||
sealed trait Decoder[T] { | ||
|
||
def decode(req: Request): Task[String\/T] | ||
def consumes: Seq[MediaType] | ||
def force: Boolean | ||
def or(other: Decoder[T]): Decoder[T] = Decoder.OrDec(this, other) | ||
|
||
private[Decoder] def checkMediaType(req: Request): Boolean = { | ||
if (!consumes.isEmpty) { | ||
req.headers.get(Header.`Content-Type`).map { | ||
h => | ||
consumes.find { | ||
m => m == h.mediaType | ||
}.isDefined | ||
}.getOrElse(false) | ||
} | ||
else false | ||
} | ||
} | ||
|
||
object Decoder { | ||
|
||
private type Result[T] = Task[String\/T] | ||
|
||
|
||
private case class BasicDecoder[T](decoder: Request => Result[T], consumes: Seq[MediaType], force: Boolean) extends Decoder[T] { | ||
override def decode(req: Request): Result[T] = decoder(req) | ||
} | ||
|
||
private case class OrDec[T](c1: Decoder[T], c2: Decoder[T]) extends Decoder[T] { | ||
|
||
override val consumes: Seq[MediaType] = c1.consumes ++ c2.consumes | ||
|
||
override def force: Boolean = c1.force || c2.force | ||
|
||
override def decode(req: Request): Result[T] = { | ||
if (c1.checkMediaType(req)) c1.decode(req) | ||
else if (c2.checkMediaType(req)) c2.decode(req) | ||
else if (c1.force) c1.decode(req) | ||
else if (c2.force) c2.decode(req) | ||
else Task.now(-\/(s"No suitable codec found. Supported media types: ${consumes.mkString(", ")}")) | ||
} | ||
} | ||
|
||
implicit val strDec: Decoder[String] = { | ||
val dec: Request => Result[String] = _.body.runLog.map(vs => \/-(new String(vs.reduce(_ ++ _).toArray))) | ||
BasicDecoder(dec, MediaType.`text/plain`::Nil, true) | ||
} | ||
|
||
implicit def reqDecoder[T](f: Request => Task[T], mediaType: Seq[MediaType] = Nil, force: Boolean = true): Decoder[T] = | ||
BasicDecoder(f.andThen(_.attempt.map(_.leftMap(t => t.getMessage))), mediaType, force) | ||
|
||
implicit def bodyDecoder[T](f: HttpBody => Task[T]): Decoder[T] = reqDecoder(r => f(r.body)) | ||
|
||
} |
Oops, something went wrong.