2: Specifying Request Headers

It’s easy to specify request headers. The HeaderName class provides an arrow operator, which can be used with the Headers factory constructor like this. In this example, we ask for some French content from a website that switches automatically (Google).

...   imports
object Example2a {

  val headers = Headers(
    ACCEPT -> "text/html",
    ACCEPT_LANGUAGE -> "fr"
  )
  val httpClient = new HttpClient

  def main(args: Array[String]) {
    val response = httpClient.get("http://www.google.com/", headers)

    // prints a list of the response header names available to you
    println(response.headers.names.sorted)

    val startOfBody = response.body.asString.indexOf("<body")
    // show some French content
    println(response.body.asString.substring(startOfBody))
  }
}

We set the “Accept” header with the value “fr” and request Google’s main page. It responds in French. Also shown in this example is access to the response header names using response.headers.names.

Adding Headers to Requests

There is an alternative way to do what we did in the example above. In fact, it’s not really an alternative; it’s what happens under the hood in that example.

import uk.co.bigbeeconsultants.http._
import request.Request
import header.Headers
import header.HeaderName._

object Example2b {
  val headers = Headers(
    ACCEPT -> "text/html",
    ACCEPT_LANGUAGE -> "fr"
  )
  val httpClient = new HttpClient

  def main(args: Array[String]) {
    val request = Request.get("http://www.google.com/")
    val response = httpClient.makeRequest(request + headers)

    ... etc as above
}

This example explicity constructs a Request object and passes it to the execute method, along with the headers. The + operation merely converts the request instance without any headers to one with headers, and it can be applied multiple times on Header or Headers if necessary. (Instances are, of course, immutable.)

Default Headers

The Headers object we constructed and passed into the get method could also be passed into the HttpClient constructor, where it will be used by all its requests, in addition to the headers used on the request itself. When there are multiple collections of headers, they are aggregated in the ‘obvious’ way so that the latest ones take precedence. HttpClient has a default value for the headers which is

  val defaultRequestHeaders = Headers (
    ACCEPT -> "*/*",
    ACCEPT_ENCODING -> GZIP,
    ACCEPT_CHARSET -> (UTF8 + ",*;q=.1")
  )

Because headers are held in a list within Headers, it is easy to extend or reduce an existing list.

Also, Headers has apply, get, filter, contains etc map-like methods to make it easy to find any particular header. But remember that the HTTP protocol treats its headers as a List, not as a Map; Headers is therefore not really a Map.