Skip to content
This repository was archived by the owner on Jun 5, 2026. It is now read-only.

Commit 730161f

Browse files
committed
feat: ✨ Allow wildcard hostnames (#347)
1 parent eacf136 commit 730161f

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
"preversion": "yarn clean",
143143
"test": "yarn build-client && PERCY_TOKEN=abc mocha --forbid-only \"test/**/*.test.ts\" --exclude \"test/percy-agent-client/**/*.test.ts\" --exclude \"test/integration/**/*\"",
144144
"test-client": "karma start ./test/percy-agent-client/karma.conf.js",
145-
"test-integration": "yarn build-client && node ./bin/run exec -h localtest.me -- mocha test/integration/**/*.test.ts",
145+
"test-integration": "yarn build-client && node ./bin/run exec -h *.localtest.me -- mocha test/integration/**/*.test.ts",
146146
"test-snapshot-command": "./bin/run snapshot test/integration/test-static-site -b /dummy-base-url -i '(red-keep)' -c '\\.(html)$'",
147147
"version": "oclif-dev readme && git add README.md",
148148
"watch": "npm-watch"

src/services/response-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as os from 'os'
44
import * as path from 'path'
55
import * as puppeteer from 'puppeteer'
66
import { URL } from 'url'
7+
import domainMatch from '../utils/domain-match'
78
import Constants from './constants'
89
import PercyClientService from './percy-client-service'
910
import ResourceService from './resource-service'
@@ -28,8 +29,7 @@ export default class ResponseService extends PercyClientService {
2829
}
2930

3031
// Capture if the resourceUrl has a hostname in the allowedHostnames
31-
const parsedResourceUrl = new URL(resourceUrl)
32-
if (this.allowedHostnames.some((hostname) => parsedResourceUrl.hostname === hostname)) {
32+
if (this.allowedHostnames.some((hostname) => domainMatch(hostname, resourceUrl))) {
3333
return true
3434
}
3535

src/utils/domain-match.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { URL } from 'url'
2+
3+
function domainCheck(domain: string, host: string, isWild: boolean) {
4+
if (domain === host) {
5+
return true
6+
}
7+
8+
if (isWild && host) {
9+
const last = host.lastIndexOf(domain)
10+
return (last >= 0 && ((last + domain.length) === host.length))
11+
}
12+
13+
return false
14+
}
15+
16+
function pathCheck(pathprefix: string, pathname: string) {
17+
return pathname.indexOf(pathprefix) === 0
18+
}
19+
20+
export default function domainMatch(pattern: string, siteUrl: string) {
21+
if (pattern === '*') {
22+
return true
23+
} else if (!pattern) {
24+
return false
25+
}
26+
27+
const isWild = ((pattern.indexOf('*.') === 0) || (pattern.indexOf('*/') === 0))
28+
29+
// tslint:disable-next-line
30+
let slashed = pattern.split('/') // tslint wants this to be `const` even though it's mutated
31+
let domain = slashed.shift() as string
32+
33+
const pathprefix = `/${slashed.join('/')}`
34+
const parsedUrl = new URL(siteUrl)
35+
36+
if (isWild) {
37+
domain = domain.substr(2)
38+
}
39+
40+
return (domainCheck(domain, parsedUrl.hostname, isWild) && pathCheck(pathprefix, parsedUrl.pathname))
41+
}

0 commit comments

Comments
 (0)