Skip to content

Commit

Permalink
adding highlight.js for code highlighting of scala code
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddenton committed Mar 30, 2017
1 parent 0e388ba commit e70fda8
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 35 deletions.
10 changes: 5 additions & 5 deletions src/main/hugosite2/content/guide/building-http-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ weight = 5
+++

It's all very well being able to extract pieces of data from HTTP requests, but that's only half the story - we also want to be able to easily build responses. Fintrospect comes bundled with a extensible set of HTTP Response Builders to do this. The very simplest way is by using a ResponseBuilder object directly...
```
```scala
ResponseBuilder.toFuture(
ResponseBuilder.HttpResponse(ContentTypes.APPLICATION_JSON).withCode(Status.Ok).withContent("some text").build()
)
Expand All @@ -16,12 +16,12 @@ handling content types like JSON or XML in a set of popular OSS libraries. These
INSERT LINK TO FORMAT TABLE HERE..

The simplest (least concise) way to invoke an auto-marshalling (ie. typesafe) ResponseBuilder is along the lines of:
```
```scala
Xml.ResponseBuilder.HttpResponse(Status.Ok).withContent(<xml>lashings and lashings of wonderful</xml>).toFuture
```
... although with tiny bit of implicit magic, we can use custom status methods on the builders and then convert the `ResponseBuilder` to
a `Future[Response]`, you can reduce this to the rather more concise:
```
```scala
import io.fintrospect.formats.Xml.ResponseBuilder._
val responseViaImplicits: Future[Response] = Ok(<xml>lashings and lashings of wonderful</xml>)
```
Expand All @@ -34,7 +34,7 @@ Some of the JSON libraries (`Circe`, `Argonaut`, `Json4S`, `Play`) supported by
class instances directly to JSON without any custom conversion code needing to be written. This is supported by `encode()` and `decode()`
methods present on the relevant Fintrospect `JsonFormat` format instance (e.g. `io.fintrospect.formats.Circe.JsonFormat`). Generally,
these are very simple to use:
```
```scala
case class EmailAddress(address: String)

import io.circe.generic.auto._
Expand All @@ -50,7 +50,7 @@ encoder/decoder instances, you can get away with just importing the relevant `im
Fintrospect also contains filters which allow you to abstract away the HTTP Request/Response entirely. In this example,
the `Circe.Filters.AutoInOut` filter converts the `Service[Request, Response]` to a `Service[EmailAddress, ReversedEmailAddress]`, auto-converting
the case class objects in and out of the request/response. The returned status code in the `Response` is 200, but this is overridable:
```
```scala
import io.circe.generic.auto._
import io.fintrospect.formats.Circe
import io.fintrospect.formats.Circe.Auto._
Expand Down
2 changes: 1 addition & 1 deletion src/main/hugosite2/content/guide/client-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ returns a Twitter ```Future``` containing the response. Any required manipulatio
headers) can be done in the standard way by chaining a ```Filter``` to the client ```Service```. Note that ```Content-Type``` headers for posted HTTP
bodies is already handled by the bound ```Body``` instance.:

```
```scala
val employeeId = Path.integer("employeeId")
val name = Query.required.string("name")
val client: RouteClient = RouteSpec()
Expand Down
4 changes: 2 additions & 2 deletions src/main/hugosite2/content/guide/cross-field-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ For this purpose, you can use an `Extractor` - a trait which provides a single m
states: `Extracted(Option(value))` and `ExtractionFailed(parameter)` for missing or
invalid values. These constructs can be used inside a for comprehension to provide cross-field validation, and eventual creation of a target
object. Below is a service that implements this logic - note the use of a predicate and a failure reason which provides the logic for the check:
```
```scala
case class DateRange(startDate: LocalDate, endDate: Option[LocalDate])

val range: Extractor[Request, DateRange] = Extractor.mk {
Expand All @@ -36,7 +36,7 @@ to do so since any missing or invalid mandatory parameters short-circuit the com
incoming request.

The above example can be further simplified by use of the built-in `RequestFilters.ExtractableRequest` filter to transform the input:
```
```scala
RequestFilters.ExtractableRequest(range).andThen(Service.mk[DateRange, Response] {
dateRange => ...
})
Expand Down
10 changes: 5 additions & 5 deletions src/main/hugosite2/content/guide/defining-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,32 @@ builder pattern. Apart from the path-building elements (which terminate the buil
are the descriptive strings (used for the auto-documenting features). Here's the simplest possible REST-like example for getting all employees
in a notional system:

```
```scala
RouteSpec().at(Method.Get) / "employee"
```

Notice that the request routing in that example was completely static? If we want an example of a dynamic endpoint, such as listing
all users in a particular numerically-identified department, then we can introduce a ```Path``` parameter:
```
```scala
RouteSpec("list all employees in a particular group").at(Method.Get) / "employee" / Path.integer("departmentId")
```
... and we can do the same for Header and Query parameters; both optional and mandatory parameters are supported, as are parameters that can appear multiple times.:
```
```scala
RouteSpec("list all employees in a particular group")
.taking(Header.optional.boolean("listOnlyActive"))
.taking(Query.required.*.localDate("datesTakenAsHoliday"))
.at(Method.Get) / "employee" / Path.integer("departmentId")
```
Moving onto HTTP bodies - for example adding an employee via a HTTP Post and declaring the content types that we produce (although
this is optional):
```
```scala
RouteSpec("add employee", "Insert a new employee, failing if it already exists")
.producing(ContentTypes.TEXT_PLAIN)
.body(Body.form(FormField.required.string("name"), FormField.required.localDate("dateOfBirth")))
.at(Method.Post) / "user" / Path.integer("departmentId")
```
... or via a form submission and declaring possible responses:
```
```scala
RouteSpec("add user", "Insert a new employee, failing if it already exists")
.body(Body.form(FormField.required.string("name"), FormField.required.localDate("dateOfBirth")))
.returning(Created -> "Employee was created")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ interface to which the main functions are:

Parameters are created in a uniform way using the objects ```Path```, ```Header```, ```Query```, ```FormField``` and ```Body```.
The general form for definition is as follows, although since ```Path``` and ```Body``` parameters are always required, the middle step is omitted:
```
```scala
<parameter location class>.<required|optional>.<param type>("<name>")
```

Descriptions can be attached to these definitions for documentation purposes. Note the retrieved type for the optional param:
```
```scala
val anniversary = Header.required.localDate("anniversary", "the date you should not forget! format: yyyy-mm-dd")
val myAnniversary: LocalDate = age <-- request

Expand All @@ -29,14 +29,14 @@ val ohDearDear: Elem = anniversary <-- request
There are convenience methods for a standard set of "primitive" types, plus extensions for such as native Scala XML, Forms and JSON.

Additionally, there is another form for parameters which can appear multiple times in a request - simply insert the ```*()``` method in the chain:
```
```scala
val kidsBirthdays = Query.required.*.localDate("birthdays", "the dates you should not forget! format: yyyy-mm-dd")
val ourKidsBirthdays: Seq[LocalDate] = kidsBirthdays <-- request
```

#### forms
These represent a slightly special case you first need to retrieve the form from the request, and then the fields from the form.
```
```scala
val name = FormField.required.string("name")
val isMarried = FormField.optional.boolean("married")
val form = Body.form(name, isMarried)
Expand All @@ -58,7 +58,7 @@ with the happy case on-the-wire values. These throw exceptions if unsuccessful -
a rejected ```BadRequest``` (400) response which is returned to the caller.

An example for a simple domain case class Birthday:
```
```scala
case class Birthday(value: LocalDate)

val birthdayAsAQueryParam = Query.required(ParameterSpec.localDate().map(Birthday(_), (b:Birthday) => b.value), "DOB")
Expand All @@ -74,7 +74,7 @@ after the library in question. When defining a ```Body``` or ```Parameter```, if
use (else it will default to the bundled Argo JSON library) - and if this is done centrally then you can switch out JSON libraries with only
a single line of code change.

```
```scala
val jsonFormat = Argonaut.JsonFormat
val exampleObject = jsonFormat.obj("fieldName" -> json.string("hello"))
val json = Body.json(Option("my lovely JSON object"), exampleObject, Argonaut)
Expand All @@ -85,7 +85,7 @@ Notice that in the above we specified an example of the JSON message. This is no
<a href="http://json-schema.org/">JSON Schema</a> to be included in the auto-generated API documentation.

Additionally, in the case of some JSON libraries that provide auto marshalling and demarshalling to case class instances, you can remove the JSON step altogether:
```
```scala
case class Email(address: String)
val email = Body(Argonaut.bodySpec[Email](Option("an email address")), Email("jim@example.com"))
val retrieved: Email = email <-- request
Expand Down
11 changes: 5 additions & 6 deletions src/main/hugosite2/content/guide/server-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ this bound ```Service```, so no validation code is required. The response return
- ```Bad Request 400```: if there are any ```Header```, ```Query```, or ```Body``` params are missing (required only) or invalid

### simple example
```
```scala
val holidays = Query.required.*.localDate("datesTakenAsHoliday")
val includeManagement = Header.optional.boolean("includeManagement")

Expand All @@ -39,18 +39,17 @@ val route = ServerRoute[Request, Response] =
### modules
A Module is a collection of ```ServerRoute``` that share a common URL context, which is built up from the ```Root``` object. Add the
routes and then convert into a standard Finagle Service object which is then attached in the normal way to an HTTP server.
```
```scala
def listEmployees(): Service[Request, Response] = Service.mk(req => Future(Response()))

Http.serve(":8080",
RouteModule(Root / "employee")
.withRoute(RouteSpec("lists all employees").at(Method.Get) bindTo listEmployees)
.toService
)
```
Modules with different root contexts can also be combined with one another and then converted to a `Service`:
```
```scala
RouteModule(Root / "a").combine(RouteModule(Root / "b")).toService
```

Expand All @@ -65,7 +64,7 @@ Bundled with Fintrospect are:
- Sitemap XML format

Other implementations are pluggable by implementing the ```ModuleRenderer``` trait - see the example code for a simple XML implementation.
```
```scala
val service = RouteModule(Root / "employee", Swagger2dot0Json(ApiInfo("an employee discovery API", "3.0"))).toService
Http.serve(":8080", new HttpFilter(Cors.UnsafePermissivePolicy).andThen(service))
```
Expand All @@ -76,7 +75,7 @@ without it, the server will reject any cross-domain requests initiated inside a
Module routes can secured by adding an implementation of the ```Security``` trait - this essentially provides a filter through which
all requests will be passed. An ```ApiKey``` implementation is bundled with the library which return an ```401 Unauthorized``` HTTP
response code when a request does not pass authentication.
```
```scala
RouteModule(Root / "employee")
.securedBy(ApiKey(Header.required.string("api_key"), (key: String) => Future(key == "extremelySecretThing")))
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Templates are applied by using a custom ```RenderView``` filter to convert ```Vi
the filter. You can do this for entire modules by making the ```RouteModule``` itself generified on ```View``` by using the
templating ```Filter``` as a Module-level filter:

```
```scala
case class ViewMessage(value: String) extends View

val showMessage = Service.mk[Request, View] { _ => Future(ViewMessage("some value to be displayed")) }
Expand All @@ -25,7 +25,7 @@ val webModule = RouteModule(Root / "web",
## redirects
After Form posts, it might be desirable to return an HTTP redirect instead of a View in the case of success.
For this purpose, use an instance of the `View.Redirect` class. The location and the status code (default 303) are configurable:
```
```scala
val redirect = Service.mk[Request, View] { _ => Future(View.Redirect("http://my.server/myRoute")) }
```

Expand All @@ -42,7 +42,7 @@ INSERT LINK TO FORMAT TABLE HERE
# static content
Static files can easily be served from the either the Classpath or a Directory by using an instance of ```StaticModule``` with an
appropriately injected ```ResourceLoader```:
```
```scala
val cpModule = StaticModule(Root / "public", ResourceLoader.Classpath("package/path"))
val dirModule = StaticModule(Root / "public", ResourceLoader.Directory("file/dir/path"))
```
Expand Down
4 changes: 2 additions & 2 deletions src/main/hugosite2/content/guide/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ weight = 8

### routes
Provided trait ```TestingFintrospectRoute``` can be used to unit test your routes, as in the simple example below:
```
```scala
object EchoRoute {
val route = RouteSpec().at(Method.Get) / Path.string("message") bindTo( (message: String) => Service.mk {
req: Request => Future(PlainText.ResponseBuilder.OK(message))
Expand All @@ -30,7 +30,7 @@ generated fake servers for downstream dependencies - simply complete the stub im
especially well if you are utilising custom serialisation formats (such as one of the auto-marshalling JSON libraries), as there is
absolutely no marshalling code required to send back objects over the wire from your stub.

```
```scala
val route = RouteSpec().at(Get) / "myRoute" bindTo(() => Service.mk {r => Future(Response(Status.Ok))})
new TestHttpServer(9999, route).start()
```
Expand Down
9 changes: 7 additions & 2 deletions src/main/hugosite2/content/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,14 @@ Since Fintrospect is build on top of Finagle, it's worth acquainting yourself wi
1. Finagle provides protocol-agnostic RPC and is based on Netty
2. It is mainly asynchronous and makes heavy usage of Twitter's version of Scala Futures
3. It defines uniform ```Service``` and ```Filter``` interfaces for both client and server APIs that are effectively a single method...

```scala
Service: def apply(request : Request) : Future[Response]
Filter: def apply(request : RequestIn, service : Service[RequestOut, ResponseIn]) : Future[ResponseOut]
trait Service {
def apply(request : Request) : Future[Response]
}
trait Filter {
def apply(request : RequestIn, service : Service[RequestOut, ResponseIn]) : Future[ResponseOut]
}
```
4. ```Filters``` can be chained together and then applied to a ```Service```, which results in another ```Service```. This is useful to
apply layers of functionality such as caching headers, retry behaviour, and timeouts.
Expand Down
2 changes: 2 additions & 0 deletions src/main/hugosite2/static/js/highlight.pack.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
<script src="{{ .Site.BaseURL }}js/owl.carousel.min.js"></script>

<!-- custom -->
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.10.0/highlight.min.js"></script>
<script src="{{ .Site.BaseURL }}js/highlight.pack.js"></script>

<script>hljs.initHighlightingOnLoad();</script>
<script>
$('.language-scala').addClass('scala').removeClass('language-scala');
</script>

<script>
hljs.configure({languages: ['scala']
});
hljs.initHighlightingOnLoad();
</script>

0 comments on commit e70fda8

Please sign in to comment.