HTTP API Assistance

Hello,

I am trying to translate this Python3 script into Julia (https://github.com/Brightspace/bds-headless-client-example/blob/master/main.py) to gain more familiarity with Julia and building an application that relies on an API.

In particular, I am trying to understand the following function:

def trade_in_refresh_token(config):
    # https://tools.ietf.org/html/rfc6749#section-6
    response = requests.post(
        '{}/core/connect/token'.format(config['auth_service']),
        # Content-Type 'application/x-www-form-urlencoded'
        data={
            'grant_type': 'refresh_token',
            'refresh_token': config['refresh_token'],
            'scope': 'datahub:dataexports:*'
        },
        auth=HTTPBasicAuth(config['client_id'], config['client_secret'])
    )

    if response.status_code != 200:
        logger.error('Status code: %s; content: %s', response.status_code, response.text)
        response.raise_for_status()

    return response.json()

Does the HTTP (or any Julia) package have the ability to specify a Dictionary for the grant_type, refresh_token, and scope and has a similiar function to HTTPBasicAuth to parse in the client_id and client_secret?

I have executed the Python3 script without complications, but I have a limited understanding on HTTP post and response functions.

Is there any good documentation about how to make Julia work for the scenario?

Thanks!

Looking at the docs for HTTP.jl there is this example:

using JSON
params = Dict("user"=>"RAO...tjN", "token"=>"NzU...Wnp", "message"=>"Hello!")
base_url = "http://api.domain.com"
endpoint = "/1/messages.json"
url = base_url * endpoint
r = HTTP.request("POST", url,
             ["Content-Type" => "application/json"],
             JSON.json(params))
println(JSON.parse(String(r.body)))

The way HTTP works is that HTTP.request(“POST”, url, headers, body) needs the data here (grant type, refresh_token, and scope) passed in as a json string. Json and dictionaries are easy to convert between, so make a dictionary as in this example, and use JSON.json(dict) to turn it into a json string for the body of the request here.

The auth is a bit trickier, but still not too bad. The way HTTP Basic Authentication works can be done in a few steps:

  1. Combine the username and password into a string, separated by a “:”:
plaintext = config["client_id"] * ":" * config["client_secret"]
  1. Convert the string to the base64 encoding of it (and this seems clunky, there’s gotta be a better way):
io = IOBuffer();
iob64_encode = Base64EncodePipe(io);
write(iob64_encode, plaintext);
close(iob64_encode);
encoded = String(take!(io))

3: Prepend that string with "Basic " (note the space):

value = "Basic " * encoded

4: Write a header with the key as “Authorization” and the value as this new string “Basic dXNlcjpwYXNzd29yZA==” (the value here is your “value” above, but this example is the base64 encoding of the string “user:password”)

Updating the example above:

using JSON
params = Dict("user"=>"RAO...tjN", "token"=>"NzU...Wnp", "message"=>"Hello!")
base_url = "http://api.domain.com"
endpoint = "/1/messages.json"
url = base_url * endpoint
r = HTTP.request("POST", url,
            ["Authorization" => value],
             JSON.json(params))
println(JSON.parse(String(r.body)))

Now I haven’t tested this, so it might need some small modifications, but hopefully this helps!

To convert from or to a base64 encoded string, you can use the Base64 standard library. It contains a function base64encode.

1 Like