apache / openwhisk-runtime-java

Apache OpenWhisk Runtime Java supports Apache OpenWhisk functions written in Java and other JVM-hosted languages
https://openwhisk.apache.org/
Apache License 2.0
46 stars 63 forks source link

HTTP requests/responses not correctly parsed in expected format in webactions #111

Closed daviddenton closed 4 years ago

daviddenton commented 4 years ago

Given a WebAction call of:

https://localhost:31001/api/v1/web/guest/foo/testFunction/foo?aQuery=bob&aQuery2=bob

... the parsed JSON object extracts and passes the query parameters as fields on the root object and not in the __ow_query field (which was expected and would be consistent with other runtimes). So for the above request, the JSON object looks like:

{
   "__ow_method":"get",
   "__ow_headers":{
      "accept-encoding":"gzip",
      "host":"owdev-controller.default.svc.cluster.local:8080",
      "user-agent":"okhttp/4.7.2"
   },
   "__ow_path":"/foo",
   "value2":"bob",
   "value":"bill"
}

Is this expected behaviour? Additionally, even with the above, neither header or queries would cope with multiple parameters with the same name - for this it seems like the format of those blocks should be along the lines of:

{
    "__ow_method": "get",
    "__ow_headers": {
        "accept-encoding": "gzip",
        "host": "owdev-controller.default.svc.cluster.local:8080",
        "user-agent": "okhttp/4.7.2"
    },
    "__ow_path": "/foo",
    "__ow_query": {
        "value2": [
            "bob"
        ],
        "value": [
            "bill"
        ]
    }
}

Additionally, the response code of an HTTP action is hardcoded to 200 in the Proxy.java. I'm not sure if this is required by OpenWhisk or is something that could be fixed in the case that an HTTP response object was returned by the underlying action.

rabbah commented 4 years ago

Hi @daviddenton - a web action by default promotes all query and body parameters to first class properties in the event that triggers the function. This is described here https://github.com/apache/openwhisk/blob/master/docs/webactions.md#http-context and is language/runtime independent.

For this sample function which you can run in the Nimbella Playground for OpenWhisk

import com.google.gson.JsonObject;

public class Main {
    public static JsonObject main(JsonObject args) {
        JsonObject response = new JsonObject();
        response.add("body", args);
        response.addProperty("statusCode", "201");
        return response;
    }
}

The result is what you posted first:

{
  "__ow_headers": { ... },
  "__ow_method": "get",
  "__ow_path": "",
  "aQuery": "bob",
  "aQuery2": "bob"
}

Note that to return an explicit status code, also as described in the docs, you must specify the value for statusCode in your response.

> curl https://apigcp.nimbella.io/api/v1/web/playground/user687283/x -v
 HTTP/1.1 201 Created
< Server: nginx/1.14.2
< Date: Tue, 30 Jun 2020 16:21:20 GMT
...

To retrieve the query string explicitly, you need to set the web action to use "raw" http handlers which will pass the query string to the function. You can do this by passing --web raw to the cli when you create/update the action.

> curl 'https://apigcp.nimbella.io/api/v1/web/rodricgm-h4nvfnjgdgg/default/j?aQuery=bob&aQuery2=bob'
{
  "__ow_body": "",
  "__ow_headers": {
   ...
  },
  "__ow_method": "get",
  "__ow_path": "",
  "__ow_query": "aQuery=bob&aQuery2=bob"

The query string is reconstructed from the URI and the function must parse it (for which there are libraries available).

rabbah commented 4 years ago

neither header or queries would cope with multiple parameters with the same name

Multiple query string parameters with the same name is generally not supported - this is not something openwhisk itself can fix. Last time I looked at this, it was ambiguous if this was permitted or excluded explicitly by the RFC although my recollection is vague and the akka http server library used by OpenWhisk dedups the properties in the query string.

There is a precedence order for handling overlaps between query parameters, body parameters and action parameters which is described in the same document I linked above.

Web actions otherwise receive query and body parameters as first class properties
in the action arguments with body parameters taking precedence over query parameters, 
which in turn take precedence over action and package parameters.
daviddenton commented 4 years ago

Thanks for your quick (and thorough!) responses. And apologies for not spotting those in the docs. Will get it working now then close this issue. :)