diff --git a/3.0/docs/http/message.md b/3.0/docs/http/message.md index 6ce3c2f4..3ad9b7d2 100644 --- a/3.0/docs/http/message.md +++ b/3.0/docs/http/message.md @@ -1,15 +1,60 @@ # Using HTTPMessage -There are two types of HTTP messages: [`HTTPRequest`](#fixme) and [`HTTPResponse`](#fixme). For the most part they are very similar, but there are a couple of differences. The first part of this guide will explain the common properties, followed by the unique ones. +There are two types of HTTP messages, [`HTTPRequest`](#fixme) and [`HTTPResponse`](#fixme). For the most part they are very similar, but there are a couple of differences. -Here is what an HTTP request looks like. This one is querying `/hello`. +## 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`](#fixme) +- [`url`](#fixme) + +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`](#fixme) 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 ``` -Here is an example of a potential HTTP response to the previous request. +## 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`](#fixme) + +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). + +```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 @@ -33,7 +78,7 @@ There must be at least a `"Content-Length"` or `"Transfer-Encoding"` header to d You can access an HTTP message's headers using the `headers` property. ```swift -let message: HTTPMessage ... +var message: HTTPMessage ... message.headers.firstValue(for: .contentLength) // 5 ``` @@ -41,4 +86,51 @@ If you are interacting with common HTTP headers, you can use the convenience HTT ## Body -Coming soon. +HTTP messages can have an [`HTTPBody`](#fixme) containing arbitrary data. This data can be either static or streaming and can be in whatever format you want. Use the [`contentType`](#fixme) 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`](#fixme) +- [`HTTPMessageDecoder`](#fixme) + +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. + diff --git a/3.0/docs/http/server.md b/3.0/docs/http/server.md index 9e7cc724..d5992da4 100644 --- a/3.0/docs/http/server.md +++ b/3.0/docs/http/server.md @@ -1,6 +1,6 @@ # Using HTTPServer -HTTP servers respond to incoming [`HTTPRequests`](#fixme) with [`HTTPResponses`](#fixme). They usually run for long periods of time on dedicated computers. The [`HTTPServer`](#fixme) type is what powers Vapor's higher-level server. This short guide will show you how to set up your own HTTP server manually. +HTTP servers respond to incoming [`HTTPRequests`](#fixme) with [`HTTPResponses`](#fixme). The [`HTTPServer`](#fixme) type is what powers Vapor's higher-level server. This short guide will show you how to set up your own HTTP server manually. !!! tip If you are using Vapor, you probably don't need to use HTTP's APIs directly. Refer to [Vapor → Server](../vapor/server.md) for the more convenient APIs.