Представьте, что вам нужно разработать интерфейс приложения, которое должно получать список самых популярных фильмов из API MovieDB.

Давай сделаем это !

Перейдите на MovieDB и зарегистрируйтесь, чтобы получить собственный ключ API и следуйте инструкциям.

Мы создадим новый проект с именем protectingapisecrets с помощью приложения create-react-app и начнем программировать наш интерфейс.

npx create-react-app protectingapisecrets
cd protectingapisecrets
touch .env
npm install axios

Откройте этот проект в своем любимом редакторе кода, отредактируйте файл .env и добавьте переменную со своим ключом API.

// .env
REACT_APP_API_KEY=<<your api key>>

затем откройте файл .gitignore и добавьте строку с вашим файлом .env и, наконец, удалите все файлы в папке src и создайте чистый i *ndex.js* App.js и App.css

Начать кодирование

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
// App.js
import React, { useState, useEffect } from "react"
import axios from "axios"
import "./App.css"
const App = () => {
  const [movies, setMovies] = useState(null)
    
    async function fetchMovies() {
        const url = `https://api.themoviedb.org/3/movie/popular?api_key=${process.env.REACT_APP_API_KEY}&language=en-US&page=1`
      const response = await axios.get(url)
        const data = response.data.results
        setMovies(data)
      }  
    useEffect(() => {
    fetchMovies()
  }, [])
    return (
    <>
      {movies === null ? (
        <div className="loading">
          <h2>Loading ...</h2>
        </div>
      ) : (
        <>
          <div className="container">
            {movies.map((movie) => (
              <div className="movie" key={movie.id}>
                <img src={`https://image.tmdb.org/t/p/w185/${movie.poster_path}`} alt={movie.title} />
              </div>
            ))}
          </div>
        </>
      )}
    </>
   )
  }
export default App
// App.css
*,
*::after,
*::before {
  margin: 0rem;
  padding: 0rem;
  box-sizing: inherit;
}
html {
  font-size: 62.5%;
  scroll-behavior: smooth;
}
body {
  box-sizing: border-box;
  background-color: #222831;
}
.loading {
  padding-top: 5rem;
  text-align: center;
}
.loading h2 {
  color: white;
  font-size: 2rem;
}
.container {
  margin: auto;
  padding: 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
  max-width: 110rem;
  grid-gap: 2rem;
}
.movie img {
  width: 100%;
}

Круто, теперь побежали

npm start

и проверьте, все ли ведет себя так, как мы ожидали

Развертывание

Удивительный!

Мы завершили наш интерфейс, теперь пришло время его развернуть.

С Netlify мы сделаем это очень легко и всего за три шага:

1-й: создайте новый репозиторий GitHub и отправьте свой код.

2-й: Создайте учетную запись на Netlify и подключите свою учетную запись к своему GitHub.

3-й: На панели Netlify выберите «Новый сайт из git» и выберите созданный вами репозиторий, вам также необходимо отметить «показать дополнительные» и добавить новую переменную, например:

нажмите «Развернуть сайт», и все, теперь у нас есть живая версия нашего приложения!

Проблема

Мы сохранили наш API-ключ в переменной среды, чтобы он не был доступен в нашем коде, но если кто-то откроет инструменты разработчика Chrome во время просмотра вашего сайта, он быстро сможет найти ваш ключ.

Итак, что мы можем сделать, чтобы защитить наш ключ API?

Бессерверные функции

Мы можем создать бессерверную функцию, которая будет обрабатывать вызовы нашего API, чтобы нам не приходилось публиковать наш ключ.

Давайте попробуем, вернитесь в свой терминал и запустите:

npm install netlify-lambda http-proxy-middleware env-cmd
mkdir functions
touch netlify.toml

Обновите скрипты в файле package.json, чтобы они выглядели следующим образом:

// package.json
"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
        "lambda-serve": "env-cmd netlify-lambda serve functions",
        "lambda-build": "netlify-lambda build functions"
  },

добавьте эти строки в файл netlify.toml и добавьте папку functions в свой .gitignorefile

// netlify.toml
[build]
    functions = "lambda"

добавьте файл с именем setupProxy.js в папку src и вставьте этот код:

// setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
  app.use(
    '/.netlify/functions/',
    createProxyMiddleware({
      target: 'http://localhost:9000',
      "pathRewrite": {
        "^/\\.netlify/functions": ""
      }
    })
  );
};

Эта настройка прокси позволит вам пинговать разные конечные точки в зависимости от того, в какой среде вы находитесь, если вы находитесь в разработке, вы хотите пинговать localhost, а в рабочей среде вам нужны ./netlify/functions конечная точка.

Кодируем нашу функцию

Давайте создадим файл с именем getMovies.js внутри нашего каталога functions.

// getMovies.js
const axios = require("axios")
exports.handler = function(event, context, callback) {
    const { API_KEY } = process.env
    const url = `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}&language=en-US&page=1`
    const send = body => {
        callback(null, {
            statusCode: 200,
            body: JSON.stringify(body)
        })
    }
    const getMovies = async () => {
        const response = await axios.get(url)
        const data = response.data.results
        send(data)
    }
    getMovies()
}

Теперь нам нужно отредактировать нашу функцию fetchMovies внутри App.js, чтобы использовать бесполезную функцию вместо прямого пинга API moviedb:

async function fetchMovies() {
    const url = `/.netlify/functions/getMovies`
    const response = await axios.get(url)
    const data = response.data
    setMovies(data)
  }

И, наконец, отредактируйте файл .env и измените имя переменной с REACT_APP_API_KEY на API_KEY.

Отлично, давайте проверим!

Откройте два окна терминала и запустите npm start в первом и npm run lambda-serve во втором и проверьте вкладку сети.

Круто, мы вызываем бессерверную функцию, скрывающую настоящую конечную точку API, давайте развернем ее на Netlify, откроем ваш терминал и запустим:

git add .
git commit -m "finished version"
git push

Когда вы отправляете фиксацию в репозиторий GitHub, Netlify инициирует новое развертывание для вашего сайта. Вам просто нужно сделать еще один шаг, и все готово, откройте панель Netlify и измените имя переменной среды, которую вы создали при первом развертывании, с REACT_APP_API_KEY на API_KEY.

Мы закончили, скоро увидимся!

Вы можете проверить мой репозиторий GitHub здесь: https://github.com/NunoCPNP/protectapisecrets

и моя развернутая версия здесь: https://protectingapisecrets.netlify.app/