Make knative init/run logic more granular/efficient based upon type of request (#245)

* Make knative init/run logic more granular/efficient

* Make knative init/run logic more granular/efficient
diff --git a/knative-build/runtimes/javascript/platform/knative.js b/knative-build/runtimes/javascript/platform/knative.js
index d3013cd..6cf8620 100644
--- a/knative-build/runtimes/javascript/platform/knative.js
+++ b/knative-build/runtimes/javascript/platform/knative.js
@@ -61,44 +61,21 @@
     return false;
 }
 
-/**
- * Determine if runtime is a "stem" cell, i.e., can be initialized with request init. data
- * @param env
- * @returns {boolean}
- */
-function isStemCell(env) {
-    let actionCode = env.__OW_ACTION_CODE;
-    // It is a stem cell if valid code is "built into" the runtime's process environment.
-    return (typeof actionCode === 'undefined' || actionCode.length === 0);
-}
 
 /**
- * Determine if the request (body) contains valid activation data.
- * @param req
- * @returns {boolean}
+ * Remove all INIT data from the value data that will be passed to the user function.
+ * @param body
  */
-function hasActivationData(req) {
-    // it is a valid activation if the body contains an activation and value keys with data.
-    if (typeof req.body !== "undefined" &&
-        typeof req.body.activation !== "undefined" &&
-        typeof req.body.value !== "undefined") {
-        return true;
-    }
-    return false;
-}
+function removeInitData(body) {
 
-/**
- * Determine if the request (body) contains valid init data.
- * @param req
- * @returns {boolean}
- */
-function hasInitData(req) {
-    // it is a valid init. if the body contains an init key with data.
-    if (typeof req.body !== "undefined" &&
-        typeof req.body.init !== "undefined") {
-        return true;
+    DEBUG.dumpObject(body,"body");
+    if (typeof body !== "undefined" &&
+        typeof body.value !== "undefined") {
+        delete body.value.code;
+        delete body.value.main;
+        delete body.value.binary;
+        delete body.value.raw;
     }
-    return false;
 }
 
 /**
@@ -207,23 +184,46 @@
 }
 
 /**
- * Pre-process HTTP request details, send them as parameters to the action input argument
- * __ow_method, __ow_headers, __ow_path, __ow_user, __ow_body, and __ow_query
+ * Pre-process HTTP request information and make it available as parameter data to the action function
+ * by moving it to where the route handlers expect it to be (i.e., in the JSON value data map).
+ *
+ * See: https://github.com/apache/incubator-openwhisk/blob/master/docs/webactions.md#http-context
+ *
+ * HTTP Context
+ * ============
+ * All web actions, when invoked, receives additional HTTP request details as parameters to the action
+ * input argument. These include:
+ *
+ * __ow_method (type: string): the HTTP method of the request.
+ * __ow_headers (type: map string to string): the request headers.
+ * __ow_path (type: string): the unmatched path of the request (matching stops after consuming the action extension).
+ * __ow_user (type: string): the namespace identifying the OpenWhisk authenticated subject.
+ * __ow_body (type: string): the request body entity, as a base64 encoded string when content is
+ *      binary or JSON object/array, or plain string otherwise.
+ * __ow_query (type: string): the query parameters from the request as an unparsed string.
+ *
+ * TODO:
+ * A request may not override any of the named __ow_ parameters above; doing so will result in a
+ * failed request with status equal to 400 Bad Request.
  */
 function preProcessHTTPContext(req, valueData) {
     DEBUG.functionStart();
     try {
         if (valueData.raw) {
+            // __ow_body is a base64 encoded string when content is binary or JSON object/array,
+            // or plain string otherwise.
             if (typeof req.body.value === "string" && req.body.value !== undefined) {
                 valueData.__ow_body = req.body.value;
             } else {
-                const body = Object.assign({}, req.body.value);
+                // make value data available as __ow_body
+                const tmpBody = Object.assign({}, req.body.value);
                 // delete main, binary, raw, and code from the body before sending it as an action argument
-                delete body.main;
-                delete body.code;
-                delete body.binary;
-                delete body.raw;
-                var bodyStr = JSON.stringify(body);
+                delete tmpBody.main;
+                delete tmpBody.code;
+                delete tmpBody.binary;
+                delete tmpBody.raw;
+                var bodyStr = JSON.stringify(tmpBody);
+                // note: we produce an empty map if there are no query parms/
                 valueData.__ow_body = Buffer.from(bodyStr).toString("base64");;
             }
             valueData.__ow_query = req.query;
@@ -261,17 +261,18 @@
         let activationData = body.activation || {};
         let env = process.env || {};
 
-        // process initialization (i.e., "init") data
-        preProcessInitData(env, initData, valueData, activationData);
-
-        preProcessHTTPContext(req, valueData);
-
         // Fix up pointers in case we had to allocate new maps
         req.body = body;
         req.body.value = valueData;
         req.body.init = initData;
         req.body.activation = activationData;
 
+        // process initialization (i.e., "init") data
+        preProcessInitData(env, initData, valueData, activationData);
+
+        // process HTTP request header and body to make it available to function as parameter data
+        preProcessHTTPContext(req, valueData);
+
         // process per-activation (i.e, "run") data
         preProcessActivationData(env, activationData);
 
@@ -415,6 +416,8 @@
                 preProcessRequest(req);
 
                 service.initCode(req).then(function () {
+                    // delete any INIT data (e.g., code, raw, etc.) from the 'value' data before calling run().
+                    removeInitData(req.body);
                     service.runCode(req).then(function (result) {
                         postProcessResponse(req, result, res)
                     });