Skip to content

Python requests inspired Brightscript Network Library for Roku

License

Notifications You must be signed in to change notification settings

rokucommunity/roku-requests

Repository files navigation

roku-requests

Simple, python requests inspired Brightscript requests framework for Roku apps

build status monthly downloads npm version license Slack

Installation

Using ropm

ropm install roku-requests

Manually

Copy src/source/Requests.brs into your project as source/Requests.brs folder

Usage

Make a Request

Making a request with Requests is very simple.

Brightscript Debugger> r = Requests().get("https://api.github.com/events")

Now, we have a Response object called r. We can get all the information we need from this object.

Brightscript Debugger> ?r.ok
Brightscript Debugger> true
Brightscript Debugger> ?r.statuscode
Brightscript Debugger>  200

Requests’ simple API means that all forms of HTTP request are as obvious. For example, this is how you make an HTTP POST request:

Brightscript Debugger> r = Requests().post("https://httpbin.org/post", {"data":"value"})

What about the other HTTP request types: PUT, DELETE, HEAD and OPTIONS? These are all supported and simple by using the .request(VERB... method:

Brightscript Debugger> r = Requests().request("PUT", "https://httpbin.org/put", {"key":"value"})
Brightscript Debugger> r = Requests().request("DELETE", "https://httpbin.org/delete", {})
Brightscript Debugger> r = Requests().request("HEAD", "https://httpbin.org/get", {})
Brightscript Debugger> r = Requests().request("OPTIONS", "https://httpbin.org/get", {})

Passing Parameters In URLs

Brightscript Debugger> payload = {"key1": "value1", "key2": "value2"}
Brightscript Debugger> r = Requests().get("https://httpbin.org/get", {"params":payload})

You can see that the URL has been correctly encoded by printing the URL:

Brightscript Debugger> ?r.url
Brightscript Debugger> https://httpbin.org/get?key1=value1&key2=value2

Response Content

We can read the content of the server’s response. Consider the GitHub timeline again:

Brightscript Debugger> r = Requests().get("https://api.github.com/events")`
Brightscript Debugger> ?r.text
Brightscript Debugger> [{"id":"8575373301","type":"WatchEvent","actor":{"id":4537355,"login":"...

JSON Response Content

There’s also a builtin JSON encoder/decoder, in case you’re dealing with JSON data:

Brightscript Debugger> r = Requests().get("https://api.github.com/events")
Brightscript Debugger> ?r.json
Brightscript Debugger> <Component: roArray> =
[
    <Component: roAssociativeArray>
    <Component: roAssociativeArray>
    ...
]

You also also pass flags for json parsing. parseJsonFlags is passed to the ParseJson() function.

Brightscript Debugger> r = Requests().get("https://api.github.com/events", {parseJsonFlags:"i"})
Brightscript Debugger> ?r.json

Or disable json parsing

Brightscript Debugger> r = Requests().get("https://api.github.com/events", {parseJson:false})
Brightscript Debugger> ?r.json

Custom Headers

If you’d like to add HTTP headers to a request, simply pass in an AA to the headers key in the args dictionary.

Brightscript Debugger> url =
Brightscript Debugger> headers = {"user-agent": "my-app/0.0.1"}
Brightscript Debugger> r = Requests().get(url, {"headers":headers})

More complicated POST requests

Instead of encoding the AA yourself, you can also pass it directly using the json parameter

Brightscript Debugger> url = "https://httpbin.org/post"
Brightscript Debugger> payload = {"some": "data"}
Brightscript Debugger> r = Requests().post(url, {"json":payload})

Using the json parameter in the request will change the Content-Type in the header to application/json.

Response Status Codes

Brightscript Debugger> r = Requests().get("https://httpbin.org/get")
Brightscript Debugger> ?r.statuscode
Brightscript Debugger>  200

Response Headers

We can view the server’s response headers using an AA:

Brightscript Debugger> ?r.headers
Brightscript Debugger> <Component: roAssociativeArray> =
{
    access-control-allow-credentials: "true"
    access-control-allow-origin: "*"
    connection: "keep-alive"
    content-length: "272"
    content-type: "application/json"
    date: "Mon, 12 Nov 2018 17:25:53 GMT"
    server: "gunicorn/19.9.0"
    via: "1.1 vegur"
}

Timeouts

You can tell Requests to stop waiting for a response after a given number of seconds with the timeout parameter (int).

Brightscript Debugger> r = Requests().get("https://httpbin.org/delay/10", {"timeout":1})
Brightscript Debugger> <Component: roAssociativeArray> =
{
    cachehit: false
    ok: false
    timestried: 1
    url: "https://httpbin.org/delay/10"
}

Caching

You can tell Requests to use cache (on by default) by passing the useCache parameter (boolean). This will automatically cache the request if there are cache-control headers in the response.

Brightscript Debugger> r = Requests().get("https://httpbin.org/cache/60", {"useCache":true})

You can see if the cache was hit by checking the cacheHit value on the Response object.

Brightscript Debugger> r = Requests().get("https://httpbin.org/cache/60", {"useCache":true})
Brightscript Debugger> ?r.cachehit
Brightscript Debugger> false
Brightscript Debugger> r = Requests().get("https://httpbin.org/cache/60", {"useCache":true})
Brightscript Debugger> ?r.cachehit
Brightscript Debugger> true

If the server does not return cache-control headers or you want to manually specify the time to cache a request just pass the cacheSeconds parameter (int) to Requests.

Brightscript Debugger> r = Requests().get("https://httpbin.org/get", {"useCache":true, "cacheSeconds":300})

Notes about Cache implementation

Roku's Cachefs:

  • The cache implementation uses Roku's cachefs (https://sdkdocs.roku.com/display/sdkdoc/File+System)
  • cachefs is available as a Beta feature starting in Roku OS 8.
  • cachefs exists across channel launches but will evict data when more space is required for another Channel.

Cache Keys and Storage Location

  • Requests uses an MD5 hash of the URL + Request Headers being passed as the cache key
  • Requests stores the cached request as a file in cachefs:/{MD5_HASH}. Please be aware of this if your channel is storing things in the cachefs:/ space as there is a very minute possiibility of name collisions.
  • The cache data is stored as a file with the first line as a unix epoch of the time the file was written (time the first request was made). Subsequient requests read the file and compute/compare timestamps to determine if the cached file is still valid or not.

Development

Roku Requests is an independent open-source project, maintained exclusively by volunteers.

You might want to help! Get in touch via the slack group, or raise issues.