Fix code quality violations for publish
Progressive breadcrumb resolution with caching, fix double headers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
171
node_modules/@jqhtml/ssr/src/http-intercept.js
generated
vendored
Normal file
171
node_modules/@jqhtml/ssr/src/http-intercept.js
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* JQHTML SSR HTTP Interception
|
||||
*
|
||||
* Intercepts fetch() and XMLHttpRequest to rewrite relative URLs
|
||||
* using the configured baseUrl.
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
|
||||
/**
|
||||
* Resolve a URL relative to a base URL
|
||||
* @param {string} url - URL to resolve (may be relative)
|
||||
* @param {string} baseUrl - Base URL (e.g., "https://example.com")
|
||||
* @returns {string} Absolute URL
|
||||
*/
|
||||
function resolveUrl(url, baseUrl) {
|
||||
// Already absolute with protocol
|
||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||
return url;
|
||||
}
|
||||
|
||||
// Protocol-relative (//cdn.example.com/...)
|
||||
if (url.startsWith('//')) {
|
||||
const baseProtocol = new URL(baseUrl).protocol;
|
||||
return baseProtocol + url;
|
||||
}
|
||||
|
||||
// Absolute path (/api/users)
|
||||
if (url.startsWith('/')) {
|
||||
const base = new URL(baseUrl);
|
||||
return `${base.protocol}//${base.host}${url}`;
|
||||
}
|
||||
|
||||
// Relative path (api/users)
|
||||
const base = new URL(baseUrl);
|
||||
const basePath = base.pathname.endsWith('/') ? base.pathname : base.pathname + '/';
|
||||
return `${base.protocol}//${base.host}${basePath}${url}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fetch function that rewrites URLs
|
||||
* @param {string} baseUrl - Base URL for relative URL resolution
|
||||
* @returns {function} Configured fetch function
|
||||
*/
|
||||
function createFetch(baseUrl) {
|
||||
// Use native fetch if available (Node 18+), otherwise use a simple implementation
|
||||
const nativeFetch = globalThis.fetch;
|
||||
|
||||
if (nativeFetch) {
|
||||
return async function ssrFetch(url, options = {}) {
|
||||
const resolvedUrl = resolveUrl(String(url), baseUrl);
|
||||
|
||||
// Remove any auth-related headers for SSR (SEO mode)
|
||||
const safeHeaders = { ...(options.headers || {}) };
|
||||
delete safeHeaders['Authorization'];
|
||||
delete safeHeaders['authorization'];
|
||||
delete safeHeaders['Cookie'];
|
||||
delete safeHeaders['cookie'];
|
||||
|
||||
return nativeFetch(resolvedUrl, {
|
||||
...options,
|
||||
headers: safeHeaders
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback for older Node versions - basic fetch implementation
|
||||
return function ssrFetch(url, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const resolvedUrl = resolveUrl(String(url), baseUrl);
|
||||
const parsedUrl = new URL(resolvedUrl);
|
||||
const isHttps = parsedUrl.protocol === 'https:';
|
||||
const lib = isHttps ? https : http;
|
||||
|
||||
const requestOptions = {
|
||||
hostname: parsedUrl.hostname,
|
||||
port: parsedUrl.port || (isHttps ? 443 : 80),
|
||||
path: parsedUrl.pathname + parsedUrl.search,
|
||||
method: options.method || 'GET',
|
||||
headers: options.headers || {}
|
||||
};
|
||||
|
||||
// Remove auth headers
|
||||
delete requestOptions.headers['Authorization'];
|
||||
delete requestOptions.headers['authorization'];
|
||||
delete requestOptions.headers['Cookie'];
|
||||
delete requestOptions.headers['cookie'];
|
||||
|
||||
const req = lib.request(requestOptions, (res) => {
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
resolve({
|
||||
ok: res.statusCode >= 200 && res.statusCode < 300,
|
||||
status: res.statusCode,
|
||||
statusText: res.statusMessage,
|
||||
headers: new Map(Object.entries(res.headers)),
|
||||
text: () => Promise.resolve(data),
|
||||
json: () => Promise.resolve(JSON.parse(data))
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
|
||||
if (options.body) {
|
||||
req.write(options.body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an XMLHttpRequest class that rewrites URLs
|
||||
* This is needed for jQuery $.ajax compatibility
|
||||
* @param {string} baseUrl - Base URL for relative URL resolution
|
||||
* @param {function} OriginalXHR - Original XMLHttpRequest constructor from jsdom
|
||||
* @returns {function} Wrapped XMLHttpRequest constructor
|
||||
*/
|
||||
function createXHRWrapper(baseUrl, OriginalXHR) {
|
||||
return class SSR_XMLHttpRequest extends OriginalXHR {
|
||||
open(method, url, async = true, user, password) {
|
||||
const resolvedUrl = resolveUrl(String(url), baseUrl);
|
||||
return super.open(method, resolvedUrl, async, user, password);
|
||||
}
|
||||
|
||||
setRequestHeader(name, value) {
|
||||
// Block auth headers for SSR
|
||||
const lowerName = name.toLowerCase();
|
||||
if (lowerName === 'authorization' || lowerName === 'cookie') {
|
||||
return;
|
||||
}
|
||||
return super.setRequestHeader(name, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Install HTTP interception on a jsdom window
|
||||
* @param {Window} window - jsdom window object
|
||||
* @param {string} baseUrl - Base URL for URL resolution
|
||||
*/
|
||||
function installHttpIntercept(window, baseUrl) {
|
||||
// Override fetch
|
||||
window.fetch = createFetch(baseUrl);
|
||||
|
||||
// Also set on global for code that accesses global.fetch
|
||||
if (typeof global !== 'undefined') {
|
||||
global.fetch = window.fetch;
|
||||
}
|
||||
|
||||
// Override XMLHttpRequest if it exists
|
||||
if (window.XMLHttpRequest) {
|
||||
const WrappedXHR = createXHRWrapper(baseUrl, window.XMLHttpRequest);
|
||||
window.XMLHttpRequest = WrappedXHR;
|
||||
|
||||
if (typeof global !== 'undefined') {
|
||||
global.XMLHttpRequest = WrappedXHR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveUrl,
|
||||
createFetch,
|
||||
createXHRWrapper,
|
||||
installHttpIntercept
|
||||
};
|
||||
Reference in New Issue
Block a user