OpenWhisk web actions

The first way that you learn to call your OpenWhisk action over HTTP is a POST request that is authenticated using your API key. This key allows all sorts of write access to your account, so you never release it.

If you want to access the action over HTTP without the API key, you have two choices: Web Actions or API Gateway.

This article discusses how to use Web Actions as they are more useful today.

Enabling Web Actions

Web Actions are provide an endpoint to your action. The format of the URL is:

The fully qualified name for your action can be found using wsk action list. For my ping action, this is /19FT_dev/P1/ping.

Note that if your action is in the default package, e.g. it's name is /19FT_dev/hello, then you need to use /19FT_dev/default/hello.

The type is one of: http, json, text

Enable access

To enable an action for web access, you need to annotate the action with the web-export key. This is done using the --annotation switch to ask action update:

That's all that we need to do, so we can now test it:

Calling via Curl

Success! As we used the .json extension, OpenWhisk automatically set the status code to 200, sent our returned dictionary as JSON and set the correct Content-Type header. What about if we need to change the status code though?

Sending data to the client

To set your own status code and HTTP headers, you need to use the .http extension on the URL and change the data array that you return from your action.

To recap from my previous post, our action currently looks like this:

ping.swift

In this action we simply return a dictionary of the data we want to appear as JSON in the body. To use the http web action type, we return a dictionary with three keys: code, headers and body:

code

Number of the HTTP status code e.g. 200.
headers

Dictionary of HTTP headers to send. The key is the header's name and the value is the header's value.
body

HTTP body as a string. The format depends on the Content-Type header that you have set. If the format is a binary one, then the string must be base64 encoded. OpenWhisk uses Spray, so consult their list to find out which are considered binary and which are text.

Most importantly, note that JSON content types are considered binary by Spray!

Let's change our action to send XML:

ping.swift

(Don't forget to update your action whenever you change it using wsk action update)

As the XML content types are considered text, we can just set the string containing our XML for the body element of our dictionary.

Let's test it:

Note, that if you the Accept header doesn't contain the content type that is set in your headers, then the Web Action controller will send an error back to the client.

JSON

For application/json, we have to convert our dictionary to a JSON string and then base64 encode it. OpenWhisk's Swift environment includes SwiftyJSON, so this isn't too hard:

ping.swift

OpenWhisk's Swift envionment includes the WhiskJsonUtils class that has some useful JSON related methods. In our case, we use the dictionaryToJsonString() method to create the JSON string from our dictionary. We then convert this to a base64 encoded string using the Foundation Data class's base64EncodedString() method.

Proving that it works:

Reading headers

We've talked about sending data from our action to the HTTP client, but what about receiving data from the client? This information is provided to you in the args parameter that is passed to your main() method. You can inspect args with this code:

env.swift:

Run it as POST request, with a very simple JSON payload:

As you can see, our body data ({"foo": "bar}) is just an element in the args dictionary. However, OpenWhisk has also given us some __ow_* properties with useful information. __ow_meta_verb tells us the METHOD of the HTTP message that the client sent and __ow_meta_headers contains the HTTP headers. Note that the keys are normalised to lower case.

Armed with this knowledge, it's possible to ensure that your action works with the HTTP method(s) that you want it to and by reading the headers, you can implement things like authentication via the Authorization header or read the Accept header to ensure you return data in the right format.

Fin

That's it. OpenWhisk Web Actions provide a very easy way to create HTTP endpoints that can be called by clients via the GET, PUT, POST or DELETE methods without needing your API key.

In comparison to API Gateway, you have less control over the name of the URL, but in exchange you are able to set the HTTP status code and custom headers, which isn't possible in API Gateway today. Over time, I expect API Gateway to gain more features, but until it supports the ability to set the status code, I recommend Web Actions.

Leave a Reply

Your email address will not be published. Required fields are marked *