/foursquare-fhttp

A scalaj-http style library for finagle http clients

Primary LanguageScalaOtherNOASSERTION

Foursquare Finagle Http Library

Finagle is a wonderful protocol agnostic communication library. Building an http client using finagle is super simple. However, building an http request and parsing the response can ba a chore. FHttp is a scala-idiomatic request building interface similar to scalaj-http for finagle http clients.

Like scalaj-http, it supports multipart data and oauth1.

You will probably want to override FHttpClient.service to add your own logging and tracing filters.

##How to Build## ./sbt compile ./sbt test

##API Docs##

Adding FHttp to your build

The project is cross-compiled for scala 2.9.2 and scala 2.10.2. In your build.sbt, add:

"com.foursquare" %% "foursquare-fhttp" % "0.1.11"

Some Simple Examples

import com.foursquare.fhttp._
import com.foursquare.fhttp.FHttpRequest._
import com.twitter.conversions.storage._
import com.twitter.conversions.time._
import com.twitter.finagle.builder.ClientBuilder
import com.twitter.finagle.http.Http

// Create the singleton client object using a default client spec (hostConnectionLimit=1, no SSL)
val clientDefault = new FHttpClient("test", "localhost:80").releaseOnShutdown()

// or customize the ClientBuilder
val client = new FHttpClient("test2", "localhost:80", 
    ClientBuilder()
      .codec(Http(_maxRequestSize = 1024.bytes,_maxResponseSize = 1024.bytes))
      .hostConnectionLimit(15)
      .tcpConnectTimeout(30.milliseconds)
      .retries(0)).releaseOnShutdown()

// add parameters
val clientWParams = client("/path").params("msg"->"hello", "to"->"world").params(List("from"->"scala"))

// or headers
val clientWParamsWHeaders = clientWParams.headers(List("a_header"->"a_value"))

// non-blocking POST
val responseFut = clientWParamsWHeaders.postFuture()

// or issue a blocking request
clientWParamsWHeaders.getOption()

OAuth Example

import com.foursquare.fhttp._
import com.foursquare.fhttp.FHttpRequest._

// Create the singleton client object using a default client spec
val client = new FHttpClient("oauth", "term.ie:80")
val consumer = Token("key", "secret")

// Get the request token
val token = client("/oauth/example/request_token").oauth(consumer).get_!(asOAuth1Token)

// Get the access token
val accessToken = client("/oauth/example/access_token").oauth(consumer, token).get_!(asOAuth1Token)

// Try some queries
client("/oauth/example/echo_api").params("k1"->"v1", "k2"->"v2").oauth(consumer, accessToken).get_!()
// res0: String = k1=v1&k2=v2

Dropbox OAuth Example

Here's a slightly more complicated oauth (and HTTPS) example showing, using a Dropbox API account.

import com.foursquare.fhttp._
import com.foursquare.fhttp.FHttpRequest._
import com.twitter.conversions.storage._
import com.twitter.conversions.time._
import com.twitter.finagle.builder.ClientBuilder
import com.twitter.finagle.http.Http

// Using the App key and App Secret, fill out the consumer token here:
val consumer = Token(dbApiKey, dbApiSecret)

val api = new FHttpClient("dropbox-api", "api.dropbox.com:443", 
    ClientBuilder()
      .codec(Http())
      .tls("api.dropbox.com")
      .tcpConnectTimeout(1.second)
      .hostConnectionLimit(1)
      .retries(0))

val reqToken = api("/1/oauth/request_token").oauth(consumer).post_!("", asOAuth1Token)

// Go authorize usage of the app in a web browser using this link:
println("""go visit

https://www.dropbox.com/1/oauth/authorize?oauth_token=%s&oauth_token_secret=%s

and accept the app!""".format(reqToken.key, reqToken.secret))


// wait for the app to be accepted by the user


// Finally, get the access token
val accessToken = api("/1/oauth/access_token").oauth(consumer, reqToken).post_!("", asOAuth1Token)


// and go do some stuff with it.
api("/1/account/info").oauth(consumer, accessToken).get_!()