Автор оригинала: FreeCodeCamp Community Member.
Фрэнсис Воскресенье
TL; DR: В этом руководстве я покажу вам, насколько легко создать веб-приложение с GO и Framework GIN и добавить аутентификацию к нему. Проверьте Github репо Для кода мы собираемся написать.
Джин является высокопроизводительным микро-каркасом. Он обеспечивает очень минималистичные рамки, которые выполняют его только самые важные функции, библиотеки и функциональные возможности, необходимые для создания веб-приложений и микросервисов. Это делает его простым для создания трубопровода обработки запросов от модульных, многоразовых деталей. Это делает это, позволяя вам писать промежуточное программное обеспечение, которое можно подключить к одному или нескольким обработчикам запроса или групп обработчиков запросов.
Особенности джина
Джин – это быстрый, простая, но полностью полностью представлена и очень эффективная веб-каркас для GO. Проверьте некоторые из функций ниже, которые делают достойную структуру для рассмотрения вашего следующего проекта Golang.
- Скорость: Джин построен для скорости. Рамки предлагают маршрутизацию на основе Radix на основе дерева и небольшую площадь памяти. Нет отражения. Предсказуемая производительность API.
- БЕСПЛАТНЫЙ : Джин имеет возможность ловить аварию или панику во время выполнения, и может оправиться от них. Таким образом, ваше приложение всегда будет доступно.
- Маршрутизация: GIN предоставляет интерфейс маршрутизации, чтобы позволить вам выразить ваше веб-приложение или маршруты API.
- Валидация JSON: Джин может легко разбирать и подтвердить запросы JSON, проверяя наличие необходимых значений.
- Управление ошибками: Джин дает удобный способ собрать все ошибки во время HTTP-запроса. В конце концов, промежуточное программное обеспечение может написать их в файл журнала или в базу данных и отправлять их через сеть.
- Встроенный рендеринг: GIN обеспечивает простые в использовании API для JSON, XML и HTML-рендеринга.
Предварительные условия
Чтобы следить с этим руководством, вам нужно будет установить на вашем компьютере, веб-браузер для просмотра приложения и командной строки для выполнения команд сборки.
Иди, или как его нормально называют Голанг Этот язык программирования, разработанный Google для создания современного программного обеспечения. Go – это язык, предназначенный для эффективного и быстро и быстро. Основные преимущества GO включают в себя:
- Сильно набран и мусор собранный
- Пылающий быстрые времена компиляции
- Встроенный параллелизм
- Обширная стандартная библиотека
Перейти к Скачать раздел веб-сайта Go, чтобы пойти на работу на вашу машину.
Создание приложения с джином
Мы будем строить простое приложение для списка шуток с Джин . Наше приложение будет перечислять некоторые глупые шутки папы. Мы собираемся добавить аутентификацию к нему, чтобы все зарегистрированные пользователи будут иметь привилегию любить и просматривать шутки.
Это позволит нам иллюстрировать, как Джин Может использоваться для разработки веб-приложений и/или API.
Мы будем использовать следующие функциональные возможности, предлагаемые Джином:
- Промежуточное программное обеспечение
- Маршрутизация
- Маршруты Группировка
На старт, внимание, марш
Мы напишем все наше приложение Go в main.go файл. Поскольку это небольшое приложение, это будет легко создать приложение только с Иди беги от терминала.
Мы создадим новый каталог Голанг-Джин в нашем рабочем пространстве, а затем main.go Файл в нем:
$ mkdir -p $GOPATH/src/github.com/user/golang-gin $ cd $GOPATH/src/github.com/user/golang-gin $ touch main.go
Содержание main.go файл:
package main
import (
"net/http"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
func main() {
// Set the router as the default one shipped with Gin
router := gin.Default()
// Serve frontend static files
router.Use(static.Serve("/", static.LocalFile("./views", true)))
// Setup route group for the API
api := router.Group("/api")
{
api.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H {
"message": "pong",
})
})
}
// Start and run the server
router.Run(":3000")
}Нам нужно создать еще несколько каталогов для наших статических файлов. В том же каталоге, что и main.go Файл, давайте создадим Виды папка. В Виды Папка, создать JS Папка и index.html Файл в нем.
index.html Файл будет очень прост сейчас:
Jokeish App Welcome to the Jokeish App
Перед тем, как мы проверим то, что мы имеем до сих пор, давайте установим дополнительные зависимости:
$ go get -u github.com/gin-gonic/gin $ go get -u github.com/gin-gonic/contrib/static
Чтобы посмотреть, что работает, нам нужно запустить наш сервер, запустив Go Run Main.go Отказ
Как только приложение запущено, перейдите к http://localhost: 3000 в вашем браузере. Если все прошло хорошо, вы должны увидеть текст заголовка уровня 1 Добро пожаловать в приложение для шутки отображается.
Определение API
Давайте добавим еще код в нашем main.go Файл для наших определений API. Мы обновим наше Главная Функция с двумя маршрутами /шутки/ и /анекдоты/как/: joundid в группу маршрутов /API/ Отказ
func main() {
// ... leave the code above untouched...
// Our API will consit of just two routes
// /jokes - which will retrieve a list of jokes a user can see
// /jokes/like/:jokeID - which will capture likes sent to a particular joke
api.GET("/jokes", JokeHandler)
api.POST("/jokes/like/:jokeID", LikeJoke)
}
// JokeHandler retrieves a list of available jokes
func JokeHandler(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, gin.H {
"message":"Jokes handler not implemented yet",
})
}
// LikeJoke increments the likes of a particular joke Item
func LikeJoke(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, gin.H {
"message":"LikeJoke handler not implemented yet",
})
}Содержание main.go Файл должен выглядеть так:
package main
import (
"net/http"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
func main() {
// Set the router as the default one shipped with Gin
router := gin.Default()
// Serve frontend static files
router.Use(static.Serve("/", static.LocalFile("./views", true)))
// Setup route group for the API
api := router.Group("/api")
{
api.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H {
"message": "pong",
})
})
}
// Our API will consit of just two routes
// /jokes - which will retrieve a list of jokes a user can see
// /jokes/like/:jokeID - which will capture likes sent to a particular joke
api.GET("/jokes", JokeHandler)
api.POST("/jokes/like/:jokeID", LikeJoke)
// Start and run the server
router.Run(":3000")
}
// JokeHandler retrieves a list of available jokes
func JokeHandler(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, gin.H {
"message":"Jokes handler not implemented yet",
})
}
// LikeJoke increments the likes of a particular joke Item
func LikeJoke(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, gin.H {
"message":"LikeJoke handler not implemented yet",
})
}Давайте снова запустим наше приложение Go Run Main.go и получить доступ к нашим маршрутам. http://localhost: 3000/API/Jokes вернется 200 ОК Ответ заголовка, с сообщением Шутки обработчика еще не реализованы Отказ Пост запрос на http://localhost: 3000/api/jokes/like/1 Возвращает 200 ОК Заголовок и сообщение Обработчик AlceJoke не реализован еще Отказ
Шутки данных
Поскольку у нас уже есть наши маршруты набор определений, что делает только одно (вернуть ответ JSON), мы немного выпиваем нашу кодовую базу, добавив еще несколько кода к нему.
// ... leave the code above untouched...
// Let's create our Jokes struct. This will contain information about a Joke
// Joke contains information about a single Joke
type Joke struct {
ID int `json:"id" binding:"required"`
Likes int `json:"likes"`
Joke string `json:"joke" binding:"required"`
}
// We'll create a list of jokes
var jokes = []Joke{
Joke{1, 0, "Did you hear about the restaurant on the moon? Great food, no atmosphere."},
Joke{2, 0, "What do you call a fake noodle? An Impasta."},
Joke{3, 0, "How many apples grow on a tree? All of them."},
Joke{4, 0, "Want to hear a joke about paper? Nevermind it's tearable."},
Joke{5, 0, "I just watched a program about beavers. It was the best dam program I've ever seen."},
Joke{6, 0, "Why did the coffee file a police report? It got mugged."},
Joke{7, 0, "How does a penguin build it's house? Igloos it together."},
}
func main() {
// ... leave this block untouched...
}
// JokeHandler retrieves a list of available jokes
func JokeHandler(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, jokes)
}
// LikeJoke increments the likes of a particular joke Item
func LikeJoke(c *gin.Context) {
// confirm Joke ID sent is valid
// remember to import the `strconv` package
if jokeid, err := strconv.Atoi(c.Param("jokeID")); err == nil {
// find joke, and increment likes
for i := 0; i < len(jokes); i++ {
if jokes[i].ID == jokeid {
jokes[i].Likes += 1
}
}
// return a pointer to the updated jokes list
c.JSON(http.StatusOK, &jokes)
} else {
// Joke ID is invalid
c.AbortWithStatus(http.StatusNotFound)
}
}
// NB: Replace the JokeHandler and LikeJoke functions in the previous version to the ones aboveС нашим кодом выглядит хорошо, давайте пойдем вперед и проверим нашу API. Мы можем проверить с Curl или почтальон , а затем отправьте Получить Запрос на http://localhost: 3000/jokes Чтобы получить полный список шуток и Пост Запрос на http://localhost: 3000/jokes/like/{jokeid} увеличить симпатию шутки.
$ curl http://localhost:3000/api/jokes $ curl -X POST http://localhost:3000/api/jokes/like/4
Создание пользовательского интерфейса (реагировать)
У нас есть наш API на месте, поэтому давайте построим интерфейс для представления данных с наших API. Для этого мы будем использовать React. Мы не будем слишком глубоко реагировать, так как он будет вне сферы этого учебника. Если вам нужно узнать больше о реагировании, оформить заказ официальным Учебное пособие Отказ Вы можете реализовать пользовательский интерфейс с любыми беспризорными каркасами, с которыми вам удобно.
Настраивать
Мы отредактируем index.html Файл, чтобы добавить внешние библиотеки, необходимые для работы. Тогда нам нужно создать app.jsx Файл в Виды/JS. каталог, который будет содержать наш код REACT.
Наше index.html Файл должен выглядеть так:
Jokeish App
Создание наших компонентов
В реакции представления разбиты на компоненты. Нам нужно будет построить некоторые компоненты:
-
ПриложениеКомпонент в качестве основной записи, которая запускает приложение - А
ГлавнаяКомпонент, который столкнется с запутанными пользователями - А
LogugedinКомпонент с контентом виден только аутентифицированными пользователями - и а
ШуткаКомпонент для отображения списка шуток.
Мы напишем все эти компоненты в app.jsx файл.
Компонент приложения
Этот компонент загрузил все наше время реагирования. Он решает, какой компонент показать на основе того, аутентифицирован ли пользователь или нет. Мы начнем с его базой, а позже обновите его с большим количеством функциональности.
class App extends React.Component {
render() {
if (this.loggedIn) {
return ( );
} else {
return ( );
}
}
}Домашний компонент
Этот компонент отображается не зарегистрированным пользователям, наряду с кнопкой, которая открывает хостованный экран блокировки, в котором они могут регистрироваться или входить в систему. Мы добавим эту функцию позже.
class Home extends React.Component {
render() {
return (
)
}
}Компонент logugedin
Этот компонент отображается, когда пользователь аутентифицирован. Он хранит в своем Государство Массив шуток, который заполняется при установке компонентов.
class LoggedIn extends React.Component {
constructor(props) {
super(props);
this.state = {
jokes: []
}
}
render() {
return (
Log out
Jokeish
Let's feed you with some funny Jokes!!!
{this.state.jokes.map(function(joke, i){
return ( );
})}
)
}
}Компонент шутки
Шутка Компонент будет содержать информацию о каждом элементе из отклика шуток, который будет отображаться.
class Joke extends React.Component {
constructor(props) {
super(props);
this.state = {
liked: ""
}
this.like = this.like.bind(this);
}
like() {
// ... we'll add this block later
}
render() {
return (
)
}
}Мы написали наши компоненты, поэтому теперь давайте скажем отреагировать, где сделать приложение. Мы добавим блок код ниже в нижнюю часть нашего app.jsx файл.
ReactDOM.render(, document.getElementById('app'));
Давайте перезапустим наш сервер Go Go Run Main.go и отправьтесь к URL-адресу нашего приложения http://localhost: 3000/ Отказ Вы увидите, что Главная компонент оказывается.
Обеспечение нашего приложения Joxes с AUTH0
AUTH0 проблемы JSON WEB. Токены На каждом входе для ваших пользователей. Это означает, что вы можете иметь твердое Инфраструктура идентичности , в том числе Одиночный вход , Управление пользователем, поддержка поставщиков социальной идентичности (Facebook, Github, Twitter и т. Д.), Поставщики Identity Enterprise (Active Directory, LDAP, SAML и т. Д.) И ваша собственная база данных пользователей с несколькими линиями кода.
Мы можем легко настроить аутентификацию в нашем приложении GIN с помощью AUTH0. Вам понадобится учетная запись, чтобы следовать вместе с этой частью. Если у вас нет учетной записи AUTH0, Зарегистрироваться на один сейчас.
Создание клиента API
Наши токены будут сгенерированы с помощью AUTH0, поэтому нам нужно создать API и клиент с нашей панели инструментов AUTH0. Опять же, если вы еще не сделали, Зарегистрироваться Для учетной записи AUTH0.
Чтобы создать новую API, перейдите к Секция API на приборной панели и нажмите на Создать API кнопка.
Выберите API Имя и Идентификатор Отказ Идентификатор будет Аудитория для промежуточного программного обеспечения. Подписание алгоритма должно быть RS256. .
Чтобы создать новый клиент, перейдите к Секция клиентов на приборной панели и нажмите на Создать клиент кнопка. Выберите тип Регулярные веб-приложения .
Как только клиент создан, обратите внимание на Client_id и Client_Secret. , как нам понадобится позже.
Мы должны добавить учетные данные, необходимые для нашего API для переменной среды. В корневом каталоге создайте новый файл .env И добавьте его к нему, с деталями приборной панели AUTH0:
export AUTH0_API_CLIENT_SECRET="" export AUTH0_CLIENT_ID="" export AUTH0_DOMAIN="yourdomain.auth0.com" export AUTH0_API_AUDIENCE=""
Защита наших конечных точек API
В настоящее время наша API открыта для мира. Нам нужно обеспечить наши конечные точки, поэтому только авторизованные пользователи могут получить доступ к ним.
Мы собираемся использовать JWT Mardware Чтобы проверить действительный JSON WEB. Токен Из каждого запроса ударяет наши конечные точки.
Давайте создадим наше промежуточное программное обеспечение:
// ...
var jwtMiddleWare *jwtmiddleware.JWTMiddleware
func main() {
jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
aud := os.Getenv("AUTH0_API_AUDIENCE")
checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false)
if !checkAudience {
return token, errors.New("Invalid audience.")
}
// verify iss claim
iss := os.Getenv("AUTH0_DOMAIN")
checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false)
if !checkIss {
return token, errors.New("Invalid issuer.")
}
cert, err := getPemCert(token)
if err != nil {
log.Fatalf("could not get cert: %+v", err)
}
result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
return result, nil
},
SigningMethod: jwt.SigningMethodRS256,
})
// register our actual jwtMiddleware
jwtMiddleWare = jwtMiddleware
// ... the rest of the code below this function doesn't change yet
}
// authMiddleware intercepts the requests, and check for a valid jwt token
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Get the client secret key
err := jwtMiddleWare.CheckJWT(c.Writer, c.Request)
if err != nil {
// Token not found
fmt.Println(err)
c.Abort()
c.Writer.WriteHeader(http.StatusUnauthorized)
c.Writer.Write([]byte("Unauthorized"))
return
}
}
}В приведенном выше коде у нас есть новый jwtmiddleware Переменная, которая инициализируется в Главная функция. Он используется в authmiddleware средняя функция.
Если вы заметите, мы вытягиваем наши учетные данные для серверов из переменной окружающей среды (один из принципов приложений 12-фактор ). Наши промежуточные программы проверяют и получает токен из запроса и вызывает jwtmiddleware. Checkjwt Метод для подтверждения отправленного токена.
Давайте также напишем функцию, чтобы вернуть веб-ключи JSON:
// ... the code above is untouched...
// Jwks stores a slice of JSON Web Keys
type Jwks struct {
Keys []JSONWebKeys `json:"keys"`
}
type JSONWebKeys struct {
Kty string `json:"kty"`
Kid string `json:"kid"`
Use string `json:"use"`
N string `json:"n"`
E string `json:"e"`
X5c []string `json:"x5c"`
}
func main() {
// ... the code in this method is untouched...
}
func getPemCert(token *jwt.Token) (string, error) {
cert := ""
resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json")
if err != nil {
return cert, err
}
defer resp.Body.Close()
var jwks = Jwks{}
err = json.NewDecoder(resp.Body).Decode(&jwks)
if err != nil {
return cert, err
}
x5c := jwks.Keys[0].X5c
for k, v := range x5c {
if token.Header["kid"] == jwks.Keys[k].Kid {
cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----"
}
}
if cert == "" {
return cert, errors.New("unable to find appropriate key.")
}
return cert, nil
}Использование промежуточного программного обеспечения JWT
Использование промежуточного программного обеспечения очень просто. Мы просто передаем его как параметр на наши маршруты определения.
...
api.GET("/jokes", authMiddleware(), JokeHandler)
api.POST("/jokes/like/:jokeID", authMiddleware(), LikeJoke)
...Наше main.go Файл должен выглядеть так:
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"os"
"strconv"
jwtmiddleware "github.com/auth0/go-jwt-middleware"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
type Response struct {
Message string `json:"message"`
}
type Jwks struct {
Keys []JSONWebKeys `json:"keys"`
}
type JSONWebKeys struct {
Kty string `json:"kty"`
Kid string `json:"kid"`
Use string `json:"use"`
N string `json:"n"`
E string `json:"e"`
X5c []string `json:"x5c"`
}
type Joke struct {
ID int `json:"id" binding:"required"`
Likes int `json:"likes"`
Joke string `json:"joke" binding:"required"`
}
/** we'll create a list of jokes */
var jokes = []Joke{
Joke{1, 0, "Did you hear about the restaurant on the moon? Great food, no atmosphere."},
Joke{2, 0, "What do you call a fake noodle? An Impasta."},
Joke{3, 0, "How many apples grow on a tree? All of them."},
Joke{4, 0, "Want to hear a joke about paper? Nevermind it's tearable."},
Joke{5, 0, "I just watched a program about beavers. It was the best dam program I've ever seen."},
Joke{6, 0, "Why did the coffee file a police report? It got mugged."},
Joke{7, 0, "How does a penguin build it's house? Igloos it together."},
}
var jwtMiddleWare *jwtmiddleware.JWTMiddleware
func main() {
jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
aud := os.Getenv("AUTH0_API_AUDIENCE")
checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false)
if !checkAudience {
return token, errors.New("Invalid audience.")
}
// verify iss claim
iss := os.Getenv("AUTH0_DOMAIN")
checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false)
if !checkIss {
return token, errors.New("Invalid issuer.")
}
cert, err := getPemCert(token)
if err != nil {
log.Fatalf("could not get cert: %+v", err)
}
result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
return result, nil
},
SigningMethod: jwt.SigningMethodRS256,
})
jwtMiddleWare = jwtMiddleware
// Set the router as the default one shipped with Gin
router := gin.Default()
// Serve the frontend
router.Use(static.Serve("/", static.LocalFile("./views", true)))
api := router.Group("/api")
{
api.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
api.GET("/jokes", authMiddleware(), JokeHandler)
api.POST("/jokes/like/:jokeID", authMiddleware(), LikeJoke)
}
// Start the app
router.Run(":3000")
}
func getPemCert(token *jwt.Token) (string, error) {
cert := ""
resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json")
if err != nil {
return cert, err
}
defer resp.Body.Close()
var jwks = Jwks{}
err = json.NewDecoder(resp.Body).Decode(&jwks)
if err != nil {
return cert, err
}
x5c := jwks.Keys[0].X5c
for k, v := range x5c {
if token.Header["kid"] == jwks.Keys[k].Kid {
cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----"
}
}
if cert == "" {
return cert, errors.New("unable to find appropriate key")
}
return cert, nil
}
// authMiddleware intercepts the requests, and check for a valid jwt token
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Get the client secret key
err := jwtMiddleWare.CheckJWT(c.Writer, c.Request)
if err != nil {
// Token not found
fmt.Println(err)
c.Abort()
c.Writer.WriteHeader(http.StatusUnauthorized)
c.Writer.Write([]byte("Unauthorized"))
return
}
}
}
// JokeHandler returns a list of jokes available (in memory)
func JokeHandler(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, jokes)
}
func LikeJoke(c *gin.Context) {
// Check joke ID is valid
if jokeid, err := strconv.Atoi(c.Param("jokeID")); err == nil {
// find joke and increment likes
for i := 0; i < len(jokes); i++ {
if jokes[i].ID == jokeid {
jokes[i].Likes = jokes[i].Likes + 1
}
}
c.JSON(http.StatusOK, &jokes)
} else {
// the jokes ID is invalid
c.AbortWithStatus(http.StatusNotFound)
}
}Давайте установим jwtmiddleware Библиотеки:
$ go get -u github.com/auth0/go-jwt-middleware $ go get -u github.com/dgrijalva/jwt-go
Давайте исходным наш файл окружающей среды и перезапустите наш сервер приложений:
$ source .env $ go run main.go
Теперь, если мы попробуем доступ к любому из конечных точек, мы будем столкнуться с 401 Несанкционировано ошибка. Это потому, что нам нужно отправить в токен с запросом.
Войти с AUTH0 и реагировать
Давайте реализуем систему входа в систему, чтобы пользователи могли войти или создавать учетные записи и получить доступ к нашим шуткам. Мы добавим к нашему app.jsx Файл следующие учетные данные AUTH0:
Auth0_client_id.Auth0_domainAuth0_callback_url– URL вашего приложенияAUTH0_API_AUDINE.
Нам нужно установить Обратный вызов на что AUTH0 перенаправляет. Перейдите к разделу клиентов на приборной панели. В настройках давайте установим обратный вызов на http://localhost: 3000 :
С учетом учетных данных давайте обновим наши комментарии реагирования.
Компонент приложения
const AUTH0_CLIENT_ID = "aIAOt9fkMZKrNsSsFqbKj5KTI0ObTDPP";
const AUTH0_DOMAIN = "hakaselabs.auth0.com";
const AUTH0_CALLBACK_URL = location.href;
const AUTH0_API_AUDIENCE = "golang-gin";
class App extends React.Component {
parseHash() {
this.auth0 = new auth0.WebAuth({
domain: AUTH0_DOMAIN,
clientID: AUTH0_CLIENT_ID
});
this.auth0.parseHash(window.location.hash, (err, authResult) => {
if (err) {
return console.log(err);
}
if (
authResult !== null &&
authResult.accessToken !== null &&
authResult.idToken !== null
) {
localStorage.setItem("access_token", authResult.accessToken);
localStorage.setItem("id_token", authResult.idToken);
localStorage.setItem(
"profile",
JSON.stringify(authResult.idTokenPayload)
);
window.location = window.location.href.substr(
0,
window.location.href.indexOf("#")
);
}
});
}
setup() {
$.ajaxSetup({
beforeSend: (r) => {
if (localStorage.getItem("access_token")) {
r.setRequestHeader(
"Authorization",
"Bearer " + localStorage.getItem("access_token")
);
}
}
});
}
setState() {
let idToken = localStorage.getItem("id_token");
if (idToken) {
this.loggedIn = true;
} else {
this.loggedIn = false;
}
}
componentWillMount() {
this.setup();
this.parseHash();
this.setState();
}
render() {
if (this.loggedIn) {
return ;
}
return ;
}
}Мы обновили компонент приложения с тремя методами компонентов ( Setup , Parsehash и SetState ) и метод жизненного цикла ComponentWillmount Отказ Parsehash Метод инициализирует AUTH0 Webauth Клиент и анализируют хэш до более читаемого формата, сохраняя их в локальную. Чтобы показать экран блокировки, захватить и хранить токен пользователя и добавьте правильный заголовок авторизации в любые запросы на нашу API
Домашняя компонент
Наш домашний компонент будет обновлен. Мы добавим функциональность для аутентифицировать Метод, который забудит размещенный экран блокировки размещенного блокировки и позволит нашим пользователям войти или регистрацию.
class Home extends React.Component {
constructor(props) {
super(props);
this.authenticate = this.authenticate.bind(this);
}
authenticate() {
this.WebAuth = new auth0.WebAuth({
domain: AUTH0_DOMAIN,
clientID: AUTH0_CLIENT_ID,
scope: "openid profile",
audience: AUTH0_API_AUDIENCE,
responseType: "token id_token",
redirectUri: AUTH0_CALLBACK_URL
});
this.WebAuth.authorize();
}
render() {
return (
);
}
}Компонент logugedin
Мы обновим Logugedin Компонент для общения с нашим API и потяните все шутки. Это пройдет каждую шутку как опора к Шутка Компонент, который делает панель Bootstrap. Давайте напишем те:
class LoggedIn extends React.Component {
constructor(props) {
super(props);
this.state = {
jokes: []
};
this.serverRequest = this.serverRequest.bind(this);
this.logout = this.logout.bind(this);
}
logout() {
localStorage.removeItem("id_token");
localStorage.removeItem("access_token");
localStorage.removeItem("profile");
location.reload();
}
serverRequest() {
$.get("http://localhost:3000/api/jokes", res => {
this.setState({
jokes: res
});
});
}
componentDidMount() {
this.serverRequest();
}
render() {
return (
Log out
Jokeish
Let's feed you with some funny Jokes!!!
{this.state.jokes.map(function(joke, i) {
return ;
})}
);
}
}Шутка компонент
Мы также обновим Шутка Компонент для форматирования каждого элемента шутки передан ему из родительского компонента ( loggedin ). Мы также добавим Как Метод, который будет увеличиваться как шутка.
class Joke extends React.Component {
constructor(props) {
super(props);
this.state = {
liked: "",
jokes: []
};
this.like = this.like.bind(this);
this.serverRequest = this.serverRequest.bind(this);
}
like() {
let joke = this.props.joke;
this.serverRequest(joke);
}
serverRequest(joke) {
$.post(
"http://localhost:3000/api/jokes/like/" + joke.id,
{ like: 1 },
res => {
console.log("res... ", res);
this.setState({ liked: "Liked!", jokes: res });
this.props.jokes = res;
}
);
}
render() {
return (
)
}
}Положить все вместе
С помощью UI и API завершены, мы можем проверить наше приложение. Мы начнем, загрузив наш сервер Источник .env && Go Run Main.go , а затем мы перейдем к http://localhost: 3000 из любого браузера. Вы должны увидеть Главная Компонент с кнопкой входа. Нажатие на кнопку Signin будет перенаправлять на страницу Hosted Lock (создайте учетную запись или вход в систему), чтобы продолжить использование приложения.
Дом:
Auth0 Hosted Lock Screen:
Logugedin Просмотр приложений:
Заключение
Поздравляю! Вы узнали, как создать приложение и API с GO и GIN Framework.
Я пропустил что-то важное? Дайте мне знать об этом в комментариях.
Вы можете сказать привет мне в Twitter @Codehakase.
Оригинал: “https://www.freecodecamp.org/news/how-to-build-a-web-app-with-go-gin-and-react-cffdc473576/”