This repository has been archived on 2025-11-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
api/app/gravatar/[...path]/route.ts
2025-03-25 21:47:40 +08:00

121 lines
3.6 KiB
TypeScript

import { type NextRequest, NextResponse } from "next/server"
// Replace with your mirror site's domain
const upstream = "gravatar.com"
// If it's a mobile-specific site, otherwise keep it the same as upstream
const upstream_mobile = "gravatar.com"
// Countries you wish to block from accessing
const blocked_region: string[] = []
// IP addresses you wish to block from accessing
const blocked_ip_address: string[] = []
// Replace the domains in the text response
const replace_dict: Record<string, string> = {
$upstream: "$custom_domain",
"//gravatar.com": "",
}
export async function GET(request: NextRequest, { params }: { params: { path: string[] } }) {
const url = new URL(request.url)
const url_host = url.host
const user_agent = request.headers.get("user-agent") || ""
// Determine if it's a mobile device
const is_desktop = await device_status(user_agent)
const upstream_domain = is_desktop ? upstream : upstream_mobile
// Construct the upstream URL
const path = params.path.join("/")
const upstream_url = `https://${upstream_domain}/${path}${url.search}`
try {
// Fetch from upstream
const upstream_response = await fetch(upstream_url, {
headers: {
Host: upstream_domain,
"User-Agent": user_agent,
Referer: url.href,
},
})
// Clone the response so we can read it multiple times
const original_response = upstream_response.clone()
// Get the response headers
const response_headers = new Headers(upstream_response.headers)
// Set CORS headers
response_headers.set("access-control-allow-origin", "*")
response_headers.set("access-control-allow-credentials", "true")
// Remove security headers that might cause issues
response_headers.delete("content-security-policy")
response_headers.delete("content-security-policy-report-only")
response_headers.delete("clear-site-data")
// Get the content type
const content_type = response_headers.get("content-type") || ""
// Process the response body
let response_body
if (content_type.includes("text/html") && content_type.includes("UTF-8")) {
// If it's HTML, replace text
const text = await original_response.text()
response_body = replace_response_text(text, upstream_domain, url_host)
} else {
// Otherwise, just pass through the body
response_body = original_response.body
}
// Create and return the new response
return new NextResponse(response_body, {
status: upstream_response.status,
headers: response_headers,
})
} catch (error) {
console.error("Gravatar proxy error:", error)
return new NextResponse("Error proxying to Gravatar", { status: 500 })
}
}
// Helper function to determine if the request is from a desktop device
function device_status(user_agent_info: string): boolean {
const agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]
let flag = true
for (let v = 0; v < agents.length; v++) {
if (user_agent_info.indexOf(agents[v]) > 0) {
flag = false
break
}
}
return flag
}
// Helper function to replace text in the response
function replace_response_text(text: string, upstream_domain: string, host_name: string): string {
for (const [i, j] of Object.entries(replace_dict)) {
let from = i
let to = j
if (from === "$upstream") {
from = upstream_domain
} else if (from === "$custom_domain") {
from = host_name
}
if (to === "$upstream") {
to = upstream_domain
} else if (to === "$custom_domain") {
to = host_name
}
const re = new RegExp(from, "g")
text = text.replace(re, to)
}
return text
}