Building APIs and Web Apps with Golang
go get github.com/julienschmidt/httprouter@v1
curl -i localhost:4000/v1/healthcheck
curl -i -X OPTIONS localhost:4000/v1/healthcheck
curl -i -X POST localhost:4000/v1/movies
curl -i localhost:4000/v1/movies/123
Supported Go types to JSON types
bool ⇒ JSON boolean
string ⇒ JSON string
int*, uint*, float*, rune ⇒ JSON number
array, slice ⇒ JSON array
struct, map ⇒ JSON object
slice ofstucts ⇒ array of objects
nil pointers, interface values, slices, maps, etc. ⇒ JSON null
chan, func, complex* ⇒ Not supported
time.Time ⇒ RFC3339-format JSON string
[]byte ⇒ Base64-encoded JSON string
Encoding of nested objects is supported. So, for example, if you have a slice of structs in Go that will encode to an array of objects in JSON.
Any pointer values will encode as the value pointed to.
Channels, functions and complex number types cannot be encoded. If you try to do so you’ll get a json.UnsupportedTypeError error at runtime.
BODY=' {"title":"Moana","year":2016,"runtime":107, "genres":["animation","adventure"]}'
curl -i -d " $BODY " localhost:4000/v1/movies
JSON type to Supported Go types
JSON boolean ⇒ bool
JSON string ⇒ string
JSON number ⇒ int*, uint*, float*, rune
JSON array ⇒ array, slice
JSON object ⇒ struct, map
sudo apt install postgresql
psql --host=localhost --dbname=greenlight --username=greenlight
export GREENLIGHT_DB_DSN=' postgres://greenlight:pa55word@localhost:5432/greenlight?sslmode=disable'
go get github.com/lib/pq@v1
curl -s https://packagecloud.io/install/repositories/golang-migrate/migrate/script.deb.sh | sudo bash
$ apt-get install -y migrate
migrate create -seq -ext=.sql -dir=./migrations create_movies_table
migrate create -seq -ext=.sql -dir=./migrations add_movies_check_constraints
migrate -path=./migrations -database=$GREENLIGHT_DB_DSN up
migrate -path=./migrations -database=$EXAMPLE_DSN version
migrate -path=./migrations -database=$EXAMPLE_DSN goto 1
migrate -path=./migrations -database=$EXAMPLE_DSN up
migrate -path=./migrations -database=$EXAMPLE_DSN down
SELECT * FROM schema_migrations;
BODY=' {"title":"Moana","year":2016,"runtime":107, "genres":["animation","adventure"]}'
curl -i -d " $BODY " localhost:4000/v1/movies
BODY=' {"title":"Black Panther","year":2018,"runtime":134,"genres":["action","adventure"]}'
curl -i -d " $BODY " localhost:4000/v1/movies
BODY=' {"title":"Deadpool","year":2016, "runtime":108,"genres":["action","comedy"]}'
curl -i -d " $BODY " localhost:4000/v1/movies
BODY=' {"title":"The Breakfast Club","year":1986, "runtime":96,"genres":["drama"]}'
curl -i -d " $BODY " localhost:4000/v1/movies
curl -i localhost:4000/v1/movies/2
Database PUT Update A Movie
BODY=' {"title":"Black Panther","year":2018,"runtime":134,"genres":["sci-fi","action","adventure"]}'
curl -X PUT -d " $BODY " localhost:4000/v1/movies/2
Database PATCH Update A Movie
curl -X PATCH -d ' {"year": 1985}' localhost:4000/v1/movies/4
Database Concurrent Update A Movie
xargs -I % -P8 curl -X PATCH -d ' {"runtime":97}' " localhost:4000/v1/movies/4" < <( printf ' %s\n' {1..8})
curl -X DELETE localhost:4000/v1/movies/3
When using curl to send a request containing more than one query string parameter, you must wrap the URL in quotes for it to work correctly.
curl " localhost:4000/v1/movies?title=moana&genres=animation,adventure&page=1&page_size=5&sort=year"
curl localhost:4000/v1/movies
curl " localhost:4000/v1/movies?title=black+panther"
curl " localhost:4000/v1/movies?genres=adventure"
curl " localhost:4000/v1/movies?title=moana&genres=animation,adventure"
Database Full Text Search
curl " localhost:4000/v1/movies?title=panther"
curl " localhost:4000/v1/movies?title=the+club"
migrate create -seq -ext .sql -dir ./migrations add_movies_indexes'
migrate -path ./migrations -database $GREENLIGHT_DB_DSN up
curl " localhost:4000/v1/movies?sort=-title"
curl " localhost:4000/v1/movies?sort=-runtime"
Database Paginating Lists
curl " localhost:4000/v1/movies?page_size=2"
curl " localhost:4000/v1/movies?page_size=2&page=2"
Returning Pagination Metadata
curl " localhost:4000/v1/movies?page=1&page_size=2"
$ curl localhost:4000/v1/movies? genres=adventure
go get golang.org/x/time/rate@latest
for i in {1..6}; do curl http://localhost:4000/v1/healthcheck; done
go run ./cmd/api/ -limiter-enabled=false
User Model Setup And Regristration
migrate create -seq -ext=.sql -dir=./migrations create_users_table
migrate -path=./migrations -database=$GREENLIGHT_DB_DSN up
Encrypting User Passwords
go get golang.org/x/crypto/bcrypt@latest
curl -i -d " $BODY " localhost:4000/v1/users
go get github.com/go-mail/mail/v2@v2
curl -w ' \nTime: %{time_total}\n' -d " $BODY " localhost:4000/v1/users
curl -w ' \nTime: %{time_total}\n' -d " $BODY " localhost:4000/v1/users
curl -w ' \nTime: %{time_total}\n' -d " $BODY " localhost:4000/v1/users
curl -w ' \nTime: %{time_total}\n' -d " $BODY " localhost:4000/v1/users
Activate User: Set up Tokens Database Table
migrate create -seq -ext .sql -dir ./migrations create_tokens_table
migrate -path=./migrations -database=$GREENLIGHT_DB_DSN up
Register User: Send Activation Token
curl -w ' \nTime: %{time_total}\n' -d " $BODY " localhost:4000/v1/users
Activate User with Email Activation Token
curl -X PUT -d ' {"token": "ZYGQTPU5PKKJRY7SFOAMKXPGQY"}' localhost:4000/v1/users/activated
Generating Authentication Token
curl -i -d " $BODY " localhost:4000/v1/tokens/authentication
Authenticate Authentication Token with Authorization Header
curl -d ' {"email": "[email protected] ", "password": "pa55word"}' localhost:4000/v1/tokens/authentication
curl -i -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/healthcheck
Authenticate Authentication Token with Authorization Header of Activated User
SELECT email FROM users WHERE activated = true;
curl -i -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/movies/1
Permissions SQL Migrations
migrate create -seq -ext .sql -dir ./migrations add_permissions
migrate -path ./migrations -database $GREENLIGHT_DB_DSN up
Set Read/Write Permissions for a User and give access
-- Give all users the 'movies:read' permission
INSERT INTO users_permissions
SELECT id, (SELECT id FROM permissions WHERE code = ' movies:read' ) FROM users;
-- Give [email protected] the 'movies:write' permission
INSERT INTO users_permissions
VALUES (
(SELECT id FROM users WHERE email = ' [email protected] ' ),
(SELECT id FROM permissions WHERE code = ' movies:write' )
);
-- List all activated users and their permissions.
SELECT email, array_agg(permissions .code ) as permissions
FROM permissions
INNER JOIN users_permissions ON users_permissions .permission_id = permissions .id
INNER JOIN users ON users_permissions .user_id = users .id
WHERE users .activated = true
GROUP BY email;
curl -d " $BODY " localhost:4000/v1/tokens/authentication
curl -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/movies/1
curl -X DELETE -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/movies/1
curl -d " $BODY " localhost:4000/v1/tokens/authentication
curl -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/movies/1
curl -X DELETE -H " Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXX" localhost:4000/v1/movies/1
Grant Permissions to New User which registers an account
curl -d " $BODY " localhost:4000/v1/users
SELECT email, code FROM users
INNER JOIN users_permissions ON users .id = users_permissions .user_id
INNER JOIN permissions ON users_permissions .permission_id = permissions .id
WHERE users .email = ' [email protected] ' ;
go run ./cmd/examples/cors/simple
go install honnef.co/go/tools/cmd/staticcheck@latest
Display binary version number
go install github.com/rakyll/hey@latest
go run ./cmd/api/ -limiter-enabled=false
hey -d " $BODY " -m " POST" http://localhost:4000/v1/tokens/authentication
curl http://localhost:4000/debug/vars