mirror of https://github.com/vapor/docs.git
137 lines
5.4 KiB
Markdown
137 lines
5.4 KiB
Markdown
# Using HTTP Message
|
|
|
|
There are two types of HTTP messages, [`HTTPRequest`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPRequest.html) and [`HTTPResponse`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPResponse.html). For the most part they are very similar, but there are a couple of differences.
|
|
|
|
## Request
|
|
|
|
HTTP requests are sent by clients to a server and they should always receive exactly one HTTP response. HTTP requests contain two unique fields over a standard HTTP message:
|
|
|
|
- [`method`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPRequest.html#/s:4HTTP11HTTPRequestV6methodXev)
|
|
- [`url`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPRequest.html#/s:4HTTP11HTTPRequestV3urlXev)
|
|
|
|
The method and URL define what content on the server is being requested.
|
|
|
|
```swift
|
|
/// GET /hello
|
|
let httpReq = HTTPRequest(method: .GET, url: "/hello")
|
|
```
|
|
|
|
You can define these when initializing an HTTP request, or set them later if the request is mutable.
|
|
|
|
```swift
|
|
var httpReq: HTTPRequest = ...
|
|
httpReq.method = .POST
|
|
httpReq.url = URL(...)
|
|
```
|
|
|
|
You can use Foundation's `URLComponents` to create `URL`s from their base components. HTTP request also has a property [`urlString`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPRequest.html#/s:4HTTP11HTTPRequestV9urlStringSSv) that you can use to set a custom URL `String` manually, without going through `URL`.
|
|
|
|
Here is what a serialized HTTP request looks like. This one is querying `/hello`.
|
|
|
|
```http
|
|
GET /hello HTTP/1.1
|
|
Content-Length: 0
|
|
```
|
|
|
|
## Response
|
|
|
|
HTTP responses are generated by servers in response to an HTTP request. HTTP response only has one unique field over general HTTP messages:
|
|
|
|
- [`status`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPResponse.html#/s:4HTTP12HTTPResponseV6statusXev)
|
|
|
|
The HTTP status is used to inform the client of any errors. The status consists of a status code and a reason. The code is always a three digit number and the reason is a short string explaining the code. You can see all of the status codes on [httpstatuses.com](https://httpstatuses.com). You can find the the Swift struct and built-in status properties in the [Swift-NIO](https://apple.github.io/swift-nio/docs/current/NIOHTTP1/Enums/HTTPResponseStatus.html) repo.
|
|
|
|
```swift
|
|
let httpRes = HTTPResponse(status: .ok, body: "hello")
|
|
```
|
|
|
|
All of the commonly used HTTP statuses will have pre-defined values you can use, like `.ok` for `200 OK`. You can also define your own custom status codes.
|
|
|
|
You can define the status when initializing an HTTP response, or set it later if the response is mutable.
|
|
|
|
```swift
|
|
var httpRes: HTTPResponse = ...
|
|
httpRes.status = .notFound
|
|
```
|
|
|
|
Here is an example of a serialized HTTP response.
|
|
|
|
```http
|
|
HTTP/1.1 200 OK
|
|
Content-Length: 5
|
|
Content-Type: text/plain
|
|
|
|
```
|
|
|
|
## Headers
|
|
|
|
Every HTTP message has a collection of headers. Headers contain metadata about the message and help to explain what is in the message's body.
|
|
|
|
```http
|
|
Content-Length: 5
|
|
Content-Type: text/plain
|
|
```
|
|
|
|
There must be at least a `"Content-Length"` or `"Transfer-Encoding"` header to define how long the message's body is. There is almost always a `"Content-Type"` header that explains what _type_ of data the body contains. There are many other common headers such as `"Date"` which specifies when the message was created, and more.
|
|
|
|
You can access an HTTP message's headers using the `headers` property.
|
|
|
|
```swift
|
|
var message: HTTPMessage ...
|
|
message.headers.firstValue(for: .contentLength) // 5
|
|
```
|
|
|
|
If you are interacting with common HTTP headers, you can use the convenience HTTP names instead of a raw `String`.
|
|
|
|
## Body
|
|
|
|
HTTP messages can have an [`HTTPBody`](https://api.vapor.codes/http/latest/HTTP/Structs/HTTPBody.html) containing arbitrary data. This data can be either static or streaming and can be in whatever format you want. Use the [`contentType`](https://api.vapor.codes/http/latest/HTTP/Protocols/HTTPMessage.html#/s:4HTTP11HTTPMessagePAAE11contentTypeXev) header to describe the type of data.
|
|
|
|
```swift
|
|
var message: HTTPMessage = ...
|
|
message.body = HTTPBody(string: "Hello, world!")
|
|
message.contentType = .plainText
|
|
```
|
|
|
|
!!! tip
|
|
Setting the `body` property will automatically update the `"Content-Length"` or `"Transfer-Encoding"` headers if required.
|
|
|
|
```swift
|
|
var message: HTTPMessage = ...
|
|
message.body = HTTPBody(string: """
|
|
{"message": "Hello, world!"}
|
|
""")
|
|
message.contentType = .json
|
|
```
|
|
|
|
## Codable
|
|
|
|
Two protocols are defined for making it easy to use `Codable` with HTTP:
|
|
|
|
- [`HTTPMessageEncoder`](https://api.vapor.codes/http/latest/HTTP/Protocols/HTTPMessageEncoder.html)
|
|
- [`HTTPMessageDecoder`](https://api.vapor.codes/http/latest/HTTP/Protocols/HTTPMessageDecoder.html)
|
|
|
|
These two coders allow you to encode and decode your custom `Codable` types into an HTTP body, setting the appropriate content type headers.
|
|
|
|
By default, HTTP provides conformance for `JSONEncoder` and `JSONDecoder`, but Vapor includes coders for many more types.
|
|
|
|
Here is an example of encoding a `Codable` struct to an HTTP response.
|
|
|
|
```swift
|
|
struct Greeting: Codable {
|
|
var message: String
|
|
}
|
|
// Create an instance of Greeting
|
|
let greeting = Greeting(message: "Hello, world!")
|
|
// Create a 200 OK response
|
|
var httpRes = HTTPResponse(status: .ok)
|
|
// Encode the greeting to the response
|
|
try JSONEncoder().encode(greeting, to: &httpRes, on: ...)
|
|
```
|
|
|
|
## API Docs
|
|
|
|
Check out the [API docs](https://api.vapor.codes/http/latest/HTTP/index.html) for more in-depth information about all of the methods.
|
|
|