Here’s the POST request we pasted in the video.
request = """
POST /bears HTTP/1.1
Host: example.com
User-Agent: ExampleBrowser/1.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
name=Baloo&type=Brown
"""
response = Servy.Handler.handle(request)
IO.puts responseAnd here’s the starting point we used for the matching route function.
def route(%Conv{method: "POST", path: "/bears"} = conv) do
%{ conv | status: 201, resp_body: "Create a bear!" }
endMatching Heads and Tails in Elixir
Notes
No Match of Right-Hand Side Value?
When parsing the HTTP request, we split the string around two consecutive newline characters:
[top, params_string] = String.split(request, "\n\n")If you get a “no match of right-hand side value” error, it’s likely because your code editor is using \r\n as the end-of-line character rather than \n. Windows in particular uses \r\n as the default end-of-line character. If you’re using Visual Studio Code, you can click the button labeled “CRLF” in the status bar at the bottom right of the screen and then change it to “LF”.
Or if you want new files to automatically use \n as the end-of-line character, you can add the following setting to your settings.json file:
"files.eol": "\n",Guaranteeing Two Parts
For the purposes of this course, splitting the request string around two consecutive newline characters will always result in two parts: the top part and the params_string part. However, in a real-world application, the params_string itself might have double newlines. Specifically, POST/PUT data that is not just x-www-form-urlencoded (e.g. JSON, binary data, multi-part HTTP requests, etc.) could have two consecutive newline characters.
To guarantee that String.split/3 always returns two parts, you can pass the parts: 2 option like so:
[top, params_string] = String.split(request, "\n\n", parts: 2)Linking Heads and Tails
The familiar way to make a list is by separating each element by a comma:
iex> nums = [1, 2, 3]
[1, 2, 3]But now you know that a list is either empty or it consists of a head and a tail which is itself a list. It follows that you can create the same list using the [head | tail] expression:
iex> nums = [1 | [2, 3]]
[1, 2, 3]In the same way, you can add elements to the head of a list (prepend) using the [head | tail] expression:
iex> [0 | nums]
[0, 1, 2, 3]And if you wanted to take the long way around, you could create the list of numbers 0-3 as a series of heads and tails like so:
iex> [0 | [1 | [2 | [3 | []]]]]
[0, 1, 2, 3]This highlights that a list in Elixir is implemented as a series of linked lists. The head is always the first element of the list, while the tail “points” or “links” to the list that consists of the head and tail of the remaining elements. So lists are, by definition, recursive data structures!
Accessing Head and Tail with Functions
The head and tail of a list can also be accessed with the functions hd and tl:
iex> nums = [1, 2, 3]
iex> hd(nums)
1
iex> tl(nums)
[2, 3]The hd and tl functions are defined in the Kernel module which is automatically imported into every module, so you don’t have to prefix the function with the module name.
Code So Far
The code for this section is in the post-requests directory found within the video-code directory of the code bundle
Why always me?