Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit of sample

  • Loading branch information...
commit 8cf3530c52bd1abd9a426a583341c1dec19288e1 1 parent 4a4e5df
Jennifer Hickey authored
View
3  .gitignore
@@ -0,0 +1,3 @@
+dist
+target
+log
View
14 README.md
@@ -1,2 +1,14 @@
cf-unfiltered-sample
-====================
+================
+An [Unfiltered](https://github.com/unfiltered/unfiltered) sample generated from the [giter8 template](https://github.com/softprops/unfiltered.g8). Unfiltered is a toolkit for servicing HTTP requests in Scala. This example uses embedded Jetty and is deployed to Cloud Foundry as a standalone application.
+
+### Deploying to Cloud Foundry
+
+To deploy the application to Cloud Foundry, simply build the dist and push it to Cloud Foundry using the provided manifest.yml file. You may need to modify the manifest to use a unique URL.
+
+```bash
+sbt clean compile package-dist
+vmc push
+Would you like to deploy from the current directory? [Yn]:
+Pushing application 'cf-unfiltered-sample'...
+```
View
22 build.sbt
@@ -0,0 +1,22 @@
+import com.twitter.sbt._
+
+seq(StandardProject.newSettings: _*)
+
+packageDistZipName := "cf-unfiltered-sample.zip"
+
+organization := "com.example"
+
+name := "cf-unfiltered-sample"
+
+version := "0.1.0-SNAPSHOT"
+
+libraryDependencies ++= Seq(
+ "net.databinder" %% "unfiltered-filter" % "0.6.1",
+ "net.databinder" %% "unfiltered-jetty" % "0.6.1",
+ "org.clapper" %% "avsl" % "0.3.6",
+ "net.databinder" %% "unfiltered-spec" % "0.6.1" % "test"
+)
+
+resolvers ++= Seq(
+ "java m2" at "http://download.java.net/maven/2"
+)
View
15 manifest.yml
@@ -0,0 +1,15 @@
+---
+applications:
+ dist/cf-unfiltered-sample/cf-unfiltered-sample.zip:
+ name: cf-unfiltered-sample
+ framework:
+ name: standalone
+ info:
+ mem: 64M
+ description: Standalone Application
+ exec:
+ runtime: java
+ command: java $JAVA_OPTS -jar cf-unfiltered-sample_2.9.1-0.1.0-SNAPSHOT.jar
+ url: cf-unfiltered-sample.${target-base}
+ mem: 512M
+ instances: 1
View
1  project/build.properties
@@ -0,0 +1 @@
+sbt.version=0.11.2
View
3  project/plugins.sbt
@@ -0,0 +1,3 @@
+addSbtPlugin("com.twitter" %% "sbt-package-dist" % "1.0.0")
+
+resolvers += "twitter-repo" at "http://maven.twttr.com"
View
24 src/main/resources/avsl.conf
@@ -0,0 +1,24 @@
+[logger_root]
+level: info
+handlers: h1, h2
+
+[handler_h1]
+level: debug
+class: FileHandler
+path: log
+formatter: f1
+append: true
+
+[handler_h2]
+level: trace
+class: ConsoleHandler
+formatter: f2
+
+[formatter_f1]
+class: DefaultFormatter
+format: [%Y/%m/%d %h:%m:%s:%S %z] (%l) %t
+tz: PDT
+
+[formatter_f2]
+class: DefaultFormatter
+format: [%Y/%m/%d %h:%m:%s:%S %z] (%l) %n: %t
View
13 src/main/resources/www/css/app.css
@@ -0,0 +1,13 @@
+* { margin:0; padding:0; }
+body, input {
+ font-family:helvetica, arial, sans-serif;
+ font-size:24px;
+ color:#333;
+ line-height:1.5em;
+}
+input[type="text"] { width: 100%; margin-bottom:.5em; }
+input[type="submit"] { font-size:36px; }
+#container {
+ width:400px;
+ margin:1em auto;
+}
View
71 src/main/scala/Example.scala
@@ -0,0 +1,71 @@
+package com.example
+
+import unfiltered.request._
+import unfiltered.response._
+
+import org.clapper.avsl.Logger
+
+/** unfiltered plan */
+class App extends unfiltered.filter.Plan {
+ import QParams._
+
+ val logger = Logger(classOf[App])
+
+ def intent = {
+ case GET(Path(p)) =>
+ logger.debug("GET %s" format p)
+ Ok ~> view(Map.empty)(<p> What say you? </p>)
+ case POST(Path(p) & Params(params)) =>
+ logger.debug("POST %s" format p)
+ val vw = view(params)_
+ val expected = for {
+ int <- lookup("int") is
+ int { _ + " is not an integer" } is
+ required("missing int")
+ word <- lookup("palindrome") is
+ trimmed is
+ nonempty("Palindrome is empty") is
+ pred(palindrome, { _ + " is not a palindrome" }) is
+ required("missing palindrome")
+ } yield vw(<p>Yup. { int.get } is an integer and { word.get } is a palindrome. </p>)
+ expected(params) orFail { fails =>
+ vw(<ul> { fails.map { f => <li>{f.error} </li> } } </ul>)
+ }
+ }
+ def palindrome(s: String) = s.toLowerCase.reverse == s.toLowerCase
+ def view(params: Map[String, Seq[String]])(body: scala.xml.NodeSeq) = {
+ def p(k: String) = params.get(k).flatMap { _.headOption } getOrElse("")
+ Html(
+ <html>
+ <head>
+ <title>uf example</title>
+ <link rel="stylesheet" type="text/css" href="/assets/css/app.css"/>
+ </head>
+ <body>
+ <div id="container">
+ { body }
+ <form method="POST">
+ <div>Integer <input type="text" name="int" value={ p("int") } /></div>
+ <div>Palindrome <input type="text" name="palindrome" value={ p("palindrome") } /></div>
+ <input type="submit" />
+ </form>
+ </div>
+ </body>
+ </html>
+ )
+ }
+}
+
+/** embedded server */
+object Server {
+ val logger = Logger(Server.getClass)
+ def main(args: Array[String]) {
+ val http = unfiltered.jetty.Http(Option(System.getenv("VCAP_APP_PORT")).getOrElse("8080").toInt)
+ http.context("/assets") { _.resources(new java.net.URL(getClass().getResource("/www/css"), ".")) }
+ .filter(new App).run({ svr =>
+ unfiltered.util.Browser.open(http.url)
+ }, { svr =>
+ logger.info("shutting down server")
+ })
+ }
+}
View
23 src/test/scala/ExampleSpec.scala
@@ -0,0 +1,23 @@
+package com.example
+
+import org.specs._
+
+import dispatch._
+
+object ExampleSpec extends Specification with unfiltered.spec.jetty.Served {
+
+ import dispatch._
+
+ def setup = { _.filter(new App) }
+
+ val http = new Http
+
+ "The example app" should {
+ "serve unfiltered requests" in {
+ val status = http x (host as_str) {
+ case (code, _, _, _) => code
+ }
+ status must_== 200
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.