Mix.install([
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"},
{:tested_cell, github: "brooklinjazz/tested_cell"},
{:utils, path: "#{__DIR__}/../utils"},
{:httpoison, "~> 1.8"}
])
Ensure you type the ea
keyboard shortcut to evaluate all Elixir cells before starting. Alternatively, you can evaluate the Elixir cells as you read.
API stands for Application Programming Interface. In broad terms, an API is a way to communicate between pieces of software.
Generally, API refers to web APIs, which are programs that run on the internet. The internet is a network of interconnected machines that know how to communicate with each other.
We won't go deep into networking or how the internet works, as that is beyond the scope of this course. However, Crash Course Computer Science provides an excellent overview.
YouTube.new("https://www.youtube.com/watch?v=AEaKrq3SpW8")
These APIs use a client-server model. Servers provide a resource, and clients request a resource.
You use APIs every time you open your browser (Chrome, Safari, Firefox, Edge, etc.). The browser is the client, and it requests information from a server. For example, when you search for a video on YouTube, your browser communicates with YouTube servers to retrieve the video file.
The client uses a URL (Uniform Resource Locator) to locate the server on the internet.
For example, you can visit the URL https://v2.jokeapi.dev/joke/Any?safe-mode&format=json. This URL locates the server(s) powering the Joke API that returns a random joke.
The Joke API returns a JSON response. JSON (JavaScript Object Notation) is a key-value format conceptually similar to a map in Elixir.
{
"error": false,
"category": "Programming",
"type": "twopart",
"setup": "Why did the functional programmer get thrown out of school?",
"delivery": "Because he refused to take classes.",
"flags": {
"nsfw": false,
"religious": false,
"political": false,
"racist": false,
"sexist": false,
"explicit": false
},
"id": 48,
"safe": true,
"lang": "en"
}
A URL contains the following information
- The communication protocol:
https
- The domain name:
v2.jokeapi.dev
- Path (optional):
joke/Any
- Query parameters (optional):
?safe-mode&format=json
The communication protocol specifies how to communicate with the server. HTTP (Hypertext Transfer Protocol) and HTTPS (Hypertext Transfer Protocol Secure) are communication protocols used to send and receive data between the client and the server.
The domain name is a convenient label that maps to the underlying IP (Internet Protocol) address. For example, you can use http://142.250.217.68 instead of https://www.google.com to request the Google home page from a Google server.
The path specifies the resource we want from the server. In this case, we use the /joke/Any
path to get a random joke.
Query parameters contain additional options and information to send to the server. A URL may include many query parameters to send to the server. Query parameters start with a question mark ?
and are each split by an ampersand &
. For example, ?safe-mode&format-json
specifies that we want to use safe-mode and return the joke in a JSON format.
We use web APIs to communicate with servers on the internet. These APIs provide useful functionality that would otherwise be difficult to build on our own. Here are a few example APIs.
- The Stripe API handles Stripe payments.
- The OpenWeatherAPI provides live weather information.
- The JokeAPI returns a random joke.
We use HTTP to communicate with web APIs. The browser hides the details of how we use HTTP to communicate with these APIs. However, as developers, we want to interact with them directly using the HTTP protocol to request and send information.
In Elixir, we use an HTTP client to make HTTP requests. We've installed the popular HTTPoison HTTP client library for you in this livebook to demonstrate how to make HTTP requests.
With HTTPoison we can programmatically request information from the same Joke API you visited in the browser.
HTTPoison.get("https://v2.jokeapi.dev/joke/Any?safe-mode&format=json")
We use the HTTPoison.get/3 function to make a GET request. The response from the server includes the :body
, :headers
, :status_code
, and :request_url
.
The :body
is the JSON response you saw previously in the browser, and :headers
provide additional context and meta-data about the response. The :status_code
specifies the response's status, where 200
indicates a successful response. The :request_url
is simply the URL.
APIs use various response codes to communicate the status of a request. These are generally called response codes and are grouped into five classes.
- Informational responses (100–199)
- Successful responses (200–299)
- Redirection messages (300–399)
- Client error responses (400–499)
- Server error responses (500–599)
You've already seen that a successful request returns a 200
response. You might also be familiar with the 404
not found response code.
{:ok, response} = HTTPoison.get("https://v2.jokeapi.dev/joke/Any?safe-mode&format=json")
response.status_code
To parse a JSON response into a more convenient data structure, we can use the Poison library. Poison.decode!/2 converts the string representation of the JSON into an Elixir value.
Poison.decode!("{\"key\"\: \"value\"}")
By combining HTTPoison and Poison we can retrieve the JSON from the Joke API and return an Elixir map.
response =
case HTTPoison.get("https://v2.jokeapi.dev/joke/Any?safe-mode&format=json") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
Poison.decode!(body)
end
Now we could use this response in our program.
IO.puts("""
#{response["setup"]}
#{response["delivery"]}
""")
Use Poison.decode!/2 to decode the following json string.
string = "{\"hello\"\: \"world\"}"
HTTP GET requests retrieve data from a server and HTTP POST requests send data to a server.
We've already seen how we can use HTTPoison.get/3 to make an HTTP GET request. We can also use the HTTPoison.post/4 function to make an HTTP POST request.
POST requests include body and headers. The body contains the data to send to the server. The headers contain context and metadata about the body of data being sent, which is the data to send to the server. The POST request also includes headers which
contain context and metadata about the data. For example, the Content-Type
header tells the server the format of data being sent.
Below we send a POST request to http://httparrot.herokuapp.com/post. The body is a JSON string "{\"body\": \"test\"}"
and the
Content-Type
header specifies that the data being sent is JSON.
HTTPoison.post("http://httparrot.herokuapp.com/post", "{\"body\": \"test\"}", [
{"Content-Type", "application/json"}
])
So far, we've seen how to use HTTPoison and Poison to retrieve information from a public API. However, some APIs are private.
Private APIs require an API key to communicate with them. This key is then included in the HTTP request to authenticate the request.
For example, the Open Weather API requires an API key when making a GET request. The server returns a 401
unauthorized response without the correct API key.
api_key = ""
HTTPoison.get("https://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=#{api_key}")
Generally, you want to keep your API key a secret because bad actors could use it to maliciously access private information or attack the server with too many requests.
The Open Weather API exposes the following URL to provide weather data.
https://api.openweathermap.org/data/2.5/weather?lat=LATITUDE&lon=LONGITUDE&appid=API_KEY
lat
, lon
, and appid
are all query parameters, where we replace LATITUDE, LONGITUDE, and API_KEY with the correct values.
Create a free account on the Open Weather API and then get your API key from Open Weather API Keys page.
Use your API key and valid latitude/longitude coordinates to make a successful request to their API. Ensure the :status_code
is 200
rather than 401
.
lat = 35
lon = 139
api_key = ""
{:ok, response} =
HTTPoison.get(
"https://api.openweathermap.org/data/2.5/weather?lat=#{lat}&lon=#{lon}&appid=#{api_key}"
)
Once you are sure the above works correctly, use Poison.decode/2 to decode the response
into an Elixir map.
response
Run the following in your command line from the beta_curriculum folder to track and save your progress in a Git commit.
$ git add .
$ git commit -m "finish apis section"
Previous | Next |
---|---|
Home Page | Spoonacular Recipe API |