-1

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.

  • The thing is... you don't need to hide your key. Instead you should protect it, as per the [guidelines](https://developers.google.com/maps/api-key-best-practices). – MrUpsidown Apr 01 '20 at 18:19
  • @MrUpsidown Appreciate the response. I read Google's [guidelines](https://developers.google.com/maps/api-key-best-practices) and they recommend not embedding API keys or signing secrets in your code. My react app is going to be public facing so I think I'm going to need to use a AWS Lambda function as a proxy server to fetch images. – hackr_jackr Apr 01 '20 at 20:01
  • They recommend not embedding the keys or secret in your code *repository*. Or what other guideline are you referring to? – MrUpsidown Apr 01 '20 at 20:34

1 Answers1

-1

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