Pragmatism in the real world

Detecting OpenWhisk web actions

I’ve already written about OpenWhisk web actions and how they allow you to send a status code and HTTP headers to the client by returning a dictionary with the keys status, headers and body from your main() method:

func main(args: [String:Any]) -> [String:Any] {
    return [
        "body": "Hello world",
        "statusCode": 200,
        "headers": [
            "Content-Type": "text/xml",
        ],
    ]
}

If this test action is in the default namespace, then we create it with wsk action update test test.swift -a web-export true to enable web action support and access it via curl:

curl https://openwhisk.ng.bluemix.net/api/v1/experimental/web/19FT_dev/default/test.http

<root>Hello world</root>

However, when you invoke this via the authenticated POST API (eg. Via curl or wsk action invoke) you get this:

$ AUTH=$(wsk property get --auth | awk '{printf("%s", $3)}' | openssl base64 | tr -d "\n")
$ curl -X POST -H "Authorization: Basic $AUTH" \
"https://openwhisk.ng.bluemix.net/api/v1/namespaces/19FT_dev/actions/test?blocking=true&result=true"

{
  "body": "Hello world",
  "statusCode": 200,
  "headers": {
    "Content-Type": "text/xml"
  }
}

This could have been predicted as the authenticated POST API call just executes the action and sends back what it returned.

Additional arguments in a web action

When your action is called as a web action, then there are additional arguments, that don’t appear otherwise. We can simply look for one of these. Specifically, I chose to look for __ow_method.

The simple way of doing this:

func main(args: [String:Any]) -> [String:Any] {

    if args["__ow_method"] == nil {
        return ["root": "Hello world"]
    }
    return [
        "body": "Hello world",
        "statusCode": 200,
        "headers": [
            "Content-Type": "text/xml",
        ],
    ]
}

Note that we return a dictionary as an authenticated POST API call expects this. Calling internally via curl:

$ curl -X POST -H "Authorization: Basic $AUTH" \
"https://openwhisk.ng.bluemix.net/api/v1/namespaces/19FT_dev/actions/test?blocking=true&result=true"

{
  "root": "Hello world"
}

(We can only get JSON back this way)

and of course calling the web action hasn’t changed and we still get our XML.

We can call our function with whatever mechanism is appropriate and generate the right response.