add url-encoded form docs

This commit is contained in:
tanner0101 2018-04-16 17:35:00 -04:00
parent f49086b4fa
commit 7d2fb87258
4 changed files with 172 additions and 1 deletions

View File

@ -0,0 +1,42 @@
# Getting Started with URL-Encoded Form
URL-Encoded Form ([vapor/url-encoded-form](https://github.com/vapor/url-encoded-form)) is a small package that helps you parse and serialize `application/x-www-form-urlencoded` data. URL-encoded forms are a widely-supported encoding on the web. It's most often used for serializing web forms sent via POST requests.
The URL-Encoded Form package makes it easy to use this encoding by integrating directly with `Codable`.
## Vapor
This package is included with Vapor and exported by default. You will have access to all `URLEncodedForm` APIs when you import `Vapor`.
```swift
import Vapor
```
## Standalone
The URL-Encoded Form package is lightweight, pure-Swift, and has very few dependencies. This means it can be used to work with `form-urlencoded` data for any Swift project—even one not using Vapor.
To include it in your package, add the following to your `Package.swift` file.
```swift
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Project",
dependencies: [
...
.package(url: "https://github.com/vapor/url-encoded-form.git", from: "1.0.0"),
],
targets: [
.target(name: "Project", dependencies: ["URLEncodedForm", ... ])
]
)
```
Use `import URLEncodedForm` to access the APIs.
!!! warning
Some of this guide may contain Vapor-specific APIs, however most of it should be applicable to the URL-Encoded Form package in general.
Visit the [API Docs](https://api.vapor.codes/url-encoded-form/latest/URLEncodedForm/index.html) for specific API info.

View File

@ -0,0 +1,126 @@
# Using URL-Encoded Form
URL-Encoded Form is a widely-supported encoding on the web. It's most often used for serializing web forms sent via POST requests. This encoding is also used to send structured data in URL query strings.
It is a relatively efficient encoding for sending small amounts of data. However, all data must be percent-encoded making this encoding suboptimal for large amounts of data. See the [Multipart](../multipart/getting-started.md) encoding if you need to upload things like files.
!!! tip
URL-Encoded Form integrates with [`Content`](https://api.vapor.codes/vapor/latest/Vapor/Protocols/Content.html) like all other encoding methods in Vapor. See [Vapor → Content](../vapor/content.md) for more information about the [`Content`](https://api.vapor.codes/vapor/latest/Vapor/Protocols/Content.html) protocol.
Let's take a look at how to decode a `application/x-www-form-urlencoded` request.
## Decode Body
Most often, you will be decoding `form-urlencoded`-encoded requests from a web form. Let's take a look at what one of these requests might look like. After that, we will take a look at what the HTML form for that request would look like.
### Request
Here is an example `form-urlencoded`-encoded request for creating a new user.
```http
POST /users HTTP/1.1
Content-Type: application/x-www-form-urlencoded
name=Vapor&age=3&luckyNumbers[]=5&luckyNumbers[]=7
```
You can see the `[]` notation is used to encode arrays. Your web form will need to use this notation as well.
### Form
There are many ways to create a `form-urlencoded`-encoded request, but the most common is an HTML web form. Here is what the HTML form for this request might have looked like.
```html
<form method="POST" action="/users">
<input type="text" name="name">
<input type="text" name="age">
<input type="text" name="luckyNumbers[]">
<input type="text" name="luckyNumbers[]">
</form>
```
Since we are not specifying a special `enctype` attribute on the `<form>`, the browser will URL-encode the form by default. We are also providing two fields with the same name, `luckyNumbers[]`. This will let us send an array of values.
### Content
Now let's take a look at how we would handle this request in Vapor. The first step (as always with [`Content`](https://api.vapor.codes/vapor/latest/Vapor/Protocols/Content.html)) is to create a `Codable` struct that represents the data structure.
```swift
import Vapor
struct User: Content {
var name: String
var age: Int
var luckyNumbers: [Int]
}
```
Now that we have our `User` struct, let's decode that request! We can use the [`ContentContainer`](https://api.vapor.codes/vapor/latest/Vapor/Structs/ContentContainer.html) to do this easily.
```swift
router.post("users") { req -> Future<HTTPStatus> in
return try req.content.decode(User.self).map(to: HTTPStatus.self) { user in
print(user.name) // "Vapor"
print(user.age) // 3
print(user.luckyNumbers) // [5, 7]
return .ok
}
}
```
Now when you post the form to `/users`, you should see the information printed in the console. Nice work!
## Encode Body
APIs encode `form-urlencoded` data much less often than they decode it. However, encoding is just as easy with Vapor. Using our same `User` struct from the previous example, here is how we can encode a `form-urlencoded`-encoded response.
```swift
router.get("multipart") { req -> User in
let res = req.makeResponse()
let user = User(name: "Vapor", age: 3, luckyNumbers: [5, 7])
res.content.encode(user, as: .urlEncodedForm)
return user
}
```
!!! tip
If you set a default `MediaType` on your `Content` types, then you can return them directly in the route closure.
## URL Query
URL-Encoded Forms are also useful for sending structured data in the URL query string. This is widely used for sending data via GET requests where HTTP bodies are not allowed.
Let's take a look at how we can decode some search parameters from the query string.
```http
GET /users?name=Vapor&age=3 HTTP/1.1
```
The first step (as always with [`Content`](https://api.vapor.codes/vapor/latest/Vapor/Protocols/Content.html)) is to create a `Codable` struct that represents the data structure.
```swift
import Vapor
struct UsersFilters: Content {
var name: String?
var age: Int?
}
```
Here we are making both `name` and `age` optional since the route can be called without any flags to return all users.
Now that we have a `Codable` struct, we can decode the URL query string. The process is almost identical to decoding content, expect we use `req.query` instead of `req.content`.
```swift
router.get("users") { req -> Future<[User]> in
let filters = try req.query.decode(UsersFilters.self)
print(filters.name) // Vapor
print(filters.age) // 3
return // fetch users with filters
}
```
!!! tip
Decoding the URL query string is not asynchronous because, unlike HTTP bodies, Vapor can be sure it is available when calling the route closure.

View File

@ -1,6 +1,6 @@
# Using Content
In Vapor 3, all content types (JSON, protobuf, URLEncodedForm, [Multipart](../multipart/getting-started.md), etc) are treated the same. All you need to parse and serialize content is a `Codable` class or struct.
In Vapor 3, all content types (JSON, protobuf, [URLEncodedForm](../url-encoded-form/getting-started.md), [Multipart](../multipart/getting-started.md), etc) are treated the same. All you need to parse and serialize content is a `Codable` class or struct.
For this introduction, we will use JSON as an example. But keep in mind the API is the same for any supported content type.

View File

@ -89,6 +89,9 @@ pages:
- 'Getting Started': 'template-kit/getting-started.md'
- 'Testing':
- 'Getting Started': 'testing/getting-started.md'
- 'URL-Encoded Form':
- 'Getting Started': 'url-encoded-form/getting-started.md'
- 'Overview': 'url-encoded-form/overview.md'
- 'Validation':
- 'Getting Started': 'validation/getting-started.md'
- 'Overview': 'validation/overview.md'