CORS-Proxy + Google Autocomplete + Geoapify Routing
Technical Specification: Apps Script + Geoapify + Leaflet
The Google Places API (v1) restricts client-side requests from unauthorized domains via CORS. To solve this, we use a Google Apps Script Proxy. The client sends a request to the Script URL, which performs a server-to-server fetch (where CORS doesn't apply) and returns the data to our UI.
function doPost(e) {
const data = JSON.parse(e.postData.contents);
const API_KEY = "AIzaSy..."; // Secured on server-side
const URL = "https://places.googleapis.com/v1/places:autocomplete";
const payload = {
input: data.input,
includeQueryPredictions: true
};
const options = {
method: "post",
contentType: "application/json",
headers: {
"X-Goog-Api-Key": API_KEY,
"X-Goog-FieldMask": "suggestions.placePrediction.text,suggestions.placePrediction.location"
},
payload: JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(URL, options);
return ContentService.createTextOutput(response.getContentText()).setMimeType(ContentService.MimeType.JSON);
}
Once coordinates are obtained from Google Suggestions, we bypass further geocoding and send them directly to Geoapify. This calculates the actual path (polyline) based on the transport mode.
// Example Geoapify Request
const routeUrl = `https://api.geoapify.com/v1/routing?waypoints=${lat1},${lon1}|${lat2},${lon2}&mode=drive&apiKey=b856...`;
const response = await fetch(routeUrl);
const data = await response.json(); // Returns GeoJSON
We use Leaflet to render the map, but instead of OpenStreetMap, we point the tile layer to Google's vector tile server for a professional UI.
L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
maxZoom: 20,
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
}).addTo(map);
// 'lyrs=m' is Standard Roadmap
// 'lyrs=s' is Satellite
// 'lyrs=y' is Hybrid