✎ Edit on GitHub

> Module: `import HTTP`

# Request

The most common part of the `HTTP` library we'll be interacting with is the `Request` type. Here's a look at some of the most commonly used attributes in this type.

    public var method: Method
    public var uri: URI
    public var parameters: Node
    public var headers: [HeaderKey: String]
    public var body: Body
    public var data: Content

### Method

The HTTP `Method` associated with the `Request`, ie: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`.

### URI

The associated `URI` of the request. We will use this to access attributes about the `uri` the request was sent to.

For example, given the following uri: `http://vapor.codes/example?query=hi#fragments-too`

    let scheme = request.uri.scheme // http
    let host = request.uri.host // vapor.codes

    let path = request.uri.path // /example
    let query = request.uri.query // query=hi
    let fragment = request.uri.fragment // fragments-too

### Route Parameters

The url parameters associated with the request. For example, if we have a path registered as `hello/:name/age/:age`, we would be able to access those in our request, like so:

    let name = request.parameters["name"] // String?
    let age = request.parameters["age"]?.int // Int?

Or, to automatically throw on `nil` or invalid variable, you can also `extract`

    let name = try request.parameters.extract("name") as String
    let age = try request.parameters.extract("age") as Int

These extract functions can cast to any `NodeInitializable` type, including your own custom types. Make sure to check out Node for more info.

> Note: Vapor also provides type safe routing in the routing section of our docs.

### Headers

These are the headers associated with the request. If you are preparing an outgoing request, this can be used to add your own keys.

    let contentType = request.headers["Content-Type"]

Or for outgoing requests:

    let request = Request ...
    request.headers["Content-Type"] = "application/json"
    request.headers["Authorization"] = ... my auth token

#### Extending Headers

We generally seek to improve code bases by removing stringly typed code where possible. We can add variables to the headers using generic extensions.

    extension HTTP.KeyAccessible where Key == HeaderKey, Value == String {
        var customKey: String? {
          get {
            return self["Custom-Key"]
          }
          set {
            self["Custom-Key"] = newValue
          }
        }
    }

With this pattern implemented, our string `"Custom-Key"` is contained in one section of our code. We can now access like this:

    let customKey = request.headers.customKey

    // or

    let request = ...
    request.headers.customKey = "my custom value"

### Body

This is the body associated with the request and represents the general data payload. You can view more about body in the associated docs

For incoming requests, we'll often pull out the associated bytes like so:

    let rawBytes = request.body.bytes

## Content

Generally when we're sending or receiving requests, we're using them as a way to transport content. For this, Vapor provides a convenient `data` variable associated with the request that prioritizes content in a consistent way.

For example, say I receive a request to `http://vapor.codes?hello=world`.

    let world = request.data["hello"]?.string

This same code will work if I receive a JSON request, for example:

    {
      "hello": "world"
    }

Will still be accessible through data.

    let world = request.data["hello"]?.string

> Note: Force unwrap should never be used.

This also applies to multi-part requests and can even be extended to new types such as XML or YAML through middleware.

If you'd prefer to access given types more explicitly, that's totally fine. The `data` variable is purely opt-in convenience for those who want it.

## JSON

To access JSON directly on a given request, use the following:

    let json = request.json["hello"]

## Query Parameters

The same applies to query convenience:

    let query = request.query?["hello"]  // String?
    let name = request.query?["name"]?.string // String?
    let age = request.query?["age"]?.int // Int?
    let rating = request.query?["rating"]?.double // Double?

## Key Paths

Key paths work on most Vapor types that can have nested key value objects. Here's a couple examples of how to access given the following json:

    {
      "metadata": "some metadata",
      "artists" : {
        "href": "http://someurl.com",
        "items": [
          {
            "name": "Van Gogh",
          },
          {
            "name": "Mozart"
          }
        ]
      }
    }

We could access the data in the following ways:

### Metadata

Access top level values

    let type = request.data["metadata"].string // "some metadata"

### Items

Access nested values

    let items = request.data["artists", "items"] // [["name": "Van Gogh"], ["name": "Mozart"]]

### Mixing Arrays and Objects

Get first artists

    let first = request.data["artists", "items", 0] // ["name": "Van Gogh"]

### Array Item

Get key from array item

    let firstName = request.data["artists", "items", 0, "name"] // "Van Gogh"

### Array Comprehension

We can also smartly map an array of keys, for example, to just get the names of all of the artists, we could use the following

    let names = request.data["artists", "items", "name"] // ["Van Gogh", "Mozart"]