Question: I have an application which uses a YouTube API key to search for videos on YouTube and display them on my page. I've just learned that it's **bad** to expose any secrets to the client. So, the solution I'm considering is to have the client send requests to a Firebase cloud function instead. The cloud function will serve as the proxy where my API key will be stored instead of storing it in the client.

How do I set it up?

For starters, I tried logging the `request` object but I'm getting a cryptic error message.

```
error: SUPERVISOR clientError { Error: Parse Error bytesParsed: 0, code: 'HPE_INVALID_METHOD' } connecting=false, _hadError=false, bytesRead=193, , fd=
-1, reading=true, $ref=$, onread=function onread(nread, buffer) {

```

Here's the `GET` request sent by the client that produced the error message above

```
https://localhost:5000/jpls-youtube-viewer/us-central1/helloWorld?part=snippet&type=video&q=Linkin+Park

```

Here's the repo of my application: <https://github.com/jpls93/jpls-youtube-viewer>

And here's the hosted site: <https://jpls-youtube-viewer.firebaseapp.com/>

Answer: 
I solved it by pointing the client request to my Firebase database URL then I had the Firebase database URL do the request to the YouTube REST API URL and resolve the response to my client. I had an issue with CORS, but that was simply fixed by allowing access-control-origin/methods

```
exports.helloWorld = functions.https.onRequest((request, response) => {
  var term = request.query.q;
  // See https://howtofirebase.com/firebase-cloud-functions-753935e80323
  // why we're requiring it inside the function
  var YT_URL = "https://www.googleapis.com/youtube/v3/search";
  const axios = require("axios");
  axios
    .get(YT_URL, {
      params: {
        part: "snippet",
        type: "video",
        key: require("./secret"),
        q: term
      }
    })
    .then(YouTubeData => {
      response.set("Access-Control-Allow-Origin", "*");
      response.set("Access-Control-Allow-Methods", "GET, POST");
      response.status(200).send(YouTubeData.data.items);
    })
    .catch(err => console.error(err));
});

```
```
const https = require('https');
const buffer = require('buffer');

exports.proxyURL = functions.https.onRequest(async (req, res) => {

const url = req.query.url;  
await https.get(url, (resp) => {   

let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {

  let ctype = resp.headers["content-type"];
  if (ctype.includes("charset=ISO-8859-1"))
  {
    const latin1Buffer = buffer.transcode(Buffer.from(chunk), "latin1", "utf8");      
    data += latin1Buffer.toString("utf8");
  }else{
    data += chunk;
  }            
});

// The whole response has been received. Print out the result.
resp.on('end', () => {          
  res.contentType('application/xml; charset=UTF-8');      
  res.write(data);
  return res.status(200).end();
});

}).on("error", (err) => {
console.log("Error: " + err.message);
return res.status(500).end();
});  
});

```