Skip to content

Commit

Permalink
[NT] Normalise paths before proxying. (#2068)
Browse files Browse the repository at this point in the history
## Description, Motivation and Context

Due to various layers of proxying, sometimes a proxied request ends up
with multiple leading slashes. Some web servers do not not normalise
request paths, leading to 404's.

This PR normalises the received request path on the mock server before
matching against contract paths, and normalises the received request
paths when proxying the request.

## Checklist:

- [x] I've added/updated tests to cover my changes
- [x] I've created an issue associated with this PR
  • Loading branch information
timdawborn authored Oct 9, 2023
1 parent 478d1a8 commit 996cef8
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
21 changes: 20 additions & 1 deletion lib/src/mock-server/matcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isRequestForEndpoint } from "./matcher";
import { isRequestForEndpoint, normalisePath } from "./matcher";

const BASE_ENDPOINT = {
name: "my-endpoint",
Expand Down Expand Up @@ -160,4 +160,23 @@ describe("Matcher", () => {
).toBeFalsy();
});
});

describe("normalisePath", () => {
it("Performs a no-op with no slashes", () => {
expect(normalisePath("")).toBe("");
expect(normalisePath("chicken little")).toBe("chicken little");
});

it("Normalises more than one slash at various positions within the string", () => {
expect(normalisePath("//foo/bar")).toBe("/foo/bar");
expect(normalisePath("////foo/bar")).toBe("/foo/bar");
expect(normalisePath("/foo/////bar")).toBe("/foo/bar");
expect(normalisePath("/foo/bar//")).toBe("/foo/bar/");
});

it("Normalises more than one slash at multiple positions within the string", () => {
expect(normalisePath("//foo//bar")).toBe("/foo/bar");
expect(normalisePath("////foo////bar")).toBe("/foo/bar");
});
});
});
14 changes: 12 additions & 2 deletions lib/src/mock-server/matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export function isRequestForEndpoint(
pathPrefix: string,
endpoint: Endpoint
): boolean {
if (req.path.substr(0, pathPrefix.length) !== pathPrefix) {
const requestPath = normalisePath(req.path);
if (requestPath.substr(0, pathPrefix.length) !== pathPrefix) {
return false;
}
if (req.method.toUpperCase() !== endpoint.method) {
Expand All @@ -24,5 +25,14 @@ export function isRequestForEndpoint(
const regexp = new RegExp(
"^" + endpoint.path.replace(/:\w+/g, "[^/]+") + "$"
);
return regexp.test(req.path.substr(pathPrefix.length));
return regexp.test(requestPath.substr(pathPrefix.length));
}

/**
* Normalises a given HTTP request path, by replacing all instances of two or more "/" in a row with a singular "/".
*
* @param path The path to normalise
*/
export function normalisePath(path: string): string {
return path.replace(/[/]{2,}/g, "/");
}
3 changes: 2 additions & 1 deletion lib/src/mock-server/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Request, Response } from "express";
import http from "http";
import https from "https";
import { ProxyConfig } from "./server";
import { normalisePath } from "./matcher";

export function proxyRequest({
incomingRequest,
Expand All @@ -23,7 +24,7 @@ export function proxyRequest({
? 443
: 80
: proxyConfig.port,
path: proxyConfig.path + incomingRequest.path,
path: normalisePath(proxyConfig.path + incomingRequest.path),
headers: {
...incomingRequest.headers,
host: proxyConfig.host
Expand Down

0 comments on commit 996cef8

Please sign in to comment.