解决高德地图无外网访问难题:Vue项目代理转发全攻略

​ 背景:访问高德地图时由于其组件内嵌了域名请求,客户机无外网环境时会出现底图、相关图片资源无法加载的问题。

​ 解决方案:当部署的环境或者使用系统的用户电脑不能上网,但是有一台代理服务器可以上网,可以使用代理服务器加载高德地图。就需要将高德官方相关请求全部转发至代理服务器。

​ 项目背景:vue2、nginx。

方法一:域名匹配替换 + Service Worker

此方法注意事项:由于浏览器安全策略,Service Worker的使用需要配置证书,有证书条件的可以使用此方案。

​ 瓦片图相关资源请求由高德地图内部动态生成的域名,域名匹配替换一直无法成功需要配合Service Worker,通过Service Worker将瓦片图相关资源请求进行替换转发。

瓦片图相关资源请求如下(可能伴随官方升级进行变化):

jsapi-data1.amap.com

jsapi-data2.amap.com

jsapi-data3.amap.com

jsapi-data4.amap.com

jsapi-data5.amap.com

​ 采用"两层机制"完成地图域名转发:

​ 第一层是在应用初始化阶段挂载一个代理控制钩子,负责统一管理代理配置注入(如转发目标、匹配规则、调试参数)和环境兼容;

​ 第二层是Service Worker的请求拦截机制,在网络请求发出前识别地图相关目标地址,将其按规则重写到指定中转域并保留原始路径与参数后再继续请求。

​ 这样业务侧仍按原有地图调用方式开发,不需要逐页面改接口地址,即可实现透明转发。其核心原理是"应用层做策略控制、网络层做请求重写",优点是改造成本低、切换灵活、可统一治理地图访问稳定性与跨域受限问题。

废话不多说,直接上源码!!!

  • 域名匹配替换部分(amapProxyHook.js)
js 复制代码
/**
 * 将匹配到指定 host 前缀的 URL 重写到代理地址。
 *
 * 例如:
 * https://webapi.amap.com/xxx -> {proxyHost}/webapi.amap.com/xxx
 */
function rewriteByHost(url, prefix, proxyHost) {
  const httpsPrefix = `https://${prefix}`
  const httpPrefix = `http://${prefix}`
  const protocolRelativePrefix = `//${prefix}`

  // 处理 https://host
  if (url.indexOf(httpsPrefix) !== -1) {
    return `${proxyHost}/${prefix}${url.split(httpsPrefix)[1]}`
  }
  // 处理 http://host
  if (url.indexOf(httpPrefix) !== -1) {
    return `${proxyHost}/${prefix}${url.split(httpPrefix)[1]}`
  }
  // 处理 //host(协议相对地址)
  if (url.indexOf(protocolRelativePrefix) !== -1) {
    return `${proxyHost}/${prefix}${url.split(protocolRelativePrefix)[1]}`
  }
  return null
}

/**
 * 创建一个"高德 URL 重写函数"。
 *
 * 目的:
 * 将高德地图相关静态资源和数据请求统一改写到反向代理域名,
 * 从而规避直接访问高德域名时的跨域/网络策略限制。
 */
function createAmapUrlRewriter(proxyHost) {
  // 按产品线区分的高德基础域名
  const mapsUrl = 'https://webapi.amap.com/maps'
  const webapiHttpsUrl = 'https://webapi.amap.com'
  const restApiUrl = 'https://restapi.amap.com'
  const jsApiUrl = 'https://jsapi.amap.com'
  const o4ApiUrl = 'https://o4.amap.com'

  // 需要按"原 host + path"直通代理的数据域名
  const dataHosts = [
    'webapi.amap.com',
    'jsapi-service.amap.com'
  ]

  /**
   * 基于 URL.hostname 兜底匹配。
   * 对 dataHosts 中的域名,按 {proxyHost}/{host}{pathname}{search} 形式重写。
   */
  const toProxyByHostname = sourceUrl => {
    try {
      const urlObj = new URL(sourceUrl, window.location.origin)
      const host = urlObj.host
      if (dataHosts.indexOf(host) !== -1) {
        return `${proxyHost}/${host}${urlObj.pathname}${urlObj.search || ''}`
      }
      return null
    } catch (e) {
      // 非法 URL 或无法解析时,不做改写
      return null
    }
  }

  return source => {
    const sourceUrl = String(source)

    // 按固定前缀优先改写,保持后续路径与查询参数不变
    if (sourceUrl.indexOf(mapsUrl) !== -1) {
      return `${proxyHost}/maps${sourceUrl.split(mapsUrl)[1]}`
    }
    if (sourceUrl.indexOf(webapiHttpsUrl) !== -1) {
      return `${proxyHost}/webAmap${sourceUrl.split(webapiHttpsUrl)[1]}`
    }
    if (sourceUrl.indexOf(restApiUrl) !== -1) {
      return `${proxyHost}/restAmap${sourceUrl.split(restApiUrl)[1]}`
    }
    if (sourceUrl.indexOf(jsApiUrl) !== -1) {
      return `${proxyHost}/jsAmap${sourceUrl.split(jsApiUrl)[1]}`
    }
    if (sourceUrl.indexOf(o4ApiUrl) !== -1) {
      return `${proxyHost}/o4Amap${sourceUrl.split(o4ApiUrl)[1]}`
    }

    // 再尝试 dataHosts 前缀改写
    for (let i = 0; i < dataHosts.length; i++) {
      const rewritten = rewriteByHost(sourceUrl, dataHosts[i], proxyHost)
      if (rewritten) {
        return rewritten
      }
    }

    // 最后尝试 hostname 兜底改写
    const byHostname = toProxyByHostname(sourceUrl)
    if (byHostname) {
      return byHostname
    }

    // 非高德地址或未命中规则时,保持原样
    return source
  }
}

/**
 * 初始化高德代理 Hook。
 *
 * 功能:
 * 1. 劫持常见 DOM 属性赋值(script/img/link/a)
 * 2. 劫持 setAttribute
 * 3. 劫持 XMLHttpRequest.open
 * 4. 劫持 window.fetch
 * 5. 注入高德安全配置(_AMapSecurityConfig)
 */
export function initAmapProxyHook(options = {}) {
  // 避免重复初始化造成多次重写
  if (window.__amapScriptHooked__) {
    return
  }

  const proxyHost = options.proxyHost
  const amapKey = options.key
  const rewriteAmapUrl = createAmapUrlRewriter(proxyHost)

  // Hook <script>.src
  const scriptProperty = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'src')
  if (scriptProperty && scriptProperty.set) {
    const nativeSet = scriptProperty.set
    Object.defineProperty(HTMLScriptElement.prototype, 'src', {
      configurable: true,
      enumerable: scriptProperty.enumerable,
      get: scriptProperty.get,
      set(url) {
        nativeSet.call(this, rewriteAmapUrl(url))
      }
    })
  }

  // Hook <img>.src
  const imageProperty = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src')
  if (imageProperty && imageProperty.set) {
    const nativeImgSet = imageProperty.set
    Object.defineProperty(HTMLImageElement.prototype, 'src', {
      configurable: true,
      enumerable: imageProperty.enumerable,
      get: imageProperty.get,
      set(url) {
        nativeImgSet.call(this, rewriteAmapUrl(url))
      }
    })
  }

  // Hook <link>.href
  const linkProperty = Object.getOwnPropertyDescriptor(HTMLLinkElement.prototype, 'href')
  if (linkProperty && linkProperty.set) {
    const nativeLinkSet = linkProperty.set
    Object.defineProperty(HTMLLinkElement.prototype, 'href', {
      configurable: true,
      enumerable: linkProperty.enumerable,
      get: linkProperty.get,
      set(url) {
        nativeLinkSet.call(this, rewriteAmapUrl(url))
      }
    })
  }

  // Hook <a>.href
  const anchorProperty = Object.getOwnPropertyDescriptor(HTMLAnchorElement.prototype, 'href')
  if (anchorProperty && anchorProperty.set) {
    const nativeAnchorSet = anchorProperty.set
    Object.defineProperty(HTMLAnchorElement.prototype, 'href', {
      configurable: true,
      enumerable: anchorProperty.enumerable,
      get: anchorProperty.get,
      set(url) {
        nativeAnchorSet.call(this, rewriteAmapUrl(url))
      }
    })
  }

  // Hook setAttribute,覆盖通过属性字符串方式设置 src/href 的场景
  const nativeSetAttribute = Element.prototype.setAttribute
  Element.prototype.setAttribute = function(name, value) {
    if ((this.tagName === 'SCRIPT' || this.tagName === 'IMG') && name === 'src') {
      return nativeSetAttribute.call(this, name, rewriteAmapUrl(value))
    }
    if (this.tagName === 'LINK' && name === 'href') {
      return nativeSetAttribute.call(this, name, rewriteAmapUrl(value))
    }
    if (this.tagName === 'A' && name === 'href') {
      return nativeSetAttribute.call(this, name, rewriteAmapUrl(value))
    }
    return nativeSetAttribute.call(this, name, value)
  }

  // Hook XHR 请求
  const nativeXhrOpen = XMLHttpRequest.prototype.open
  XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
    const nextUrl = typeof url === 'string' ? rewriteAmapUrl(url) : url
    return nativeXhrOpen.call(this, method, nextUrl, async, user, password)
  }

  // Hook fetch 请求
  if (window.fetch) {
    const nativeFetch = window.fetch
    window.fetch = function(input, init) {
      if (typeof input === 'string') {
        return nativeFetch.call(this, rewriteAmapUrl(input), init)
      }
      if (input instanceof Request) {
        const nextRequest = new Request(rewriteAmapUrl(input.url), input)
        return nativeFetch.call(this, nextRequest, init)
      }
      if (input && input.url) {
        return nativeFetch.call(this, rewriteAmapUrl(input.url), init)
      }
      return nativeFetch.call(this, input, init)
    }
  }

  // 高德 JSAPI 安全配置:关闭 SW,指定服务地址走代理
  window._AMapSecurityConfig = {
    serviceWorker: false,
    serviceHost: `${proxyHost}/_AMapService`
  }

  /**
   * 自检函数:用于快速验证代理链路是否可用。
   *
   * 检查逻辑:
   * - 请求一个高德初始化接口
   * - 返回不是 HTML 且不是明显错误页,则视为通过
   */
  window.__amapProxySelfCheck__ = async function() {
    const checkUrl = `${proxyHost}/jsAmap/web/init?key=${amapKey}&v=2.0`
    try {
      const res = await window.fetch(checkUrl, { method: 'GET' })
      const text = await res.text()
      const isHtml = text.indexOf('<html') !== -1 || text.indexOf('<!DOCTYPE') !== -1
      const maybeBlocked = text.indexOf('error') !== -1 || text.indexOf('forbidden') !== -1
      const pass = res.ok && !isHtml && !maybeBlocked
      console.log('[AMapProxySelfCheck]', {
        pass,
        status: res.status,
        url: checkUrl,
        contentType: res.headers.get('content-type'),
        sample: text.slice(0, 180)
      })
      return pass
    } catch (error) {
      console.error('[AMapProxySelfCheck] request failed', error)
      return false
    }
  }

  // 标记已初始化
  window.__amapScriptHooked__ = true
}
  • Service Worker部分(amap-sw.js 置与public目录下与index.html同级)
js 复制代码
/* eslint-disable no-restricted-globals */
const AMAP_PROXY_HOSTS = new Set([
  'jsapi-data1.amap.com',
  'jsapi-data2.amap.com',
  'jsapi-data3.amap.com',
  'jsapi-data4.amap.com',
  'jsapi-data5.amap.com'
])

const MIN_TILE_BYTES = 200

function getProxyHost() {
  const params = new URLSearchParams(self.location && self.location.search ? self.location.search : '')
  return params.get('proxyHost') || ''
}

function isTileRequest(url) {
  return /\/tile\/.+\/pbf\//.test(url.pathname)
}

function isLikelyBadTile(contentType, byteLength) {
  const isText = contentType && contentType.toLowerCase().includes('text')
  return isText || byteLength < MIN_TILE_BYTES
}

self.addEventListener('install', () => {
  self.skipWaiting()
})

self.addEventListener('activate', event => {
  event.waitUntil(self.clients.claim())
})

self.addEventListener('fetch', event => {
  const req = event.request
  const url = new URL(req.url)

  if (!AMAP_PROXY_HOSTS.has(url.host)) return

  const proxyHost = getProxyHost()
  const proxyUrl = `${proxyHost}/proxy/${url.host}${url.pathname}${url.search}`

  event.respondWith((async() => {
    try {
      const proxyRes = await fetch(proxyUrl)
      if (!proxyRes || !proxyRes.ok) {
        throw new Error(`proxy fetch failed: ${proxyRes ? proxyRes.status : 'unknown'}`)
      }

      if (isTileRequest(url)) {
        const clone = proxyRes.clone()
        const buf = await clone.arrayBuffer()
        const contentType = proxyRes.headers.get('content-type') || ''
        const badTile = isLikelyBadTile(contentType, buf.byteLength)

        if (badTile) {
          return fetch(req)
        }
      }

      return proxyRes
    } catch (e) {
      return fetch(req)
    }
  })())
})
  • main.js配置
js 复制代码
import { initAmapProxyHook } from '@/utils/amapProxyHook'

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    const swUrl = `/amap-sw.js?proxyHost=${encodeURIComponent(store.getters.amapProxyHost)}`
    navigator.serviceWorker
      .register(swUrl)
      .then(() => navigator.serviceWorker.ready)
      .then(() => {
        console.log('[AMap SW] ready')
      })
      .catch(err => {
        console.error('[AMap SW] register failed', err)
      })
  })
}

// 全局高德代理hook:必须在任何高德SDK加载前执行
initAmapProxyHook({
  proxyHost: store.getters.amapProxyHost,
  key: store.getters.amapKey
})
  • 代理服务器nginx配置
nginx 复制代码
server {
    listen 监听端口;
    server_name localhost;
    
    # DNS 解析器配置(放在 server 块内) 
    # 将114.114.114.114 8.8.8.8替换为你内网自己的DNS解析器
    resolver 114.114.114.114 8.8.8.8 valid=300s;
    resolver_timeout 10s;
    
    # ===== 统一 CORS 配置 =====
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
    
    # 处理 OPTIONS 预检请求
    if ($request_method = OPTIONS) {
        return 204;
    }
    
    # ===== 通用代理参数 =====
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_ssl_server_name on;
    proxy_ssl_verify off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 15s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    
    # ===== 1. 处理直接请求 /maps 或 /maps/ 的情况 =====
    location /maps/ {
        proxy_pass https://webapi.amap.com/maps/;
        proxy_set_header Host webapi.amap.com;
        proxy_set_header Referer https://webapi.amap.com/;
        proxy_set_header Origin https://webapi.amap.com;
        proxy_set_header Accept-Encoding "";
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
	
	location /webAmap/ {
        rewrite ^/webAmap/(.*)$ /$1 break;
        proxy_pass https://webapi.amap.com;
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
	
	location /jsapi-service.amap.com/ {
        proxy_set_header Host jsapi-service.amap.com;
        proxy_pass https://jsapi-service.amap.com/;
	
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
	
	location /webapi.amap.com/ {
        proxy_set_header Host webapi.amap.com;
        proxy_pass https://webapi.amap.com/;
	
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 2. 高德服务端 API 代理(安全密钥验证) =====
    location /_AMapService/ {
        rewrite ^/_AMapService/(.*)$ /$1 break;
        
        # 关键:追加安全密钥
        set $args "$args&jscode=你的高德安全密钥";
        
        proxy_pass https://restapi.amap.com;
        proxy_set_header Host restapi.amap.com;
        proxy_set_header Referer https://restapi.amap.com;
        proxy_set_header User-Agent "Mozilla/5.0";
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 3. JS API 脚本代理 =====
    location /jsAmap/ {
        rewrite ^/jsAmap/(.*)$ /$1 break;
        proxy_pass https://jsapi.amap.com;
        proxy_set_header Host jsapi.amap.com;
        proxy_set_header Referer https://jsapi.amap.com;
        proxy_set_header Origin https://jsapi.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
	
	location /restAmap/ {
        rewrite ^/restAmap/(.*)$ /$1 break;
        proxy_pass https://restapi.amap.com;
        proxy_set_header Host restapi.amap.com;
        proxy_set_header Referer https://restapi.amap.com;
        proxy_set_header Origin https://restapi.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
	
	location /o4Amap/ {
        rewrite ^/o4Amap/(.*)$ /$1 break;
        proxy_pass https://o4.amap.com;
        proxy_set_header Host o4.amap.com;
        proxy_set_header Referer https://o4.amap.com;
        proxy_set_header Origin https://o4.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
	# 动态匹配 o4.amap.com 或 jsapi-data*.amap.com 等
	location ~ ^/proxy/([^/]+)/(.*)$ {
		set $target_host $1;
		set $target_path $2;
		
		proxy_pass https://$target_host/$target_path$is_args$args;
		proxy_ssl_server_name on;
		proxy_ssl_name $target_host;
		proxy_set_header Host $target_host;
		proxy_set_header Referer "https://$target_host/";
		proxy_set_header Origin "https://$target_host";
		
		proxy_hide_header Access-Control-Allow-Origin;
		proxy_hide_header Access-Control-Allow-Methods;
		proxy_hide_header Access-Control-Allow-Headers;
		proxy_hide_header Access-Control-Expose-Headers;
		add_header Access-Control-Allow-Origin "*" always;
		add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
		add_header Access-Control-Allow-Headers "*" always;
		add_header Access-Control-Expose-Headers "Content-Length,Content-Range,ETag" always;
		if ($request_method = OPTIONS) { return 204; }
	}
    
    access_log /data/project/dev/nginxLog/access.log;
    error_log  /data/project/dev/nginxLog/error.log;
}

方案二:@huangjs888/amap-proxy组件 (推荐使用)

css 复制代码
npm i @huangjs888/amap-proxy
  • main.js配置
js 复制代码
import ap from '@huangjs888/amap-proxy'

// http://IP:端口/proxy/ 为代理服务器IP和nginx监听端口,/proxy/为自定义前缀
ap(
  'http://IP:端口/proxy/',
  /(https?:)?\/\/((jsapi-data[1-5]|webapi|restapi|jsapi|o4|mapplugin|jsapi-service)\.amap\.com)/g
)
  • 代理服务器nginx配置
nginx 复制代码
server {
    listen 8068;
    server_name localhost;
    
    # DNS 解析器配置(放在 server 块内) 
    # 将114.114.114.114 8.8.8.8替换为你内网自己的DNS解析器
    resolver 114.114.114.114 8.8.8.8 valid=300s;
    resolver_timeout 10s;
    
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
    
    if ($request_method = OPTIONS) {
        return 204;
    }
    
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_ssl_server_name on;
    proxy_ssl_verify off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 15s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
    
    # ===== 规则1: webapi.amap.com/maps =====
    location ~* ^/proxy/webapi\.amap\.com/maps(?:/(.*))?$ {
        set $webapi_path $1;
        proxy_pass https://webapi.amap.com/maps/${webapi_path}$is_args$args;
        proxy_set_header Host webapi.amap.com;
        proxy_set_header Referer https://webapi.amap.com/;
        proxy_set_header Origin https://webapi.amap.com;
        proxy_set_header Accept-Encoding "";
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 规则2: jsapi-service.amap.com =====
    location ~* ^/proxy/jsapi-service\.amap\.com(?:/(.*))?$ {
        set $jsapi_service_path $1;
        proxy_pass https://jsapi-service.amap.com/${jsapi_service_path}$is_args$args;
		proxy_set_header Host jsapi-service.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 规则3: webapi.amap.com =====
    location ~* ^/proxy/webapi\.amap\.com(?:/(.*))?$ {
        set $webapi_path $1;
        proxy_pass https://webapi.amap.com/${webapi_path}$is_args$args;
		proxy_set_header Host webapi.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 规则4: restapi.amap.com(安全密钥验证)=====
    location ~* ^/proxy/restapi\.amap\.com/(.*)$ {
        set $restapi_path $1;
        set $args "$args&jscode=0409a616c842552f2f836d3f6f402836";
        proxy_pass https://restapi.amap.com/$restapi_path$is_args$args;
        proxy_set_header Host restapi.amap.com;
        #proxy_set_header Referer https://restapi.amap.com;
        #proxy_set_header User-Agent "Mozilla/5.0";
		
		#add
		#proxy_set_header Origin https://jsapi.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 规则5: jsapi.amap.com =====
    location ~* ^/proxy/jsapi\.amap\.com/(.*)$ {
        set $jsapi_path $1;
        proxy_pass https://jsapi.amap.com/$jsapi_path$is_args$args;
        proxy_set_header Host jsapi.amap.com;
        #proxy_set_header Referer https://jsapi.amap.com;
        #proxy_set_header Origin https://jsapi.amap.com;
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Allow-Credentials;
    }
    
    # ===== 规则6: 通用兜底 *.amap.com =====
    location ~ ^/proxy/([^/]+)/(.*)$ {
        set $target_host $1;
        set $target_path $2;
        
        proxy_pass https://$target_host/$target_path$is_args$args;
        proxy_ssl_server_name on;
        proxy_ssl_name $target_host;
        proxy_set_header Host $target_host;
        proxy_set_header Referer "https://$target_host/";
        proxy_set_header Origin "https://$target_host";
        
        proxy_hide_header Access-Control-Allow-Origin;
        proxy_hide_header Access-Control-Allow-Methods;
        proxy_hide_header Access-Control-Allow-Headers;
        proxy_hide_header Access-Control-Expose-Headers;
        add_header Access-Control-Allow-Origin "*" always;
        add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
        add_header Access-Control-Allow-Headers "*" always;
        add_header Access-Control-Expose-Headers "Content-Length,Content-Range,ETag" always;
        if ($request_method = OPTIONS) { return 204; }
    }
    
    access_log /data/nginxLogs/access.log;
    error_log  /data/nginxLogs/error.log;
}
相关推荐
wand codemonkey1 小时前
Maven Web 项目 + Tomcat 从零排错全流程(零遗漏版)
前端·tomcat·maven
豆苗学前端1 小时前
【前端内功】同为数据驱动,为什么只有 React 的"心智负担"这么重?(附实战优化指南)
前端·vue.js·面试
铁皮饭盒1 小时前
震惊, Bun突发新版, 重写核心, 换掉了底层Zig
前端·javascript·后端
IT_陈寒1 小时前
深入理解Java:核心原理与最佳实践
前端·人工智能·后端
恋猫de小郭1 小时前
Android Studio 放着没怎么用,怎么也会越来越卡?
android·前端·flutter
fanzhonghong1 小时前
javaWeb开发之前端实战(Vue工程化+ElementPlus)
前端·javascript·vue.js·后端·spring
openKaka_1 小时前
completeWork:真实 DOM 是在哪里被创建的
前端·javascript·react.js
希冀1231 小时前
【CSS学习第六篇】
前端
Python大数据分析@2 小时前
说说Markdown为什么不会被HTML取代
前端·html