Make WebFinger respect host-meta

This commit is contained in:
Laura Hausmann 2023-09-05 21:57:30 +02:00
parent 84867f1c13
commit 85f396ff49
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
5 changed files with 91 additions and 11 deletions

11
.pnp.cjs generated
View file

@ -3274,7 +3274,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\ ],\
[\ [\
"fast-xml-parser",\ "fast-xml-parser",\
"npm:3.21.1"\ "npm:4.2.7"\
],\ ],\
[\ [\
"fastest-levenshtein",\ "fastest-levenshtein",\
@ -15259,6 +15259,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["escape-regexp", "npm:0.0.1"],\ ["escape-regexp", "npm:0.0.1"],\
["eslint", "npm:8.45.0"],\ ["eslint", "npm:8.45.0"],\
["execa", "npm:6.1.0"],\ ["execa", "npm:6.1.0"],\
["fast-xml-parser", "npm:4.2.7"],\
["feed", "npm:4.2.2"],\ ["feed", "npm:4.2.2"],\
["file-type", "npm:17.1.6"],\ ["file-type", "npm:17.1.6"],\
["fluent-ffmpeg", "npm:2.1.2"],\ ["fluent-ffmpeg", "npm:2.1.2"],\
@ -20798,6 +20799,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["strnum", "npm:1.0.5"]\ ["strnum", "npm:1.0.5"]\
],\ ],\
"linkType": "HARD"\ "linkType": "HARD"\
}],\
["npm:4.2.7", {\
"packageLocation": "./.yarn/cache/fast-xml-parser-npm-4.2.7-c57a954c1f-d8b0c9e047.zip/node_modules/fast-xml-parser/",\
"packageDependencies": [\
["fast-xml-parser", "npm:4.2.7"],\
["strnum", "npm:1.0.5"]\
],\
"linkType": "HARD"\
}]\ }]\
]],\ ]],\
["fastest-levenshtein", [\ ["fastest-levenshtein", [\

BIN
.yarn/cache/fast-xml-parser-npm-4.2.7-c57a954c1f-d8b0c9e047.zip (Stored with Git LFS) vendored Normal file

Binary file not shown.

View file

@ -64,6 +64,7 @@
"decompress": "^4.2.1", "decompress": "^4.2.1",
"deep-email-validator": "0.1.21", "deep-email-validator": "0.1.21",
"escape-regexp": "0.0.1", "escape-regexp": "0.0.1",
"fast-xml-parser": "^4.2.7",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "17.1.6", "file-type": "17.1.6",
"fluent-ffmpeg": "2.1.2", "fluent-ffmpeg": "2.1.2",

View file

@ -1,6 +1,8 @@
import { URL } from "node:url"; import { URL } from "node:url";
import { getJson } from "@/misc/fetch.js"; import {getJson, getResponse} from "@/misc/fetch.js";
import { query as urlQuery } from "@/prelude/url.js"; import { query as urlQuery } from "@/prelude/url.js";
import config from "@/config/index.js";
import { XMLParser } from "fast-xml-parser";
type ILink = { type ILink = {
href: string; href: string;
@ -13,7 +15,9 @@ type IWebFinger = {
}; };
export default async function (query: string): Promise<IWebFinger> { export default async function (query: string): Promise<IWebFinger> {
const url = genUrl(query); const hostMetaUrl = queryToHostMetaUrl(query);
const webFingerTemplate = await hostMetaToWebFingerTemplate(hostMetaUrl) ?? queryToWebFingerTemplate(query);
const url = genWebFingerUrl(query, webFingerTemplate);
return (await getJson( return (await getJson(
url, url,
@ -21,20 +25,71 @@ export default async function (query: string): Promise<IWebFinger> {
)) as IWebFinger; )) as IWebFinger;
} }
function genUrl(query: string) { async function hostMetaToWebFingerTemplate(url: string) {
try {
const res = await getResponse({
url,
method: "GET",
headers: Object.assign(
{
"User-Agent": config.userAgent,
Accept: "application/xml, text/xml, */*",
},
{},
),
timeout: 10000,
});
const parser = new XMLParser({ignoreAttributes: false});
const hostMeta = parser.parse(await res.text());
const template = hostMeta['XRD']['Link']['@_template'];
return template.indexOf('{uri}') < 0 ? null : template;
}
catch {
return null;
}
}
function queryToWebFingerTemplate(query: string) {
if (query.match(/^https?:\/\//)) { if (query.match(/^https?:\/\//)) {
const u = new URL(query); const u = new URL(query);
return `${u.protocol}//${u.hostname}/.well-known/webfinger?${urlQuery({ return `${u.protocol}//${u.hostname}/.well-known/webfinger?resource={uri}`;
resource: query,
})}`;
} }
const m = query.match(/^([^@]+)@(.*)/); const m = query.match(/^([^@]+)@(.*)/);
if (m) { if (m) {
const hostname = m[2]; const hostname = m[2];
return `https://${hostname}/.well-known/webfinger?${urlQuery({ return `https://${hostname}/.well-known/webfinger?resource={uri}`;
resource: `acct:${query}`, }
})}`;
throw new Error(`Invalid query (${query})`);
}
function queryToHostMetaUrl(query: string) {
if (query.match(/^https?:\/\//)) {
const u = new URL(query);
return `${u.protocol}//${u.hostname}/.well-known/host-meta`;
}
const m = query.match(/^([^@]+)@(.*)/);
if (m) {
const hostname = m[2];
return `https://${hostname}/.well-known/host-meta`;
}
throw new Error(`Invalid query (${query})`);
}
function genWebFingerUrl(query: string, webFingerTemplate: string) {
if (webFingerTemplate.indexOf('{uri}') < 0)
throw new Error(`Invalid webFingerUrl: ${webFingerTemplate}`);
if (query.match(/^https?:\/\//)) {
return webFingerTemplate.replace('{uri}', encodeURIComponent(query));
}
const m = query.match(/^([^@]+)@(.*)/);
if (m) {
return webFingerTemplate.replace('{uri}', encodeURIComponent(`acct:${query}`));
} }
throw new Error(`Invalid query (${query})`); throw new Error(`Invalid query (${query})`);

View file

@ -5917,6 +5917,7 @@ __metadata:
escape-regexp: 0.0.1 escape-regexp: 0.0.1
eslint: ^8.44.0 eslint: ^8.44.0
execa: 6.1.0 execa: 6.1.0
fast-xml-parser: ^4.2.7
feed: 4.2.2 feed: 4.2.2
file-type: 17.1.6 file-type: 17.1.6
fluent-ffmpeg: 2.1.2 fluent-ffmpeg: 2.1.2
@ -10363,6 +10364,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"fast-xml-parser@npm:^4.2.7":
version: 4.2.7
resolution: "fast-xml-parser@npm:4.2.7"
dependencies:
strnum: ^1.0.5
bin:
fxparser: src/cli/cli.js
checksum: d8b0c9e04756f6c43fa0399428f30149acadae21350e42e26e8fe98e24e6afa6b9b00aa554453795036b00e9fee974a1b556fe2ba18be391d51a9bf1ab790e7c
languageName: node
linkType: hard
"fastest-levenshtein@npm:^1.0.12": "fastest-levenshtein@npm:^1.0.12":
version: 1.0.16 version: 1.0.16
resolution: "fastest-levenshtein@npm:1.0.16" resolution: "fastest-levenshtein@npm:1.0.16"
@ -20888,7 +20900,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"strnum@npm:^1.0.4": "strnum@npm:^1.0.4, strnum@npm:^1.0.5":
version: 1.0.5 version: 1.0.5
resolution: "strnum@npm:1.0.5" resolution: "strnum@npm:1.0.5"
checksum: 651b2031db5da1bf4a77fdd2f116a8ac8055157c5420f5569f64879133825915ad461513e7202a16d7fec63c54fd822410d0962f8ca12385c4334891b9ae6dd2 checksum: 651b2031db5da1bf4a77fdd2f116a8ac8055157c5420f5569f64879133825915ad461513e7202a16d7fec63c54fd822410d0962f8ca12385c4334891b9ae6dd2