| /* |
| * Copyright 2019 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* eslint-disable no-console */ |
| |
| /** Proxy renderer which uses an OpenWhisk action for |
| * rendering, if one matches the current request's |
| * resource type and extension. |
| */ |
| const openwhisk = require('openwhisk'); |
| |
| const getAnnotation = (act, key) => { |
| if(act != null) { |
| const annotation = act.annotations.find(ann => key == ann.key); |
| return annotation ? annotation.value : undefined; |
| } |
| } |
| |
| // If an action matches the specified resource type (*) |
| // and extension (*), return its info and the content-type |
| // that it provides (*). |
| // Items marked with (*) are defined by OpenWhisk annotations |
| // on the actions. |
| // A "sling:resourceType" annotation with value "*" matches all |
| // resource types. |
| const getActionInfo = async (resourceType, extension) => { |
| return new Promise(resolve => { |
| var ow = openwhisk(); |
| ow.actions.list() |
| .then(actions => { |
| const act = actions.find(act => { |
| const rtAnnotation = getAnnotation(act, 'sling:resourceType'); |
| return ('*' == rtAnnotation || resourceType == rtAnnotation) |
| && extension == getAnnotation(act, 'sling:extensions'); |
| }) |
| let result; |
| if(act) { |
| result = { |
| action: act, |
| contentType: getAnnotation(act, 'sling:contentType'), |
| }; |
| } |
| resolve(result); |
| }) |
| .catch(e => { |
| throw e; |
| }) |
| }) |
| }; |
| |
| const renderWithAction = (resource, actionInfo) => { |
| if(!actionInfo.action) { |
| throw Error("No Action provided, cannot render"); |
| } |
| const name = actionInfo.action.name; |
| const blocking = true, result = true |
| const params = { |
| resource: resource |
| } |
| var ow = openwhisk(); |
| return ow.actions.invoke({name, blocking, result, params}); |
| }; |
| |
| const renderer = { |
| getRendererInfo : async (resourceType, extension) => { |
| return getActionInfo(resourceType, extension); |
| }, |
| render : (resource, action) => { |
| return renderWithAction(resource, action); |
| }, |
| } |
| |
| // For testing as a standalone OpenWhisk action |
| // (requires installing the action with -a provide-api-key true) |
| // or from the command line |
| function main () { |
| return new Promise(async (resolve, reject) => { |
| const resource = { |
| title: 'cmdline title test', |
| body: 'cmdline body test', |
| } |
| try { |
| const actionInfo = await getActionInfo('microsling/somedoc', 'html'); |
| console.log(`actionInfo=${JSON.stringify(actionInfo, 2, null)}`); |
| const rendered = await renderWithAction(resource, actionInfo); |
| console.log(`rendered=${JSON.stringify(rendered, 2, null)}`); |
| resolve(rendered); |
| } catch(e) { |
| reject(e); |
| } |
| }); |
| } |
| |
| // From the command line, __OW_API_HOST and __OW_API_KEY environment |
| // variables must be set |
| if (require.main === module) { |
| main(); |
| } |
| |
| module.exports.openWhiskRenderer = renderer; |
| module.exports.main = main; |