Permalink
Browse files

Revert "Revert "Merge branch 'master' into milestones/1.0.0-Mx""

This reverts commit ddd62b5.
  • Loading branch information...
1 parent 293f4e4 commit eb2e01c364db4729ce4e411deb0397466bcade86 @nuttycom nuttycom committed Mar 13, 2013
@@ -0,0 +1,15 @@
+<configuration>
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender" append="false">
+ <file>target/testlog.log</file>
+
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="trace">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
@@ -6,11 +6,12 @@ import org.specs2.mutable.Specification
import org.specs2.matcher._
import akka.dispatch.Future
import akka.dispatch.ExecutionContext
+import akka.util.Duration
trait HttpRequestMatchers extends Specification with FutureMatchers {
- case class succeedWithContent[A](matcher: Matcher[A]) extends Matcher[Future[HttpResponse[A]]] {
+ case class succeedWithContent[A](matcher: Matcher[A])(implicit await: Duration = Duration(10, "seconds")) extends Matcher[Future[HttpResponse[A]]] {
def apply[B <: Future[HttpResponse[A]]](expectable: Expectable[B]): MatchResult[B] = {
- val nested = whenDelivered[HttpResponse[A]] {
+ val nested = awaited[HttpResponse[A]](await) {
beLike {
case HttpResponse(status, _, Some(content), _) =>
(status.code must_== HttpStatusCodes.OK) and
@@ -11,6 +11,8 @@ import akka.dispatch.ExecutionContext
import blueeyes.json._
import blueeyes.util.metrics.DataSize
+import com.weiglewilczek.slf4s.Logger
+
import scala.xml.NodeSeq
import scalaz.Validation
import scalaz.Semigroup
@@ -20,6 +22,9 @@ trait HttpRequestHandlerCombinators {
implicit def service[A, B](handler: HttpServiceHandler[A, B]): HttpService[A, B] =
new HttpHandlerService(handler, identity[A])
+ def debug[A, B](logger: Logger): HttpService[A, B] => HttpService[A, B] =
+ (h: HttpService[A, B]) => new DebugService[A, B](logger, h)
+
/** The path combinator creates a handler that is defined only for suffixes
* of the specified path pattern.
*
@@ -304,6 +309,7 @@ trait HttpRequestHandlerCombinators {
def decodeUrl[A, B](h: HttpService[A, B]) = new DecodeUrlService[A, B](h)
}
+object HttpRequestHandlerCombinators extends HttpRequestHandlerCombinators
class IdentifierWithDefault[A, B](val identifier: A, dflt: => Option[B]) {
lazy val default = dflt
@@ -23,6 +23,8 @@ import scalaz.syntax.semigroup._
import scalaz.syntax.validation._
import scalaz.syntax.std.option._
+import com.weiglewilczek.slf4s.Logger
+
sealed trait AnyService {
def metadata: Option[Metadata]
lazy val inapplicable: Inapplicable = Inapplicable(this)
@@ -98,6 +100,17 @@ class FailureService[A, B](onFailure: HttpRequest[A] => (HttpFailure, String)) e
val metadata = None
}
+class DebugService[A, B](logger: Logger, val delegate: HttpService[A, B]) extends DelegatingService[A, B, A, B] {
+ val service = (request: HttpRequest[A]) => {
+ println("Received request: " + request)
+ logger.debug("Received request: " + request)
+ delegate.service(request)
+ }
+
+ lazy val metadata = None
+}
+
+
class PathService[A, B](path: RestPathPattern, val delegate: HttpService[A, B]) extends DelegatingService[A, B, A, B] {
val service = PathService.shift(path, _: HttpRequest[A]).toSuccess(inapplicable).flatMap(delegate.service)
@@ -7,6 +7,8 @@ import akka.dispatch.ExecutionContext
import blueeyes.bkka.Stoppable
import blueeyes.core.http._
+import com.weiglewilczek.slf4s.Logging
+
/**
val emailService = {
service("email", "1.23") { context =>
@@ -39,7 +41,21 @@ trait ServiceBuilder[T] {
val name = sname
val version = sversion
val desc = sdesc
- def lifecycle(context: ServiceContext) = slifecycle(context)
+
+ def lifecycle(context: ServiceContext) = {
+ import HttpRequestHandlerCombinators._
+
+ // Service paths are always prefixed by service name and major version string.
+ val ServiceLifecycle(startup, runningState) = slifecycle(context)
+ ServiceLifecycle(
+ startup,
+ (s: S) => {
+ val (service, stoppable) = runningState(s)
+ val service0 = path("/%s".format(sname)) { path("/%s".format(sversion.vname)) { service } }
+ (service0, stoppable)
+ }
+ )
+ }
}
}
@@ -1,6 +1,8 @@
package blueeyes.core.service
-case class ServiceVersion(majorVersion: Int, minorVersion: Int, version: String)
+case class ServiceVersion(majorVersion: Int, minorVersion: Int, version: String) {
+ def vname = "v" + majorVersion
+}
trait ServiceVersionImplicits {
implicit def fromString(value: String) = {
@@ -0,0 +1,15 @@
+<configuration>
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender" append="false">
+ <file>target/testlog.log</file>
+
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="trace">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
@@ -100,7 +100,7 @@ class HttpServerSpec extends Specification with FutureMatchers {
"HttpServer.apply" should {
"delegate to service request handler" in server {
case (s, _) =>
- s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/foo/bar")).toOption.get must whenDelivered {
+ s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/test/v1/foo/bar")).toOption.get must whenDelivered {
beLike {
case HttpResponse(HttpStatus(status, _), headers, Some(content), _) =>
(status must_== OK) and
@@ -112,7 +112,7 @@ class HttpServerSpec extends Specification with FutureMatchers {
"produce NotFound response when service is not defined for request" in server {
case (s, _) =>
- s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/blahblah")).toOption.get must whenDelivered {
+ s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/test/v1/blahblah")).toOption.get must whenDelivered {
beLike {
case HttpResponse(HttpStatus(HttpStatusCodes.NotFound, _), _, _, _) => ok
}
@@ -121,15 +121,15 @@ class HttpServerSpec extends Specification with FutureMatchers {
"gracefully handle error-producing service handler" in server {
case (s, _) =>
- s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/foo/bar/error")).toOption.get must whenDelivered {
+ s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/test/v1/foo/bar/error")).toOption.get must whenDelivered {
beLike {
case HttpResponse(HttpStatus(HttpStatusCodes.InternalServerError, _), _, _, _) => ok
}
}
}
"gracefully handle dead-future-producing service handler" in server {
case (s, _) =>
- s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/foo/bar/dead")).toOption.get must whenDelivered {
+ s.service(HttpRequest[ByteChunk](HttpMethods.GET, "/test/v1/foo/bar/dead")).toOption.get must whenDelivered {
beLike {
case HttpResponse(HttpStatus(HttpStatusCodes.InternalServerError, _), _, _, _) => ok
}
@@ -58,10 +58,10 @@ class HttpServiceDescriptorFactoryCombinatorsSpec extends BlueEyesServiceSpecifi
}
""".format(System.getProperty("java.io.tmpdir") + File.separator + logFilePrefix + ".log")
- implicit val httpClient: HttpClient[ByteChunk] = new HttpClient[ByteChunk] {
+ val httpClient: HttpClient[ByteChunk] = new HttpClient[ByteChunk] {
def apply(r: HttpRequest[ByteChunk]): Future[HttpResponse[ByteChunk]] = {
val responseContent = r.uri.path match {
- case Some("/foo/v1/proxy") =>
+ case Some("/foo/v1/email/v1/proxy") =>
DefaultBijections.stringToChunk("it works!")
case _ =>
@@ -82,9 +82,11 @@ class HttpServiceDescriptorFactoryCombinatorsSpec extends BlueEyesServiceSpecifi
new File(System.getProperty("java.io.tmpdir")).listFiles find { file => file.getName.startsWith(logFilePrefix) && file.getName.endsWith(".log") }
}
+ val monitorClient = client.path("/email/v1")
+
"service" should {
"support health monitor service" in {
- client.get[ByteChunk]("/foo") must whenDelivered {
+ monitorClient.get[ByteChunk]("/foo") must whenDelivered {
beLike {
case HttpResponse(HttpStatus(OK, _), _, None, _) => ok
}
@@ -93,7 +95,7 @@ class HttpServiceDescriptorFactoryCombinatorsSpec extends BlueEyesServiceSpecifi
"support health monitor statistics" in {
import blueeyes.json.JParser.parse
- client.get[JValue]("/blueeyes/services/email/v1/health") must succeedWithContent { (content: JValue) =>
+ monitorClient.get[JValue]("/blueeyes/services/email/v1/health") must succeedWithContent { (content: JValue) =>
(content \ "requests" \ "GET" \ "count" \ "eternity" mustEqual(parse("[1]"))) and
(content \ "requests" \ "GET" \ "timing" mustNotEqual(JUndefined)) and
(content \ "requests" \ "GET" \ "timing" \ "perSecond" \ "eternity" mustNotEqual(JUndefined)) and
@@ -104,7 +106,7 @@ class HttpServiceDescriptorFactoryCombinatorsSpec extends BlueEyesServiceSpecifi
}
"add service locator" in {
- client.get[String]("/proxy") must succeedWithContent((_: String) must_== "it works!")
+ monitorClient.get[String]("/proxy") must succeedWithContent((_: String) must_== "it works!")
}
"RequestLogging: Creates logRequest" in{
@@ -16,7 +16,7 @@ class ServerHealthMonitorServiceSpec extends BlueEyesServiceSpecification with S
"Server Health Monitor Service" should{
"get server health" in {
- client.get[JValue]("/blueeyes/server/health") must succeedWithContent {
+ client.get[JValue]("/serverhealth/v1/blueeyes/server/health") must succeedWithContent {
(content: JValue) => {
(content \ "runtime" must_!=(JUndefined)) and
(content \ "memory" must_!=(JUndefined)) and
Oops, something went wrong.

0 comments on commit eb2e01c

Please sign in to comment.