Using HTTP Message¶
There are two types of HTTP messages, HTTPRequest
and HTTPResponse
. 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:
The method and URL define what content on the server is being requested.
/// 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.
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
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
.
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:
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. You can find the the Swift struct and built-in status properties in the Swift-NIO repo.
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.
var httpRes: HTTPResponse = ... httpRes.status = .notFound
Here is an example of a serialized HTTP response.
HTTP/1.1 200 OK Content-Length: 5 Content-Type: text/plain hello
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.
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.
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
containing arbitrary data. This data can be either static or streaming and can be in whatever format you want. Use the contentType
header to describe the type of data.
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.
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:
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.
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 for more in-depth information about all of the methods.