There are many webservices that exist to make requests of other webservers. One example that we will see later is that of requesting distance information between locations using the Open Street Map services.
To request a webpage in Julia, we will use the HTTP
package, so add it to your system if you need to. For some basic http requests, we will use the webserver at http://httpbin.org
To get started, do
using HTTP
r = HTTP.request("GET", "http://httpbin.org/get")
and a request is sent to the webserver and the response is:
HTTP.Messages.Response:
"""
HTTP/1.1 200 OK
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Sun, 02 Dec 2018 14:53:29 GMT
Content-Type: application/json
Content-Length: 158
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur
{
"args": {},
"headers": {
"Connection": "close",
"Host": "httpbin.org"
},
"origin": "XXX.XXX.XXX.XXX",
"url": "http://httpbin.org/get"
}
"""
although you will get the IP address and the Date that you sent it from.
The fields that you get from the request is:
* status
: returns the status code from the server.
* body
: the response body as an array of UInt8
. If you wrap this is in a String
then you get the string version of the response.
*
for the above example,
* r.status
returns 200
* String(r.body)
returns:
"{\n \"args\": {}, \n \"headers\": {\n \"Connection\": \"close\", \n \"Host\": \"httpbin.org\"\n }, \n \"origin\": \"XXX.XXX.XXX.XXX\", \n \"url\": \"http://httpbin.org/get\"\n}\n"
which is a JSON object. We will parse this below.
* r.version
returns v"1.1.0"
which means that this was a HTTP1.1 response
* r.headers
returns:
8-element Array{Pair{SubString{String},SubString{String}},1}:
"Connection" => "keep-alive"
"Server" => "gunicorn/19.9.0"
"Date" => "Sun, 02 Dec 2018 14:53:29 GMT"
"Content-Type" => "application/json"
"Content-Length" => "158"
"Access-Control-Allow-Origin" => "*"
"Access-Control-Allow-Credentials" => "true"
"Via" => "1.1 vegur"
as an example. This is similar to a dictionary if you need to access the elements.
* r.request
returns
HTTP.Messages.Request:
"""
GET /get HTTP/1.1
Host: httpbin.org
Content-Length: 0
"""
The above example, showed that the response body can return a JSON object. This is a common response for webservices. Alternatively, we can return HTML or XML as other common responses.
If we have a response, we typically parse it use the JSON
package, so add this to your local system if you haven’t and then do using JSON
.
Accessing the body
field of the web response more than once is not allow (I can’t find documentation on this or why this is true. ), so you may need to rerun the request and the store the result for processing.
r = HTTP.request("GET", "http://httpbin.org/get")
body = string(r.body)
which should return the same result. Now, to parse the result as a JSON string:
body_obj = JSON.parse(body)
you get
Dict{String,Any} with 4 entries:
"headers" => Dict{String,Any}("Connection"=>"close","Host"=>"httpbin.org")
"args" => Dict{String,Any}()
"url" => "http://httpbin.org/get"
"origin" => "XXX.XXX.XXX.XXX"
And in Chapter 19, we saw how to access the elements of a dictionary as
body_obj["url"]
which returns http://httpbin.org/get
The Massachusetts Bay Transit Authority (MBTA) run public transit throughout the Boston Area. They post all transit alerts as a webservice and we can access it with Julia via:
req = HTTP.request("GET","https://api-v3.mbta.com/alerts")
Then to parse correctly,
body = String(req.body)
alerts_dict = JSON.parse(body)
all of the alerts are stored in an array in the data
alerts = alerts_dict["data"]
and for example, to drill down into a the first alert:
alerts[1]["attributes"]
and when this was run, the following was returned:
Dict{String,Any} with 15 entries:
"active_period" => Any[Dict{String,Any}("start"=>"2018-12-02T04:30:00-05:00…
"created_at" => "2018-11-28T16:45:52-05:00"
"service_effect" => "Lowell Line notice"
"short_header" => "On weekends, through Dec, Lowell service will be replac…
"cause" => "UNKNOWN_CAUSE"
"updated_at" => "2018-11-28T16:45:52-05:00"
"description" => "Inbound passengers will board a free bus shuttle that w…
"severity" => 7
"url" => nothing
"banner" => nothing
"informed_entity" => Any[Dict{String,Any}("activities"=>Any["BOARD", "EXIT", …
"timeframe" => nothing
"header" => "On weekends, through December, Lowell Line service in b…
"effect" => "SERVICE_CHANGE"
"lifecycle" => "NEW"
and for example, a phone app could take advantage of this information and post (in a more elegant fashion all of the relevant information).
If interested, here is more information on the API.
HTTP.jl
to make a simple webserver.This also has the ability to run a webservice or webserver. Consider the following:
HTTP.listen("127.0.0.1", 8081) do http
HTTP.setheader(http, "Content-Type" => "text/html")
write(http, "<h1>Hello! :) </h1>")
end
and if you go to a web browser and type in
localhost:8081
You should get a webpage that says Hello! :)