scamper
package scamper
Defines core types.
HTTP Messages
At the core of Scamper is HttpMessage, which is a trait that defines the fundamental characteristics of an HTTP message. HttpRequest and HttpResponse extend the specification to define characteristics specific to their respective message types.
An HttpRequest is created using a factory method defined in its companion object. Or you can start with a RequestMethod and use builder methods to further define the request.
import scamper.Header import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get val request = Get("/motd").withHeaders( Header("Host: localhost:8080"), Header("Accept: text/plain") ) printf("Request Method: %s%n", request.method) printf("Target URI: %s%n", request.target) request.headers.foreach(println) val host: Option[String] = request.getHeaderValue("Host")
An HttpResponse is created using a factory method defined in its companion object. Or you can start with a ResponseStatus and use builder methods to further define the response.
import scamper.{ BodyParser, Header } import scamper.Implicits.stringToEntity import scamper.ResponseStatus.Registry.Ok val response = Ok("There is an answer.").withHeaders( Header("Content-Type: text/plain"), Header("Connection: close") ) printf("Status Code: %s%n", response.statusCode) printf("Reason Phrase: %s%n", response.reasonPhrase) response.headers.foreach(println) val contentType: Option[String] = response.getHeaderValue("Content-Type") implicit val parser = BodyParser.text() printf("Body: %s%n", response.as[String])
- Alphabetic
- By Inheritance
- scamper
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Package Members
- package auth
Provides specialized access to authentication headers.
Provides specialized access to authentication headers.
Challenges and Credentials
When working with authentication, a
Challenge
is presented in the response, andCredentials
in the request. Each of these has an assigned scheme, which is associated with either a token or a set of parameters.import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Unauthorized import scamper.auth.{ Authorization, Challenge, Credentials, WwwAuthenticate } // Present response challenge (scheme and parameters) val challenge = Challenge("Bearer", "realm" -> "developer") val res = Unauthorized().withWwwAuthenticate(challenge) // Present request credentials (scheme and token) val credentials = Credentials("Bearer", "QWxsIEFjY2VzcyEhIQo=") val req = Get("/dev/projects").withAuthorization(credentials)
Basic Authentication
There are subclasses defined for Basic authentication:
BasicChallenge
andBasicCredentials
.import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Unauthorized import scamper.auth.{ Authorization, BasicChallenge, BasicCredentials, WwwAuthenticate } // Provide realm and optional parameters val challenge = BasicChallenge("admin", "title" -> "Admin Console") val res = Unauthorized().withWwwAuthenticate(challenge) // Provide user and password val credentials = BasicCredentials("sa", "l3tm31n") val req = Get("/admin/users").withAuthorization(credentials)
In addition, there are methods for Basic authentication defined in the header classes.
import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Unauthorized import scamper.auth.{ Authorization, WwwAuthenticate } // Provide realm and optional parameters val res = Unauthorized().withBasic("admin", "title" -> "Admin Console") // Access basic auth in response printf(s"Realm: %s%n", res.basic.realm) printf(s"Title: %s%n", res.basic.params("title")) // Provide user and password val req = Get("/admin/users").withBasic("sa", "l3tm3m1n") // Access basic auth in request printf(s"User: %s%n", req.basic.user) printf(s"Password: %s%n", req.basic.password)
Bearer Authentication
There are subclasses defined for Bearer authentication:
BearerChallenge
andBearerCredentials
. In addition, there are Bearer-specific methods available in the header classes.import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Unauthorized import scamper.auth.{ Authorization, WwwAuthenticate } // Provide challenge parameters val res = Unauthorized().withBearer( "scope" -> "user profile", "error" -> "invalid_token", "error_description" -> "Expired access token" ) // Print optional realm parameter res.bearer.realm.foreach(println) // Print scope from space-delimited parameter val scope: Seq[String] = res.bearer.scope scope.foreach(println) // Print error parameters res.bearer.error.foreach(println) res.bearer.errorDescription.foreach(println) res.bearer.errorUri.foreach(println) // Test for error conditions println(res.bearer.isInvalidToken) println(res.bearer.isInvalidRequest) println(res.bearer.isInsufficientScope) // Create request with Bearer token val req = Get("/users").withBearer("R290IDUgb24gaXQhCg==") // Access bearer auth in request printf("Token: %s%n", req.bearer.token)
- package client
Provides HTTP client implementation.
Provides HTTP client implementation.
Using HTTP Client
The HttpClient object can be used to send a request and handle the response.
import scamper.BodyParser import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.client.HttpClient implicit val parser = BodyParser.text() def getMessageOfTheDay(): Either[Int, String] = { val req = Get("localhost:8080/motd") // Send request and handle response HttpClient.send(req) { res => res.isSuccessful match { case true => Right(res.as[String]) case false => Left(res.statusCode) } } }
Note the request must be created with an absolute URI to make effective use of the client.
Creating HTTP Client
When using the
HttpClient
object as the client, it creates an HttpClient instance for one-time usage. If you plan to send multiple requests, you can create and maintain a reference to a client. With it, you also get access to methods corresponding to standard HTTP request methods.import scamper.BodyParser import scamper.Implicits.stringToUri import scamper.client.HttpClient implicit val parser = BodyParser.text() // Create HttpClient instance val client = HttpClient() def getMessageOfTheDay(): Either[Int, String] = { // Use client instance client.get("http://localhost:8080/motd") { res => res.isSuccessful match { case true => Right(res.as[String]) case false => Left(res.statusCode) } } }
And, if an implicit client is in scope, you can make use of
send()
on the request itself.import scamper.BodyParser import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.client.HttpClient import scamper.client.Implicits.ClientHttpRequestType // Adds send method to request import scamper.headers.{ Accept, AcceptLanguage } import scamper.types.Implicits.{ stringToMediaRange, stringToLanguageRange } implicit val client = HttpClient() implicit val parser = BodyParser.text(4096) Get("http://localhost:8080/motd") .withAccept("text/plain") .withAcceptLanguage("en-US; q=0.6", "fr-CA; q=0.4") .send(res => println(res.as[String])) // Send request and print response
See also ClientSettings for information about configuring the HTTP client before it is created.
- package cookies
Provides specialized access to message cookies.
Provides specialized access to message cookies.
Request Cookies
In HttpRequest, cookies are stringed together in the Cookie header. You can access them using extension methods provided by RequestCookies, with each cookie represented as PlainCookie.
import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.cookies.{ PlainCookie, RequestCookies } // Build request with cookies val req = Get("https://localhost:8080/motd").withCookies( PlainCookie("ID", "bG9zCg"), PlainCookie("Region", "SE-US") ) // Print all cookies req.cookies.foreach(println) // Get cookies by name val id: Option[PlainCookie] = req.getCookie("ID") val region: Option[PlainCookie] = req.getCookie("Region") // Get cookie values by name assert(req.getCookieValue("ID").contains("bG9zCg")) assert(req.getCookieValue("Region").contains("SE-US"))
Response Cookies
In HttpResponse, the cookies are a collection of Set-Cookie header values. Specialized access is provided by ResponseCookies, with each cookie represented as SetCookie.
import scamper.Implicits.stringToEntity import scamper.ResponseStatus.Registry.Ok import scamper.cookies.{ ResponseCookies, SetCookie } // Build response with cookies val res = Ok("There is an answer.").withCookies( SetCookie("ID", "bG9zCg", path = Some("/motd"), secure = true), SetCookie("Region", "SE-US") ) // Print all cookies res.cookies.foreach(println) // Get cookies by name val id: Option[SetCookie] = res.getCookie("ID") val region: Option[SetCookie] = res.getCookie("Region") // Get attributes of ID cookie val path: String = id.flatMap(_.path).getOrElse("/") val secure: Boolean = id.map(_.secure).getOrElse(false) // Get cookie values by name assert(res.getCookieValue("ID").contains("bG9zCg")) assert(res.getCookieValue("Region").contains("SE-US"))
- package headers
Provides specialized access to message headers.
Provides specialized access to message headers.
Using Header Classes
Specialized header access is provided by type classes. Some headers are available to both requests and responses, and others are available only to a specific message type. This behavior is driven by the HTTP specification.
import scamper.Implicits.stringToUri import scamper.RequestMethod.Registry.Get import scamper.headers.{ Accept, Host } import scamper.types.Implicits.stringToMediaRange // Build request using 'Host' and 'Accept' headers val req = Get("/motd").withHost("localhost:8080").withAccept("text/plain") // Access and print header values printf("Host: %s%n", req.host) printf("Accept: %s%n", req.accept.mkString(", "))
- package logging
Provides logging facilities.
- package server
Provides HTTP server implementation.
Provides HTTP server implementation.
Building HTTP Server
To build a server, you begin with
ServerApplication
. This is a mutable structure to which you apply changes to configure the server. Once the desired settings are applied, you invoke one of several methods to create the server.import java.io.File import scamper.BodyParser import scamper.Implicits.stringToEntity import scamper.ResponseStatus.Registry.{ NotFound, Ok } import scamper.server.HttpServer import scamper.server.Implicits._ // Get server application val app = HttpServer.app() // Add request handler to log all requests app.incoming { req => println(req.startLine) req } // Add request handler to specific request method and path app.get("/about") { req => Ok("This server is powered by Scamper.") } // Add request handler using path parameter app.put("/data/:id") { req => def update(id: Int, data: String): Boolean = ??? implicit val parser = BodyParser.text() // Get path parameter val id = req.params.getInt("id") update(id, req.as[String]) match { case true => Ok() case false => NotFound() } } // Serve static files app.files("/main", new File("/path/to/public")) // Gzip response body if not empty app.outgoing { res => res.body.isKnownEmpty match { case true => res case false => res.withGzipContentEncoding() } } // Create server val server = app.create(8080) printf("Host: %s%n", server.host) printf("Port: %d%n", server.port) // Run server for 60 seconds Thread.sleep(60 * 1000) // Close server when done server.close()
- package types
Defines standard types for header values.
Defines standard types for header values.
import scamper.Implicits.{ stringToEntity, stringToUri } import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Ok import scamper.headers.{ Accept, ContentType, TransferEncoding } import scamper.types.{ MediaRange, MediaType, TransferCoding } val json = MediaRange("application", "json", 0.9f) val html = MediaRange("text/html; q=0.1") val req = Get("/motd").withAccept(json, html) val text = MediaType("text/plain") val gzip = TransferCoding("gzip") val res = Ok("There is an answer.").withContentType(text).withTransferEncoding(gzip)
Using values defined in Implicits, properly formatted strings can be implicitly converted to standardized types.
import scamper.Implicits.{ stringToEntity, stringToUri } import scamper.RequestMethod.Registry.Get import scamper.ResponseStatus.Registry.Ok import scamper.headers.{ Accept, ContentType, TransferEncoding } import scamper.types.Implicits._ val req = Get("/motd").withAccept("application/json; q=0.9", "text/html; q=0.1") val res = Ok("There is an answer.").withContentType("text/plain").withTransferEncoding("gzip")
- See also
- package websocket
Provides WebSocket implementation.
Type Members
- trait BodyDecoder extends AnyRef
Provides access to decoded message body.
- trait BodyParser[T] extends AnyRef
Provides utility for parsing message body.
- trait Entity extends AnyRef
Provides input stream to HTTP entity.
- case class EntityTooLarge(maxLength: Long) extends IOException with Product with Serializable
Indicates entity larger than established maximum length.
Indicates entity larger than established maximum length.
EntityTooLarge
is a complement toReadLimitExceeded
. WhereasReadLimitExceeded
applies to raw bytes of an input stream,EntityTooLarge
applies to a constructed entity, which is potentially subject to decompression.- See also
- trait FilePart extends Part
Represents file content in multipart form data.
Represents file content in multipart form data.
- See also
- trait Header extends AnyRef
Defines HTTP header.
- case class HeaderNotFound(name: String) extends HttpException with Product with Serializable
Indicates absence of specified header.
- class HttpException extends RuntimeException
Indicates exception in HTTP processing.
- sealed trait HttpMessage extends AnyRef
Defines HTTP message.
- trait HttpRequest extends HttpMessage with MessageBuilder[HttpRequest]
Defines HTTP request.
Defines HTTP request.
- See also
- trait HttpResponse extends HttpMessage with MessageBuilder[HttpResponse]
Defines HTTP response.
Defines HTTP response.
- See also
- trait HttpVersion extends AnyRef
Defines HTTP version.
- trait MessageBuilder[T <: HttpMessage] extends AnyRef
Provides builder pattern for HTTP message.
- trait Multipart extends AnyRef
Represents multipart form data.
Represents multipart form data.
- See also
- sealed trait Part extends AnyRef
Represents part in multipart form data.
Represents part in multipart form data.
- See also
- trait QueryString extends AnyRef
Represents query string as mapped parameters.
- case class ReadLimitExceeded(limit: Long) extends IOException with Product with Serializable
Indicates read of input stream exceeds established limit.
Indicates read of input stream exceeds established limit.
ReadLimitExceeded
is a complement toEntityTooLarge
. WhereasReadLimitExceeded
applies to raw bytes of an input stream,EntityTooLarge
applies to a constructed entity, which is potentially subject to decompression.- See also
- trait RequestLine extends StartLine
Defines HTTP request line.
Defines HTTP request line.
- See also
- trait RequestMethod extends AnyRef
Defines HTTP request method.
Defines HTTP request method.
- See also
- trait ResponseStatus extends AnyRef
Defines HTTP response status.
Defines HTTP response status.
- See also
- sealed trait StartLine extends AnyRef
Defines HTTP message start line.
- trait StatusLine extends StartLine
Defines HTTP status line.
Defines HTTP status line.
- See also
- trait TextPart extends Part
Represents text content in multipart form data.
Represents text content in multipart form data.
- See also
- type Uri = URI
Uniform Resource Identifier
Value Members
- object BodyDecoder
Provides factory for
BodyDecoder
. - object BodyParser
Provides factory for
BodyParser
. - object Entity
Provides factory for
Entity
. - object FilePart
Provides factory for
FilePart
. - object Header
Provides factory for
Header
. - object HttpRequest
Provides factory for
HttpRequest
. - object HttpResponse
Provides factory for
HttpResponse
. - object HttpVersion
Provides factory for
HttpVersion
. - object Implicits
Includes implicit converter functions and type classes.
- object Multipart
Provides factory for
Multipart
. - object QueryString
Provides factory for
QueryString
. - object RequestLine
Provides factory for
RequestLine
. - object RequestMethod
Provides factory for
RequestMethod
.Provides factory for
RequestMethod
.- See also
- object ResponseStatus
Provides factory for
ResponseStatus
.Provides factory for
ResponseStatus
.- See also
- object StatusLine
Provides factory for
StatusLine
. - object TextPart
Provides factory for
TextPart
. - object Uri
Provides factory for
Uri
.
Provided herein is API documentation for Scamper, the HTTP library for Scala.