From 7d2fb87258ddd92996e23dec29ce18bf6831f015 Mon Sep 17 00:00:00 2001 From: tanner0101 Date: Mon, 16 Apr 2018 17:35:00 -0400 Subject: [PATCH] add url-encoded form docs --- 3.0/docs/url-encoded-form/getting-started.md | 42 +++++++ 3.0/docs/url-encoded-form/overview.md | 126 +++++++++++++++++++ 3.0/docs/vapor/content.md | 2 +- 3.0/mkdocs.yml | 3 + 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 3.0/docs/url-encoded-form/getting-started.md create mode 100644 3.0/docs/url-encoded-form/overview.md diff --git a/3.0/docs/url-encoded-form/getting-started.md b/3.0/docs/url-encoded-form/getting-started.md new file mode 100644 index 00000000..9c98833b --- /dev/null +++ b/3.0/docs/url-encoded-form/getting-started.md @@ -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. + diff --git a/3.0/docs/url-encoded-form/overview.md b/3.0/docs/url-encoded-form/overview.md new file mode 100644 index 00000000..e2ad8bfc --- /dev/null +++ b/3.0/docs/url-encoded-form/overview.md @@ -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 +
+ + + + +
+``` + +Since we are not specifying a special `enctype` attribute on the `
`, 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 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. + + + diff --git a/3.0/docs/vapor/content.md b/3.0/docs/vapor/content.md index 2feb3a20..9fb21928 100644 --- a/3.0/docs/vapor/content.md +++ b/3.0/docs/vapor/content.md @@ -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. diff --git a/3.0/mkdocs.yml b/3.0/mkdocs.yml index 8f5afa1b..220dc797 100644 --- a/3.0/mkdocs.yml +++ b/3.0/mkdocs.yml @@ -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'