blob: 6c1eaf172c6d90b4ae53d51a0152396438584e8d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements; and to You under the Apache License, Version 2.0.
'use strict'
const BaseOperation = require('./base_operation')
const messages = require('./messages')
const names = require('./names')
const CREATE_PARAMS = ['relpath', 'operation', 'action']
class Routes extends BaseOperation {
routeMgmtApiPath (path) {
return `web/whisk.system/apimgmt/${path}.http`
}
get (options) {
options = options || {}
options.basepath = this.basepath(options)
return this.list(this.qs(options, ['basepath']))
}
list (options) {
options = options || {}
if (this.hasBasepath(options)) {
options.basepath = this.calculateBasepath(options)
}
const qs = this.qs(options, ['relpath', 'basepath', 'operation', 'limit', 'skip'])
return this.client.request('GET', this.routeMgmtApiPath('getApi'), { qs })
}
qs (options, names) {
const result = super.qs(options, names)
if (this.hasAccessToken()) {
result.accesstoken = this.client.options.apigwToken
result.spaceguid = this.client.options.apigwSpaceGuid
}
return result
}
hasBasepath (options) {
return !!(options.name || options.basepath)
}
basepath (options) {
if (!this.hasBasepath(options)) {
throw new Error(messages.MISSING_BASEPATH_ERROR)
}
return this.calculateBasepath(options)
}
calculateBasepath (options) {
if (options.name && options.basepath) {
throw new Error(messages.INVALID_BASEPATH_ERROR)
}
return options.basepath || options.name
}
missingBasepath (options) {
return !(options.name || options.basepath)
}
delete (options) {
options = options || {}
options.basepath = this.basepath(options)
const qs = this.qs(options, ['relpath', 'basepath', 'operation'])
qs.force = true
return this.client.request('DELETE', this.routeMgmtApiPath('deleteApi'), { qs })
}
create (options) {
const body = this.createBody(options || {})
const qs = this.qs(options, ['responsetype'])
return this.client.request('POST', this.routeMgmtApiPath('createApi'), { body, qs })
}
createBody (options) {
if (options.swagger) {
return { apidoc: { namespace: '_', swagger: options.swagger } }
}
const missing = CREATE_PARAMS.filter(param => !(options || {}).hasOwnProperty(param))
if (missing.length) {
throw new Error(`Missing mandatory parameters: ${missing.join(', ')}`)
}
return this.routeSwaggerDefinition(options)
}
routeSwaggerDefinition (params) {
const apidoc = {
namespace: '_',
gatewayBasePath: this.routeBasepath(params),
gatewayPath: params.relpath,
gatewayMethod: params.operation,
id: `API:_:${this.routeBasepath(params)}`,
action: this.routeSwaggerAction(params)
}
const pathParameters = this.parsePathParameters(params.relpath)
if (pathParameters.length) {
apidoc.pathParameters = pathParameters.map(this.createPathParameter)
}
if (params.name) {
apidoc.apiName = params.name
}
return { apidoc }
}
routeSwaggerAction (params) {
const id = names.parseId(params.action)
let namespace = decodeURIComponent(this.namespace(params))
if (params.action.startsWith('/')) {
namespace = names.parseNamespace(params.action)
}
const body = {
name: id,
namespace: namespace,
backendMethod: `GET`,
backendUrl: this.actionUrlPath(id, namespace),
authkey: this.client.options.apiKey
}
if (params.secure_key) {
body.secureKey = params.secure_key
}
return body
}
routeBasepath (params) {
return params.basepath || '/'
}
actionUrlPath (id, namespace) {
// web action path must contain package identifier. uses default for
// non-explicit package.
if (!id.includes('/')) {
id = `default/${id}`
}
return this.client.pathUrl(`web/${namespace}/${id}.http`)
}
hasAccessToken () {
return !!this.client.options.apigwToken
}
// return list of path parameters from paths
// e.g. /book/{id}
// Multiple parameters are supported.
parsePathParameters (path) {
const regex = /{([^}]+)\}/g
const findAllParams = p => {
const ids = []
let id = regex.exec(p)
while (id) {
ids.push(id[1])
id = regex.exec(p)
}
return ids
}
return path.split('/')
.map(findAllParams)
.reduce((sum, el) => sum.concat(el), [])
}
createPathParameter (name) {
return {
name: name,
in: 'path',
description: `Default description for '${name}'`,
required: true,
type: 'string'
}
}
}
module.exports = Routes