fix(patches): extend internal URL rewrite to microsub, activitypub, and @rmdes posts
The localhost rewrite only covered endpoint-syndicate and endpoint-share. Add coverage for 4 more files that also self-fetch via the public URL: - @rmdes/indiekit-endpoint-microsub reader.js (2 fetch calls) - @rmdes/indiekit-endpoint-activitypub compose.js (2 fetch calls) - @rmdes/indiekit-endpoint-posts utils.js and endpoint.js Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
* Patch: rewrite micropub self-fetch URLs to localhost in endpoint-syndicate
|
||||
* and endpoint-share.
|
||||
* Patch: rewrite micropub/microsub self-fetch URLs to localhost.
|
||||
*
|
||||
* Same issue as endpoint-posts: behind a reverse proxy (nginx in a separate
|
||||
* FreeBSD jail), Node can't reach its own public HTTPS URL because port 443
|
||||
* only exists on the nginx jail.
|
||||
*
|
||||
* Rewrites fetch(application.micropubEndpoint, ...) to use
|
||||
* Behind a reverse proxy (nginx in a separate FreeBSD jail), Node can't
|
||||
* reach its own public HTTPS URL because port 443 only exists on the
|
||||
* nginx jail. Rewrites self-referential fetch URLs to use
|
||||
* http://localhost:<PORT> instead.
|
||||
*
|
||||
* Covers: endpoint-syndicate, endpoint-share, endpoint-microsub reader,
|
||||
* endpoint-activitypub compose, endpoint-posts utils, and the @rmdes
|
||||
* endpoint-posts endpoint.js copy.
|
||||
*/
|
||||
|
||||
import { access, readFile, writeFile } from "node:fs/promises";
|
||||
@@ -29,20 +30,136 @@ function _toInternalUrl(url) {
|
||||
}
|
||||
`;
|
||||
|
||||
// Each target defines one or more string replacements in a single file.
|
||||
// The helper block is inserted after the last import statement.
|
||||
const targets = [
|
||||
// --- endpoint-syndicate ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@indiekit/endpoint-syndicate/lib/controllers/syndicate.js",
|
||||
],
|
||||
oldSnippet: ` const micropubResponse = await fetch(application.micropubEndpoint, {`,
|
||||
newSnippet: ` const micropubResponse = await fetch(_toInternalUrl(application.micropubEndpoint), {`,
|
||||
replacements: [
|
||||
{
|
||||
old: ` const micropubResponse = await fetch(application.micropubEndpoint, {`,
|
||||
new: ` const micropubResponse = await fetch(_toInternalUrl(application.micropubEndpoint), {`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// --- endpoint-share ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@indiekit/endpoint-share/lib/controllers/share.js",
|
||||
],
|
||||
oldSnippet: ` const micropubResponse = await fetch(application.micropubEndpoint, {`,
|
||||
newSnippet: ` const micropubResponse = await fetch(_toInternalUrl(application.micropubEndpoint), {`,
|
||||
replacements: [
|
||||
{
|
||||
old: ` const micropubResponse = await fetch(application.micropubEndpoint, {`,
|
||||
new: ` const micropubResponse = await fetch(_toInternalUrl(application.micropubEndpoint), {`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// --- microsub reader: URL construction + 2 fetch calls ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@rmdes/indiekit-endpoint-microsub/lib/controllers/reader.js",
|
||||
],
|
||||
replacements: [
|
||||
// getSyndicationTargets: rewrite the built micropubUrl
|
||||
{
|
||||
old: ` const micropubUrl = micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href;
|
||||
|
||||
const configUrl = \`\${micropubUrl}?q=config\`;
|
||||
const configResponse = await fetch(configUrl, {`,
|
||||
new: ` const micropubUrl = _toInternalUrl(micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href);
|
||||
|
||||
const configUrl = \`\${micropubUrl}?q=config\`;
|
||||
const configResponse = await fetch(configUrl, {`,
|
||||
},
|
||||
// createPost: rewrite the built micropubUrl
|
||||
{
|
||||
old: ` const micropubUrl = micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href;`,
|
||||
new: ` const micropubUrl = _toInternalUrl(micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href);`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// --- activitypub compose: URL construction + 2 fetch calls ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@rmdes/indiekit-endpoint-activitypub/lib/controllers/compose.js",
|
||||
],
|
||||
replacements: [
|
||||
// getSyndicationTargets
|
||||
{
|
||||
old: ` const micropubUrl = micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href;
|
||||
|
||||
const configUrl = \`\${micropubUrl}?q=config\`;
|
||||
const configResponse = await fetch(configUrl, {`,
|
||||
new: ` const micropubUrl = _toInternalUrl(micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href);
|
||||
|
||||
const configUrl = \`\${micropubUrl}?q=config\`;
|
||||
const configResponse = await fetch(configUrl, {`,
|
||||
},
|
||||
// post handler: rewrite the built micropubUrl
|
||||
{
|
||||
old: ` const micropubUrl = micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href;`,
|
||||
new: ` const micropubUrl = _toInternalUrl(micropubEndpoint.startsWith("http")
|
||||
? micropubEndpoint
|
||||
: new URL(micropubEndpoint, application.url).href);`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// --- @rmdes endpoint-posts utils.js: URL built from micropubEndpoint ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@rmdes/indiekit-endpoint-posts/lib/utils.js",
|
||||
],
|
||||
replacements: [
|
||||
{
|
||||
old: ` const micropubUrl = new URL(micropubEndpoint);`,
|
||||
new: ` const micropubUrl = new URL(_toInternalUrl(micropubEndpoint));`,
|
||||
},
|
||||
],
|
||||
},
|
||||
// --- @rmdes endpoint-posts endpoint.js (separate copy from @indiekit override) ---
|
||||
{
|
||||
paths: [
|
||||
"node_modules/@rmdes/indiekit-endpoint-posts/lib/endpoint.js",
|
||||
],
|
||||
replacements: [
|
||||
{
|
||||
old: ` const endpointResponse = await fetch(url, {
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
authorization: \`Bearer \${accessToken}\`,
|
||||
},
|
||||
});`,
|
||||
new: ` const endpointResponse = await fetch(_toInternalUrl(url), {
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
authorization: \`Bearer \${accessToken}\`,
|
||||
},
|
||||
});`,
|
||||
},
|
||||
{
|
||||
old: ` const endpointResponse = await fetch(url, {
|
||||
method: "POST",`,
|
||||
new: ` const endpointResponse = await fetch(_toInternalUrl(url), {
|
||||
method: "POST",`,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -67,22 +184,23 @@ for (const target of targets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!source.includes(target.oldSnippet)) {
|
||||
console.warn(`[postinstall] micropub-fetch-internal-url: snippet not found in ${filePath} — skipping`);
|
||||
// Check that all old snippets exist before patching
|
||||
const allFound = target.replacements.every((r) => source.includes(r.old));
|
||||
if (!allFound) {
|
||||
const missing = target.replacements
|
||||
.filter((r) => !source.includes(r.old))
|
||||
.map((r) => r.old.slice(0, 60) + "...");
|
||||
console.warn(`[postinstall] micropub-fetch-internal-url: snippet not found in ${filePath} — skipping (${missing.length} missing)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Insert helper block after the last import statement.
|
||||
// Find the last "from" keyword followed by a string and semicolon,
|
||||
// which marks the end of the last import.
|
||||
const importEndPattern = /;\s*\n/g;
|
||||
// Insert helper block after the last import statement
|
||||
const allImportMatches = [...source.matchAll(/^import\s/gm)];
|
||||
if (allImportMatches.length === 0) {
|
||||
console.warn(`[postinstall] micropub-fetch-internal-url: no imports found in ${filePath} — skipping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the semicolon+newline that ends the last import block
|
||||
const lastImportStart = allImportMatches.at(-1).index;
|
||||
const afterLastImport = source.slice(lastImportStart);
|
||||
const fromMatch = afterLastImport.match(/from\s+["'][^"']+["']\s*;\s*\n/);
|
||||
@@ -97,8 +215,10 @@ for (const target of targets) {
|
||||
|
||||
let updated = beforeHelper + "\n" + helperBlock + "\n" + afterHelper;
|
||||
|
||||
// Now replace the fetch call
|
||||
updated = updated.replace(target.oldSnippet, target.newSnippet);
|
||||
// Apply all replacements
|
||||
for (const r of target.replacements) {
|
||||
updated = updated.replace(r.old, r.new);
|
||||
}
|
||||
|
||||
await writeFile(filePath, updated, "utf8");
|
||||
console.log(`[postinstall] Patched micropub-fetch-internal-url in ${filePath}`);
|
||||
|
||||
Reference in New Issue
Block a user