Skip to content

Commit

Permalink
fix: mock issue resolve for similar templated requests (stoplightio#2564
Browse files Browse the repository at this point in the history
)
  • Loading branch information
SB-akshaythakar committed Jul 19, 2024
1 parent 68e4f35 commit b8e9fd8
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@stoplight/json": "^3.18.1",
"@stoplight/json-schema-ref-parser": "9.2.7",
"@stoplight/prism-core": "^5.8.0",
"@stoplight/prism-http": "^5.8.2",
"@stoplight/prism-http": "^5.8.3",
"@stoplight/prism-http-server": "^5.8.2",
"@stoplight/types": "^14.1.0",
"chalk": "^4.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/http-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"dependencies": {
"@stoplight/prism-core": "^5.8.0",
"@stoplight/prism-http": "^5.8.2",
"@stoplight/prism-http": "^5.8.3",
"@stoplight/types": "^14.1.0",
"fast-xml-parser": "^4.2.0",
"fp-ts": "^2.11.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/http/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stoplight/prism-http",
"version": "5.8.2",
"version": "5.8.3",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": "Stoplight <support@stoplight.io>",
Expand Down
4 changes: 2 additions & 2 deletions packages/http/src/router/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ describe('http router', () => {
);
});

test('given a concrete servers and templated paths should match first resource', () => {
test('given a concrete servers and templated paths should match second resource', () => {
const templatedPathA = '/{x}/y';
const templatedPathB = '/a/{z}';
const url = 'concrete.com';
Expand All @@ -334,7 +334,7 @@ describe('http router', () => {
},
},
}),
resource => expect(resource).toBe(firstResource)
resource => expect(resource).toBe(secondResource)
);
});

Expand Down
31 changes: 29 additions & 2 deletions packages/http/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IPrismComponents } from '@stoplight/prism-core';
import { IHttpOperation, IServer } from '@stoplight/types';
import * as E from 'fp-ts/Either';
import * as A from 'fp-ts/Array';
import * as O from 'fp-ts/Ord';
import { pipe } from 'fp-ts/function';
import { IHttpConfig, IHttpRequest, ProblemJsonError } from '../types';
import {
Expand All @@ -14,16 +15,42 @@ import {
import { matchBaseUrl } from './matchBaseUrl';
import { matchPath } from './matchPath';
import { IMatch, MatchType } from './types';
import { isTemplated } from './matchPath';

// matching score is calcualated for resources based upon their match with given request
// matchScore is introduced to sort the resources in case we get multiple matches for given request.
const calculateMatchScore = (endpoint: string, request: string) => {
const endpointParts = endpoint.split('/');
const requestParts = request.split('/');
let score = 0;
for (let i = 0; i < endpointParts.length; i++) {
if (endpointParts[i] === requestParts[i]) {
score++;
} else if (isTemplated(endpointParts[i])) {
score += 0.5;
} else {
break;
}
}
return score;
};


//sort endpoints based on match score
const sortEndpointsByMatch = (endpoints:IHttpOperation[], request: string) => {
return A.sort(O.contramap((endpoint: IHttpOperation) => calculateMatchScore(endpoint.path, request))(O.ordNumber))(endpoints).reverse();
};

const route: IPrismComponents<IHttpOperation, IHttpRequest, unknown, IHttpConfig>['route'] = ({ resources, input }) => {
const { path: requestPath, baseUrl: requestBaseUrl } = input.url;
const sortedResources = sortEndpointsByMatch(resources, requestPath);

if (!requestPath.startsWith('/')) {
return E.left(new Error(`The request path '${requestPath}' must start with a slash.`));
}

return pipe(
resources,
sortedResources,
E.fromPredicate(A.isNonEmpty, () =>
ProblemJsonError.fromTemplate(
NO_RESOURCE_PROVIDED_ERROR,
Expand Down Expand Up @@ -101,7 +128,7 @@ const route: IPrismComponents<IHttpOperation, IHttpRequest, unknown, IHttpConfig
}

if (requestBaseUrl) {
if (resources.every(resource => !resource.servers || resource.servers.length === 0)) {
if (sortedResources.every(resource => !resource.servers || resource.servers.length === 0)) {
return E.left(
ProblemJsonError.fromTemplate(
NO_SERVER_CONFIGURATION_PROVIDED_ERROR,
Expand Down
2 changes: 1 addition & 1 deletion packages/http/src/router/matchPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function fragmentize(path: string): string[] {
return path.split('/').slice(1).map(decodePathFragment);
}

function isTemplated(pathFragment: string) {
export function isTemplated(pathFragment: string) {
return /{(.+)}/.test(pathFragment);
}

Expand Down

0 comments on commit b8e9fd8

Please sign in to comment.