Prev Next

Request and Response Example

To save you the trouble of typing it, here’s the request we used in the video.

Request

request = """
GET /wildthings HTTP/1.1
Host: example.com
User-Agent: ExampleBrowser/1.0
Accept: _/_
 
"""

Expected Response

expected_response = """
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 20
 
Bears, Lions, Tigers
"""

High-Level Transformations

Finally, here are the three high-level transformations we used as a starting point.

### 1. Parse the Request
 
def parse(request) do
 
# TODO: Parse the request string into a map:
 
conv = %{ method: "GET", path: "/wildthings", resp_body: "" }
end`
 
### 2. Route the Request
 
`def route(conv) do
 
# TODO: Create a new map that also has the response body:
 
conv = %{ method: "GET", path: "/wildthings", resp_body: "Bears, Lions, Tigers" }
end`
 
### 3. Format the Response
 
def format_response(conv) do
 
# TODO: Use values in the map to create an HTTP response string:
 
"""
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 20
 
Bears, Lions, Tigers
"""
end

High-Level Transformations in Elixir

Notes

Pipelines As Outlines

At this point, we have an outline for our program expressed as a pipeline of functions:

request
|> parse
|> route
|> format_response

The program doesn’t do anything interesting yet since the functions simply return hard-coded data. But we like to start this way as it helps us think through the program as a series of data transformations. And it just so happens it’s also a to-do list! We’ll implement each of the functions in subsequent modules.

Nested Function Calls

In the video, we started by sequencing the three transformation functions in a traditional style using intermediate variables:

def handle(request) do
  conv = parse(request)
  conv = route(conv)
  format_response(conv)
end

You could condense this a bit and remove the temporary variables by nesting the function calls like so:

format_response(route(parse(request)))

But this is difficult to read as the functions resolve from the inside out.

Using the Pipe Operator

The pipe operator (|>) lets us unwind these nested calls by chaining the functions together in a more readable style:

request
|> parse
|> route
|> format_response

It transforms the request by piping the result of each function into the next function. Here’s a fun fact: At compile time, this code is transformed to the nested call version.

A Piping Analogy

If you’ve ever piped multiple commands together in the Unix operating system, then Elixir’s pipe operator will be familiar. If not, think of it like the game where one person whispers a story to another person, who whispers it to the next person, and so on until the last

Code So Far

The code for this section is in the parse directory found within the video-code directory of the code bundle

Prev Next