Using images from Google Street View Static API without exposing key

1.7k Views Asked by At

I am trying to include Street View images on a React app. Here is the documentation for the API: Street View Static API

When I make a simple fetch request to google I get a response that contains a URL to the street view image as a JPG file:

bodyUsed:false
headers:Headers
ok:true
redirected:false
size:0
status:200
statusText:"OK"
Symbol(Body internals):Object {body: PassThrough, disturbed: false, error: null}
Symbol(Response internals):Object {url: "https://maps.googleapis.com/maps/api/streetview?lo…", status: 200, statusText: "OK", …}
timeout:0
// URL BELOW HERE IS WHAT I'M USING
url:"https://maps.googleapis.com/maps/api/streetview?location=3737%20N%20Southport%20Ave,%20Chicago,%20IL%2060613&key={MY_SECRECT_KEY}&size=300x300"

I can't use this image URL directly in my app because it contains my secret API key.

What I'm attempting to do now is use an AWS lambda function that uses Node to read the image file from the URL and then send this image file as an HTTP response to the client's react app.

I'm having trouble figuring out how to do this in Node. I've seen some code online about using Node's readFile function from the file system module. But I'm having trouble getting it to work.

Here's the code in my Lambda function.:


const fetch = require('node-fetch');

const fs = require('fs');

const autoCompURL = "https://maps.googleapis.com/maps/api/streetview?"

const { G_PLACES_KEY } = process.env

const key = `&key=${G_PLACES_KEY}`

const size = "&size=300x300"

function getSearch(e) {
    const resp = JSON.parse(e.body)
      return resp.place_address
}
  
async function googleResults(str) {
    const response = await fetch(
        `${autoCompURL}location=${str}${key}${size}`
    )

    return new Promise(resolve => resolve(response));
}
  
exports.handler = async function(event, context) {
  try {
    const userSearch = getSearch(event)

    const autoResults = await googleResults(userSearch)

    const imgURL = autoResults.url

    const img = await fs.promises.readFile(imgURL)

    if (autoResults.status !== "OK") {
      // NOT res.status >= 200 && res.status < 300
      return { statusCode: autoResults.status, body: autoResults.statusText, error_message: autoResults.error_message }
    }
    
    return {
      statusCode: 200,
      headers: {'Content-Type': 'image/jpeg'},
      body: img
    }
  } catch (err) {
    console.log(err) // output to netlify function log
    return {
      statusCode: 500,
      body: JSON.stringify({ msg: err.message }) // Could be a custom message or object i.e. JSON.stringify(err)
    }
  }
}

Appreciate any clues on how I can get this to work.

1

There are 1 best solutions below

0
Dinakaran Sankaranarayan On

Did you try this option ?

You can generate Digital Signature and use it along with API invocation. And limit unsigned requests to zero .

https://cloud.google.com/blog/products/maps-platform/google-maps-platform-best-practices-securing-api-keys-when-using-static-maps-and-street-view-apis