diff --git a/schemas/zzapi-bundle.schema.json b/schemas/zzapi-bundle.schema.json index d25fb36..4da2c41 100644 --- a/schemas/zzapi-bundle.schema.json +++ b/schemas/zzapi-bundle.schema.json @@ -51,9 +51,16 @@ } } }, + "pathParamObject": { + "type": "object", + "description": "A set of path parameters described as key/value pairs", + "properties": { + "": { "$ref": "#/$defs/scalar" } + } + }, "headerObject": { "type": "object", - "description": "A set ofheaders described as key/value pairs", + "description": "A set of headers described as key/value pairs", "properties": { "": { "$ref": "#/$defs/scalar" } } @@ -243,11 +250,17 @@ { "$ref": "#/$defs/headerObject" } ] }, + "pathParams": { + "description": "path parameters", + "anyOf": [ + { "$ref": "#/$defs/pathParamObject" } + ] + }, "params": { "description": "Query string parameters", "anyOf": [ { - "type": "array", + "type": "array", "items": { "$ref": "#/$defs/paramArray" } }, { "$ref": "#/$defs/paramObject" } diff --git a/src/executeRequest.ts b/src/executeRequest.ts index ce07cb9..de26ac4 100644 --- a/src/executeRequest.ts +++ b/src/executeRequest.ts @@ -5,11 +5,13 @@ import { getStringValueIfDefined } from "./utils/typeUtils"; import { GotRequest, Param, RequestSpec } from "./models"; export function constructGotRequest(allData: RequestSpec): GotRequest { - const completeUrl: string = getURL( + var completeUrl: string = getURL( allData.httpRequest.baseUrl, allData.httpRequest.url, getParamsForUrl(allData.httpRequest.params, allData.options.rawParams), + allData.httpRequest.pathParams ); + const options: OptionsOfTextResponseBody = { method: allData.httpRequest.method.toLowerCase() as Method, @@ -77,9 +79,48 @@ export function getParamsForUrl(params: Param[] | undefined, rawParams: boolean) return `?${paramString}`; } -export function getURL(baseUrl: string | undefined, url: string, paramsForUrl: string): string { +export function getURL(baseUrl: string | undefined, url: string, paramsForUrl: string, pathParams?: Param[]): string { // base url not defined, or url does not start with /, then ignore base url - if (!baseUrl || !url.startsWith("/")) return url + paramsForUrl; - // otherwise, incorporate base url - return baseUrl + url + paramsForUrl; + var completeUrl = "" + if (!baseUrl || !url.startsWith("/")){ + completeUrl = url + paramsForUrl; + }else{ + // otherwise, incorporate base url + completeUrl = baseUrl + url + paramsForUrl; + } + + if(/\/:\w+/.test(completeUrl) && pathParams){ + completeUrl = substitutePathParams(completeUrl,pathParams); + } + return completeUrl; +} + +function substitutePathParams(url: string,params: Param[]): string { + + const {baseUrl,path,query} = splitURL(url) + return baseUrl + path.replace(/:(\w+)/g, (_, key) => { + const param = params.find(p => p.name === key); + if (param) { + return param.value; + } + throw new Error(`Missing value for parameter: ${key}`); + }) + query; } + +function splitURL(url: string): { baseUrl: string; path: string; query: string } { + try { + // defaults to http if protocol not given + if (!/^\w+:\/\//.test(url)) { + url = "http://" + url; + } + const parsedUrl = new URL(url); + + return { + baseUrl: `${parsedUrl.protocol}//${parsedUrl.host}`, + path: parsedUrl.pathname, + query: parsedUrl.search + }; + } catch (error) { + throw new Error("Invalid URL"); + } +} \ No newline at end of file diff --git a/src/mergeData.ts b/src/mergeData.ts index 93d2e37..b11cf53 100644 --- a/src/mergeData.ts +++ b/src/mergeData.ts @@ -206,6 +206,7 @@ export function getMergedData(commonData: Common, requestData: RawRequest): Requ const method = requestData.method; const params = getMergedParams(commonData.params, requestData.params); + const pathParams = getMergedParams(commonData.pathParams,requestData.pathParams) const headers = getMergedHeaders(commonData.headers, requestData.headers); const body = requestData.body; const options = getMergedOptions(commonData.options, requestData.options); @@ -226,6 +227,7 @@ export function getMergedData(commonData: Common, requestData: RawRequest): Requ url: requestData.url, method, params, + pathParams, headers, body, }, diff --git a/src/models.ts b/src/models.ts index 0aaddb0..66da1e6 100644 --- a/src/models.ts +++ b/src/models.ts @@ -73,6 +73,7 @@ export interface Common { baseUrl?: string; headers: RawHeaders; params: RawParams; + pathParams: RawParams; options?: RawOptions; tests?: RawTests; } @@ -84,6 +85,7 @@ export interface RawRequest { method: Method; headers: RawHeaders; params: RawParams; + pathParams : RawParams; body?: string; options?: RawOptions; tests?: RawTests; @@ -98,6 +100,7 @@ export interface RequestSpec { baseUrl?: string; url: string; method: Method; + pathParams : Param[]; params: Param[]; headers: { [key: string]: string }; body?: any;