restructure repo, separate sample app from docker configs
This commit is contained in:
31
05-example-web-application/Makefile
Normal file
31
05-example-web-application/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
.PHONY: run-postgres
|
||||
run-postgres:
|
||||
@echo Starting postgres container
|
||||
-docker run \
|
||||
-e POSTGRES_PASSWORD=foobarbaz \
|
||||
-p 5432:5432 \
|
||||
postgres:15.1-alpine
|
||||
|
||||
.PHONY: run-api-node
|
||||
run-api-node:
|
||||
@echo Starting node api
|
||||
cd api-node && \
|
||||
PGUSER=postgres \
|
||||
PGHOST=localhost \
|
||||
PGPASSWORD=foobarbaz \
|
||||
PGDATABASE=postgres \
|
||||
PGPORT=5432 \
|
||||
npm run dev
|
||||
|
||||
.PHONY: run-api-golang
|
||||
run-api-golang:
|
||||
@echo Starting golang api
|
||||
cd api-golang && \
|
||||
DATABASE_URL=postgres://postgres:foobarbaz@localhost:5432/postgres \
|
||||
go run main.go
|
||||
|
||||
.PHONY: run-client-react
|
||||
run-client-react:
|
||||
@echo Starting react client
|
||||
cd client-react && \
|
||||
npm run dev
|
||||
16
05-example-web-application/README.md
Normal file
16
05-example-web-application/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
Docker Desktop: https://docs.docker.com/get-docker/
|
||||
|
||||
Docker Engine: https://get.docker.com/
|
||||
|
||||
Hello World:
|
||||
```
|
||||
docker run docker/whalesay cowsay "Hey Team! 👋"
|
||||
```
|
||||
|
||||
Run Postgres:
|
||||
```
|
||||
docker run \
|
||||
--env POSTGRES_PASSWORD=foobarbaz \
|
||||
--publish 5432:5432 \
|
||||
postgres:15.1-alpine
|
||||
```
|
||||
3
05-example-web-application/api-golang/.dockerignore
Normal file
3
05-example-web-application/api-golang/.dockerignore
Normal file
@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
README.md
|
||||
Dockerfile*
|
||||
4
05-example-web-application/api-golang/Makefile
Normal file
4
05-example-web-application/api-golang/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
.PHONY: run-local
|
||||
run-local:
|
||||
DATABASE_URL=postgres://postgres:foobarbaz@localhost:5432/postgres \
|
||||
go run main.go
|
||||
11
05-example-web-application/api-golang/README.md
Normal file
11
05-example-web-application/api-golang/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
```
|
||||
go mod init api-golang
|
||||
go get -u github.com/gin-gonic/gin
|
||||
go get -u github.com/lib/pq
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
go run src/main.go
|
||||
```
|
||||
34
05-example-web-application/api-golang/database/db.go
Normal file
34
05-example-web-application/api-golang/database/db.go
Normal file
@ -0,0 +1,34 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
var conn *pgxpool.Pool
|
||||
|
||||
// InitDB initialize the database pool and returns error
|
||||
func InitDB(connString string) error {
|
||||
var err error
|
||||
conn, err = pgxpool.New(context.Background(), connString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetTime(ctx *gin.Context) time.Time {
|
||||
var tm time.Time
|
||||
|
||||
err := conn.QueryRow(ctx, "SELECT NOW() as now;").Scan(&tm)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return tm
|
||||
}
|
||||
34
05-example-web-application/api-golang/go.mod
Normal file
34
05-example-web-application/api-golang/go.mod
Normal file
@ -0,0 +1,34 @@
|
||||
module api-golang
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.8.2
|
||||
github.com/jackc/pgx/v5 v5.2.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||
github.com/jackc/puddle/v2 v2.1.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/ugorji/go/codec v1.2.8 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
111
05-example-web-application/api-golang/go.sum
Normal file
111
05-example-web-application/api-golang/go.sum
Normal file
@ -0,0 +1,111 @@
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
|
||||
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
||||
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
|
||||
github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
|
||||
github.com/jackc/puddle/v2 v2.1.2 h1:0f7vaaXINONKTsxYDn4otOAiJanX/BMeAtY//BXqzlg=
|
||||
github.com/jackc/puddle/v2 v2.1.2/go.mod h1:2lpufsF5mRHO6SuZkm0fNYxM6SWHfvyFj62KwNzgels=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/ugorji/go/codec v1.2.8 h1:sgBJS6COt0b/P40VouWKdseidkDgHxYGm0SAglUHfP0=
|
||||
github.com/ugorji/go/codec v1.2.8/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 h1:ZrnxWX62AgTKOSagEqxvb3ffipvEDX2pl7E1TdqLqIc=
|
||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
36
05-example-web-application/api-golang/main.go
Normal file
36
05-example-web-application/api-golang/main.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"api-golang/database"
|
||||
)
|
||||
|
||||
func init() {
|
||||
errDB := database.InitDB(os.Getenv("DATABASE_URL"))
|
||||
if errDB != nil {
|
||||
log.Fatalf("⛔ Unable to connect to database: %v\n", errDB)
|
||||
} else {
|
||||
log.Println("DATABASE CONNECTED 🥇")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
r := gin.Default()
|
||||
var tm time.Time
|
||||
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
tm = database.GetTime(c)
|
||||
c.JSON(200, gin.H{
|
||||
"api": "golang",
|
||||
"now": tm,
|
||||
})
|
||||
})
|
||||
r.Run() // listen and serve on 0.0.0.0:8080
|
||||
}
|
||||
94
05-example-web-application/api-golang/nohup.out
Normal file
94
05-example-web-application/api-golang/nohup.out
Normal file
@ -0,0 +1,94 @@
|
||||
2023/01/27 08:34:41 DATABASE CONNECTED 🥇
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] GET / --> main.main.func1 (3 handlers)
|
||||
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
|
||||
[GIN-debug] Listening and serving HTTP on :8080
|
||||
QueryRow failed: failed to connect to `host=db user=postgres database=postgres`: hostname resolving error (lookup db: no such host)
|
||||
exit status 1
|
||||
2023/01/27 08:36:16 DATABASE CONNECTED 🥇
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] GET / --> main.main.func1 (3 handlers)
|
||||
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
|
||||
[GIN-debug] Listening and serving HTTP on :8080
|
||||
[GIN] 2023/01/27 - 08:36:20 | 200 | 76.361836ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:20 | 404 | 551ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:20 | 200 | 2.305566ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 404 | 584ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 200 | 2.258435ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 404 | 494ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 200 | 1.808336ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 404 | 530ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 200 | 1.571416ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 404 | 599ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 200 | 1.787527ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:21 | 404 | 657ns | ::1 | GET "/favicon.ico"
|
||||
2023/01/27 08:36:24 DATABASE CONNECTED 🥇
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] GET / --> main.main.func1 (3 handlers)
|
||||
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
|
||||
[GIN-debug] Listening and serving HTTP on :8080
|
||||
[GIN-debug] [ERROR] listen tcp :8080: bind: address already in use
|
||||
[GIN] 2023/01/27 - 08:36:28 | 200 | 1.946844ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:28 | 404 | 828ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:28 | 200 | 1.60934ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:28 | 404 | 537ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:29 | 200 | 1.96418ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:29 | 404 | 519ns | ::1 | GET "/favicon.ico"
|
||||
[GIN] 2023/01/27 - 08:36:29 | 200 | 1.956822ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:36:29 | 404 | 554ns | ::1 | GET "/favicon.ico"
|
||||
2023/01/27 08:39:10 DATABASE CONNECTED 🥇
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] GET / --> main.main.func1 (3 handlers)
|
||||
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
|
||||
[GIN-debug] Listening and serving HTTP on :8080
|
||||
[GIN-debug] [ERROR] listen tcp :8080: bind: address already in use
|
||||
2023/01/27 08:39:21 DATABASE CONNECTED 🥇
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] GET / --> main.main.func1 (3 handlers)
|
||||
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
|
||||
[GIN-debug] Listening and serving HTTP on :8080
|
||||
[GIN-debug] [ERROR] listen tcp :8080: bind: address already in use
|
||||
[GIN] 2023/01/27 - 08:39:29 | 200 | 2.692438ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:30 | 200 | 2.633877ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:31 | 200 | 2.567795ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:31 | 200 | 3.106938ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:32 | 200 | 3.875721ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:32 | 200 | 2.054595ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:32 | 200 | 3.713489ms | ::1 | GET "/"
|
||||
[GIN] 2023/01/27 - 08:39:32 | 200 | 1.914952ms | ::1 | GET "/"
|
||||
signal: terminated
|
||||
1
05-example-web-application/api-node/.dockerignore
Normal file
1
05-example-web-application/api-node/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
||||
12
05-example-web-application/api-node/Makefile
Normal file
12
05-example-web-application/api-node/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
.PHONY: run-local
|
||||
run-local:
|
||||
PGUSER=postgres \
|
||||
PGHOST=localhost \
|
||||
PGPASSWORD=foobarbaz \
|
||||
PGDATABASE=postgres \
|
||||
PGPORT=5432 \
|
||||
node ./src/index.js
|
||||
|
||||
.PHONY: build-naive
|
||||
build-naive:
|
||||
docker build --file ./Dockerfile.naive .
|
||||
8
05-example-web-application/api-node/README.md
Normal file
8
05-example-web-application/api-node/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
```
|
||||
npm init
|
||||
npm install express pg
|
||||
```
|
||||
|
||||
```
|
||||
node src/index.js
|
||||
```
|
||||
1150
05-example-web-application/api-node/package-lock.json
generated
Normal file
1150
05-example-web-application/api-node/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
05-example-web-application/api-node/package.json
Normal file
20
05-example-web-application/api-node/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "api-node",
|
||||
"version": "1.0.0",
|
||||
"description": "simple api that connects to postgres",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"dev": "nodemon src/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"morgan": "^1.10.0",
|
||||
"pg": "^8.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.20"
|
||||
}
|
||||
}
|
||||
25
05-example-web-application/api-node/src/db.js
Normal file
25
05-example-web-application/api-node/src/db.js
Normal file
@ -0,0 +1,25 @@
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const pool = new Pool();
|
||||
|
||||
// the pool will emit an error on behalf of any idle clients
|
||||
// it contains if a backend error or network partition happens
|
||||
pool.on('error', (err, client) => {
|
||||
console.error('Unexpected error on idle client', err);
|
||||
process.exit(-1);
|
||||
});
|
||||
|
||||
// async/await - check out a client
|
||||
const getDateTime = async () => {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
const res = await client.query('SELECT NOW() as now;');
|
||||
return res.rows[0];
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { getDateTime };
|
||||
28
05-example-web-application/api-node/src/index.js
Normal file
28
05-example-web-application/api-node/src/index.js
Normal file
@ -0,0 +1,28 @@
|
||||
const { getDateTime } = require('./db');
|
||||
|
||||
const express = require('express');
|
||||
const morgan = require('morgan');
|
||||
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
// setup the logger
|
||||
app.use(morgan('tiny'));
|
||||
|
||||
app.get('/', async (req, res) => {
|
||||
const dateTime = await getDateTime();
|
||||
const response = dateTime;
|
||||
response.api = 'node';
|
||||
res.send(response);
|
||||
});
|
||||
|
||||
const server = app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
debug('SIGTERM signal received: closing HTTP server');
|
||||
server.close(() => {
|
||||
debug('HTTP server closed');
|
||||
});
|
||||
});
|
||||
1
05-example-web-application/client-react/.dockerignore
Normal file
1
05-example-web-application/client-react/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
||||
24
05-example-web-application/client-react/.gitignore
vendored
Normal file
24
05-example-web-application/client-react/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
5
05-example-web-application/client-react/README.md
Normal file
5
05-example-web-application/client-react/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
```
|
||||
npm create vite@latest
|
||||
npm i @tanstack/react-query axios
|
||||
```
|
||||
|
||||
12
05-example-web-application/client-react/index.html
Normal file
12
05-example-web-application/client-react/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>DevOps Directive Docker Course</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
05-example-web-application/client-react/nginx.conf
Normal file
24
05-example-web-application/client-react/nginx.conf
Normal file
@ -0,0 +1,24 @@
|
||||
server {
|
||||
listen 80;
|
||||
location /api/golang/ {
|
||||
resolver 127.0.0.1;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Server $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://api-golang:8080/;
|
||||
}
|
||||
location /api/node/ {
|
||||
resolver 127.0.0.1;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Server $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://api-node:3000/;
|
||||
}
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html =404;
|
||||
}
|
||||
|
||||
include /etc/nginx/extra-conf.d/*.conf;
|
||||
}
|
||||
1024
05-example-web-application/client-react/package-lock.json
generated
Normal file
1024
05-example-web-application/client-react/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
05-example-web-application/client-react/package.json
Normal file
23
05-example-web-application/client-react/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "client-react",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^4.22.4",
|
||||
"axios": "^1.2.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@vitejs/plugin-react-swc": "^3.0.0",
|
||||
"vite": "^4.0.0"
|
||||
}
|
||||
}
|
||||
BIN
05-example-web-application/client-react/public/favicon.ico
Normal file
BIN
05-example-web-application/client-react/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
41
05-example-web-application/client-react/src/App.css
Normal file
41
05-example-web-application/client-react/src/App.css
Normal file
@ -0,0 +1,41 @@
|
||||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.react:hover {
|
||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
a:nth-of-type(2) .logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
46
05-example-web-application/client-react/src/App.jsx
Normal file
46
05-example-web-application/client-react/src/App.jsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
useQuery,
|
||||
} from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
import './App.css'
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
function Example(props) {
|
||||
const { isLoading, error, data, isFetching } = useQuery({
|
||||
queryKey: [props.api],
|
||||
queryFn: () =>
|
||||
axios
|
||||
.get(`${props.api}`)
|
||||
.then((res) => res.data),
|
||||
});
|
||||
|
||||
if (isLoading) return `Loading ${props.api}... `;
|
||||
|
||||
if (error) return "An error has occurred: " + error.message;
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<p>---</p>
|
||||
<p>API: {data.api}</p>
|
||||
<p>Time from DB: {data.now}</p>
|
||||
<div>{isFetching ? "Updating..." : ""}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<h1>Hey Team! 👋</h1>
|
||||
<Example api="/api/golang/"/>
|
||||
<Example api="/api/node/"/>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App
|
||||
70
05-example-web-application/client-react/src/index.css
Normal file
70
05-example-web-application/client-react/src/index.css
Normal file
@ -0,0 +1,70 @@
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
10
05-example-web-application/client-react/src/main.jsx
Normal file
10
05-example-web-application/client-react/src/main.jsx
Normal file
@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
26
05-example-web-application/client-react/vite.config.js
Normal file
26
05-example-web-application/client-react/vite.config.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import dns from 'dns';
|
||||
|
||||
dns.setDefaultResultOrder('verbatim');
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
proxy: {
|
||||
'/api/golang': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api\/golang/, ''),
|
||||
secure: false,
|
||||
},
|
||||
'/api/node': {
|
||||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api\/node/, ''),
|
||||
secure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user