Kitura Logo

HTML Forms: Parsing URL Encoded Data

Create a Kitura Server

First we need a Kitura server to add our routes to. If you are working with an existing project you can skip this section.

Kitura has a command-line interface which provides us with utilities for quickly creating a Kitura server.

Once we've installed the Kitura command-line interface, open a terminal window and run the following:

1. Create a directory:

mkdir ~/HTMLForms

2. Change to the new directory:

cd ~/HTMLForms

Create the Kitura server:

kitura init

kitura init creates, builds and generates a starter Kitura Xcode project and will take a couple of minutes to complete. This includes best-practice implementations of health checking and monitoring as well as configuration files to allow easy deployment to a Docker container, a Kubernetes cluster, or the IBM Cloud.

Now we're ready create our HTML form!

Create the HTML Form

Webpages use HTML forms to take a user's input and send it as an HTTP request.

The form data can be sent via a HTTP GET request. In this case, the data gets appended to the url as a query string consisting of “key=value” pairs, separated by the “&” symbol.

An example of a HTML form GET request:

http://localhost.com/form?name=Andy&age=&isDeveloper=true

Using a GET request allows users to bookmark the result and is better for non-secure data.

The form data can also be sent via an HTTP POST request. In this case, the data is sent with the content-type header "application/x-www-form-urlencoded". This indicates that the body of the request is a query string.

The data from the example above sent as a POST request:

POST / HTTP/1.1
Host: http://localhost:8080/form
Content-Type: application/x-www-form-urlencoded
Content-Length: 31
name=Andy&age=&isDeveloper=true

Use POST whenever you are working with sensitive or personal information.

We will now create an HTML page containing get and post forms.

1. Create a public directory:

mkdir ~/HTMLForms/public

2. Move to your new directory:

cd ~/HTMLForms/public

3. Create an HTML file:

touch formwebpage.html

4. Open your HTML file:

open -a Xcode.app formwebpage.html

5. Copy in the following HTML:

<!DOCTYPE html>
<html>
<body>
<h2>URL Encoded Forms</h2>

<h4>Post to Codable route</h4>
<form action="codable" method="post" enctype="application/x-www-form-urlencoded" target="redirect">
    Name: <input type="text" name="name" required="required"><br>
    Age: <input type="number" name="age"><br>
    isDeveloper:<input type="checkbox" name="isDeveloper" value="true"><br>
    <input type="submit" value="Submit">
</form>

<h4>Get to Codable route</h4>
<form action="codable" method="get" enctype="application/x-www-form-urlencoded" target="redirect">
    Name: <input type="text" name="name" required="required"><br>
    Age: <input type="number" name="age"><br>
    isDeveloper:<input type="checkbox" name="isDeveloper" value="true"><br>
    <input type="submit" value="Submit">
</form>

<h4>Post to Raw route</h4>
<form action="raw" method="post" enctype="application/x-www-form-urlencoded" target="redirect">
    Name: <input type="text" name="name" required="required"><br>
    Age: <input type="number" name="age"><br>
    isDeveloper:<input type="checkbox" name="isDeveloper" value="true"><br>
    <input type="submit" value="Submit">
</form>

<h4>Get to Raw route</h4>
<form action="raw" method="get" enctype="application/x-www-form-urlencoded" target="redirect">
    Name: <input type="text" name="name" required="required"><br>
    Age: <input type="number" name="age"><br>
    isDeveloper:<input type="checkbox" name="isDeveloper" value="true"><br>
    <input type="submit" value="Submit">
</form>


<iframe name="redirect" style="display:none;"></iframe>
</body>
</html>

This HTML will make a simple page with four HTML forms. These forms contain:

Create a StaticFileServer

We will serve the HTML page using a StaticFileServer.

1. Open your Xcode project:

open ~/HTMLForms/HTMLForms.xcodeproj

2. Open Sources > Application > Application.swift

3. Inside the postInit function, add the static file server middleware:

router.get("/", middleware: StaticFileServer())

4. In the top left of Xcode is a toolbox icon. Click this and change the scheme from HTMLForms-Package to HTMLForms.

5. Run the server and go to: localhost:8080/formwebpage.html

You should see a simple HTML page with four HTML forms. These will send the input data to our server. Now we need to create the server routes that receive this data.

Create the Form Model

The Kitura server works directly with Swift value types, therefore we need to contruct a value type to use.

It's good practice to keep value types (in this case models) and logic separated. Create a new file, to contain the models, called Models.swift as follows:

For now, let's create a very simple model:

1. Open Models.swift

2. Copy in the following code:

import KituraContracts

struct Form: Codable, QueryParams {
    let name: String
    let age: Int?
    let isDeveloper: Bool?
}

This provides a simple representation of the data we will receive from our form. The struct conforms to Codable so it can be used in Codable routes and also conforms to QueryParams so it can be decoded from the query parameters on a GET request.

If the form's age or isDeveloper fields are empty, an empty value will be sent with the key (i.e "age=isDeveloper="). In this case, Kitura will decode age to nil and isDeveloper to false.

Now we have a model we can use, we can create our routes!

Setup the Codable Routes

We will now create a Codable route to receive the POST request from an HTML form.

1. Open Application.swift

2. Inside the postInit function, register the route handler:

router.post("/codable", handler: postFormHandler)

3. After the postInit function, add your postFormHandler function:

func postFormHandler(user: Form, respondWith: (Form?, RequestError?) -> Void) {
    print("Codable POST route: \(user.name)")
    if let age = user.age { print("is \(age) years old") }
    if(user.isDeveloper ?? false) { print("and they are a developer") }
    respondWith(user, nil)
}

4. Restart your server and go to localhost:8080/formwebpage.html. Send the "Post to Codable route" form and in the Xcode logger you should see our printed message with the form data.

We will now create a Codable route to receive the GET request from an HTML form.

5. Inside postInit, register the route handler:

router.get("/codable", handler: getFormHandler)

6. After the postInit function, add your getFormHandler function:

func getFormHandler(user: Form, respondWith: (Form?, RequestError?) -> Void) {
    print("Codable GET route: \(user.name)")
    if let age = user.age { print("is \(age) years old") }
    if(user.isDeveloper ?? false) { print("and they are a developer") }
    respondWith(user, nil)
}

7. Restart your server and go to localhost:8080/formwebpage.html. Send the "Get to Codable route" form and in the Xcode logger you should see our printed message with the form data.

Setup the Raw Routes

We will now create a Raw route to receive the POST request from an HTML form.

1. Inside postInit, register the Raw POST route:

router.post("/raw") { request, response, next in
    guard let user = try? request.read(as: Form.self)
    else {
        return try response.status(.unprocessableEntity).end()
    }
    print("Raw POST route: \(user.name)")
    if let age = user.age { print("is \(age) years old") }
    if(user.isDeveloper ?? false) { print("and they are a developer") }
    response.status(.created).send(json: user)
    next()
}

This will function the same as the Codable POST route above, to receive and parse the HTML form.

2. Restart your server and go to localhost:8080/formwebpage.html. Send the "POST to Raw route" form and in the Xcode logger you should see our printed message with the form data.

3. After the Raw POST route, register the Raw GET route:

router.get("/raw") { request, response, next in
    guard let user = request.getQueryParameters(as: Form.self)
    else {
        return try response.status(.unprocessableEntity).end()
    }
    print("Raw GET route: \(user.name)")
    if let age = user.age { print("is \(age) years old") }
    if(user.isDeveloper ?? false) { print("and they are a developer") }
    response.status(.created).send(json: user)
    next()
}

4. Restart your server and go to localhost:8080/formwebpage.html. Send the "GET to Raw route" form and in the Xcode logger you should see our printed message with the form data.

This will function the same as the Codable GET route above, to receive and parse the HTML form.

Congratulations!! You have just created and hosted an HTML forms webpage and set up a server to receive and parse these forms using four different methods!

Slack icon

NEED HELP?

MESSAGE US ON SLACK.