Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
addComponentsDir,
addImports,
addPluginTemplate, addTypeTemplate,
addServerHandler,
createResolver,
defineNuxtModule,
hasNuxtModule,
Expand Down Expand Up @@ -70,6 +71,21 @@ export interface ModuleOptions {
*/
cacheMaxAge?: number
}
/**
* Google Static Maps proxy configuration.
*/
googleStaticMapsProxy?: {
/**
* Enable proxying Google Static Maps through your own origin.
* @default false
*/
enabled?: boolean
/**
* Cache duration for static map images in seconds.
* @default 3600 (1 hour)
*/
cacheMaxAge?: number
}
/**
* Whether the module is enabled.
*
Expand Down Expand Up @@ -107,6 +123,10 @@ export default defineNuxtModule<ModuleOptions>({
timeout: 15_000, // Configures the maximum time (in milliseconds) allowed for each fetch attempt.
},
},
googleStaticMapsProxy: {
enabled: false,
cacheMaxAge: 3600,
},
enabled: true,
debug: false,
},
Expand All @@ -133,6 +153,7 @@ export default defineNuxtModule<ModuleOptions>({
// expose for devtools
version: nuxt.options.dev ? version : undefined,
defaultScriptOptions: config.defaultScriptOptions,
googleStaticMapsProxy: config.googleStaticMapsProxy,
}

// Merge registry config with existing runtimeConfig.public.scripts for proper env var resolution
Expand Down Expand Up @@ -267,6 +288,14 @@ export {}`
})
})

// Add Google Static Maps proxy handler if enabled
if (config.googleStaticMapsProxy?.enabled) {
addServerHandler({
route: '/_scripts/google-static-maps-proxy',
handler: await resolvePath('./runtime/server/google-static-maps-proxy.ts'),
})
}

if (nuxt.options.dev)
setupDevToolsUI(config, resolvePath)
},
Expand Down
31 changes: 21 additions & 10 deletions src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { withQuery } from 'ufo'
import type { QueryObject } from 'ufo'
import { defu } from 'defu'
import { hash } from 'ohash'
import { useHead } from 'nuxt/app'
import { useHead, useRuntimeConfig } from 'nuxt/app'
import type { ElementScriptTrigger } from '#nuxt-scripts/types'
import { scriptRuntimeConfig } from '#nuxt-scripts/utils'
import { useScriptTriggerElement } from '#nuxt-scripts/composables/useScriptTriggerElement'
Expand Down Expand Up @@ -119,6 +119,8 @@ const emits = defineEmits<{
}>()

const apiKey = props.apiKey || scriptRuntimeConfig('googleMaps')?.apiKey
const runtimeConfig = useRuntimeConfig()
const proxyConfig = (runtimeConfig.public['nuxt-scripts'] as any)?.googleStaticMapsProxy

const mapsApi = ref<typeof google.maps | undefined>()

Expand Down Expand Up @@ -381,14 +383,17 @@ onMounted(() => {
})

if (import.meta.server) {
useHead({
link: [
{
rel: props.aboveTheFold ? 'preconnect' : 'dns-prefetch',
href: 'https://maps.googleapis.com',
},
],
})
// Only preconnect to Google Maps if not using proxy
if (!proxyConfig?.enabled) {
useHead({
link: [
{
rel: props.aboveTheFold ? 'preconnect' : 'dns-prefetch',
href: 'https://maps.googleapis.com',
},
],
})
}
}

function transformMapStyles(styles: google.maps.MapTypeStyle[]) {
Expand Down Expand Up @@ -438,7 +443,13 @@ const placeholder = computed(() => {
})
.join('|'),
})
return withQuery('https://maps.googleapis.com/maps/api/staticmap', placeholderOptions as QueryObject)

// Use proxy endpoint if enabled, otherwise use direct Google Maps API
const baseUrl = proxyConfig?.enabled
? '/_scripts/google-static-maps-proxy'
: 'https://maps.googleapis.com/maps/api/staticmap'

return withQuery(baseUrl, placeholderOptions as QueryObject)
})

const placeholderAttrs = computed(() => {
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/composables/useScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { logger } from '../logger'
function useNuxtScriptRuntimeConfig() {
return useRuntimeConfig().public['nuxt-scripts'] as {
defaultScriptOptions: NuxtUseScriptOptions
googleStaticMapsProxy?: {
enabled?: boolean
cacheMaxAge?: number
}
}
}

Expand Down
62 changes: 62 additions & 0 deletions src/runtime/server/google-static-maps-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { EventHandler } from 'h3'
import { createError, defineEventHandler, getQuery, setHeader } from 'h3'
import { $fetch } from 'ofetch'
import { withQuery } from 'ufo'
import { useRuntimeConfig } from '#imports'

export default defineEventHandler(async (event) => {
const runtimeConfig = useRuntimeConfig()
const proxyConfig = (runtimeConfig.public['nuxt-scripts'] as any)?.googleStaticMapsProxy

if (!proxyConfig?.enabled) {
throw createError({
statusCode: 404,
statusMessage: 'Google Static Maps proxy is not enabled',
})
}

// Get query parameters from the request
const query = getQuery(event)

// Validate required parameters
if (!query.key) {
throw createError({
statusCode: 400,
statusMessage: 'API key is required',
})
}

// Build the Google Static Maps API URL
const googleMapsUrl = withQuery('https://maps.googleapis.com/maps/api/staticmap', query)

try {
// Fetch the image from Google Static Maps API
const response = await $fetch.raw(googleMapsUrl, {
headers: {
'User-Agent': 'Nuxt Scripts Google Static Maps Proxy',
},
})

// Set appropriate headers for caching and content type
const cacheMaxAge = proxyConfig.cacheMaxAge || 3600
setHeader(event, 'Content-Type', response.headers.get('content-type') || 'image/png')
setHeader(event, 'Cache-Control', `public, max-age=${cacheMaxAge}, s-maxage=${cacheMaxAge}`)
setHeader(event, 'Vary', 'Accept-Encoding')

// Add CORS headers if needed
setHeader(event, 'Access-Control-Allow-Origin', '*')
setHeader(event, 'Access-Control-Allow-Methods', 'GET, OPTIONS')
setHeader(event, 'Access-Control-Allow-Headers', 'Content-Type')

return response._data
}
catch (error: any) {
// Log error for debugging
console.error('Google Static Maps Proxy Error:', error)

throw createError({
statusCode: error.statusCode || 500,
statusMessage: error.statusMessage || 'Failed to fetch static map',
})
}
}) as EventHandler
Loading