Skip to content

Commit

Permalink
Support for specifying getRedirectedUrl
Browse files Browse the repository at this point in the history
  • Loading branch information
PRO-2684 committed Apr 17, 2024
1 parent a2a50ad commit 594c3a6
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 24 deletions.
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ new Purlfy({
redirected: Number, // Number of URLs redirected (`redirect` mode)
char: Number, // Number of characters deleted
},
log: Function, // Log function (default: `console.log.bind(console, "\x1b[38;2;220;20;60m[pURLfy]\x1b[0m")`)
log: Function, // Log function (default is using `console.log` for output)
getRedirectedUrl: async Function, // Function to get redirected URL (default is using `fetch` for `HEAD` request, refer to [redirect mode](#-redirect-mode-redirect) for more details)
})
```

Expand Down Expand Up @@ -287,16 +288,12 @@ If you'd like to learn more about the syntax of the "replacement string", please
| --- | --- | --- |
| `continue` | `Boolean` | `true` |

Under Redirect mode, pURLfy will:

1. Attempt to fire a `HEAD` request to the matched URL.
2. If the status code is `3xx`, the `Location` header will be used as the new URL.
3. If `continue` is not set to `false`, purify the new URL again.
Under Redirect mode, pURLfy will call passed-in parameter `getRedirectedUrl` to get the redirected URL. The `getRedirectedUrl` should be an async function, accept a single `string` parameter `url`, and return a new `string` representing the redirected URL. The default implementation is to fire a `HEAD` request to the matched URL and return the `Location` header. If `continue` is not set to `false`, the new URL will be purified again.

#### 🔵 Lambda Mode `lambda`

> [!CAUTION]
> For security reasons, the `lambda` mode is disabled by default. Refer to the [API documentation](#-API) for enabling it.
> For security reasons, the `lambda` mode is disabled by default. If you **trust the rules provider**, refer to the [API documentation](#-API) for enabling it.
| Param | Type | Default |
| --- | --- | --- |
Expand Down
13 changes: 5 additions & 8 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ new Purlfy({
redirected: Number, // 重定向的网址数量 (`redirect` 模式)
char: Number, // 移除的字符数量
},
log: Function, // 日志函数 (默认: `console.log.bind(console, "\x1b[38;2;220;20;60m[pURLfy]\x1b[0m")`)
log: Function, // 日志函数 (默认通过 `console.log` 输出)
getRedirectedUrl: async Function, // 获取重定向后的 URL 的函数 (默认使用 `fetch` 发送 `HEAD` 请求,详见 [重定向模式](#-重定向模式-redirect))
})
```

Expand Down Expand Up @@ -281,22 +282,18 @@ new Purlfy({
#### 🟡 重定向模式 `redirect`

> [!CAUTION]
> 出于兼容性考虑,此模式默认禁用。若您想要启用此模式并且 **执行环境支持跨域**请参照 [API 文档](#-API) 开启此模式。
> 出于兼容性考虑,此模式默认禁用。请参照 [API 文档](#-API) 开启此模式。
| 参数 | 类型 | 默认值 |
| --- | --- | --- |
| `continue` | `Boolean` | `true` |

重定向模式下,pURLfy 会:

1. 向匹配到的网址发起 `HEAD` 请求
2. 若返回的状态码为 `3xx`,则会将头部信息中的 `Location` 作为新的 URL
3.`continue` 未被设置为 `false`,则再次净化新的 URL
重定向模式下,pURLfy 会调用传入参数 `getRedirectedUrl` 来获取重定向后的 URL。`getRedirectedUrl` 应为一个异步函数,接受一个类型为 `string` 的参数 `url`,并返回一个新的 `string` 类型的 URL 作为重定向后的 URL。默认情况下,pURLfy 会使用 `fetch` 发送 `HEAD` 请求来获取重定向后的 URL。若 `continue` 未被设置为 `false`,则再次净化新的 URL。

#### 🔵 匿名函数模式 `lambda`

> [!CAUTION]
> 出于安全考虑,此模式默认禁用。若您想要启用此模式并且 **信任规则来源**,请参照 [API 文档](#-API) 开启此模式。
> 出于安全考虑,此模式默认禁用。若您 **信任规则来源**,请参照 [API 文档](#-API) 开启此模式。
| 参数 | 类型 | 默认值 |
| --- | --- | --- |
Expand Down
28 changes: 19 additions & 9 deletions purlfy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ class Purlfy extends EventTarget {
lambdaEnabled = false;
maxIterations = 5;
#log = console.log.bind(console, "\x1b[38;2;220;20;60m[pURLfy]\x1b[0m");
#getRedirectedUrl = async url => {
const r = await fetch(url, {
method: "HEAD",
redirect: "manual"
});
if ((r.status === 301 || r.status === 302) && r.headers.has("location")) {
const dest = r.headers.get("location");
return dest;
}
return null;
};
#paramDecoders = {
"url": decodeURIComponent,
"base64": s => decodeURIComponent(escape(atob(s.replaceAll('_', '/').replaceAll('-', '+')))),
Expand All @@ -26,6 +37,7 @@ class Purlfy extends EventTarget {
this.maxIterations = options?.maxIterations ?? this.maxIterations;
Object.assign(this.#statistics, options?.statistics);
this.#log = options?.log ?? this.#log;
this.#getRedirectedUrl = options?.getRedirectedUrl ?? this.#getRedirectedUrl;
}

clearStatistics() {
Expand Down Expand Up @@ -203,21 +215,19 @@ class Purlfy extends EventTarget {
logFunc("Redirect mode is disabled.");
break;
}
let r = null;
let dest = null;
try {
r = await fetch(urlObj.href, {
method: "HEAD",
redirect: "manual"
});
dest = await this.#getRedirectedUrl(urlObj.href);
} catch (e) {
logFunc("Error fetching URL:", e);
logFunc("Error following redirect:", e);
break;
}
if ((r.status === 301 || r.status === 302) && r.headers.has("location")) {
let dest = r.headers.get("location");
urlObj = new URL(dest);
if (dest && URL.canParse(dest, urlObj.href)) {
urlObj = new URL(dest, urlObj.href);
shallContinue = rule.continue ?? true;
increment.redirected++;
} else {
logFunc("Invalid redirect destination:", dest);
}
break;
}
Expand Down

0 comments on commit 594c3a6

Please sign in to comment.