[
](# resting-api-in-go) restful apis in Go
This is an intermediate Go project that runs in Go with a project structure optimized for RESTful API services. The API in this project is designed based on solid and generic principles and connects to a local MySQL database.
The highlights of this project are as follows
- The RESTful API displays standard CRUD operations on database tables.
- The project has a clean architecture, and testing has been covered.
- Data validation
- It uses JWT-BASED authentication and authentication middleware.
- Each token expires within 15 minutes to prevent system errors.
- Error handling is done with clear responses.
- With the help of tokens created by JWT, it came up with a structured log of user names and passwords that lasted 15 minutes. After that, users can create TODO.
- The following software packages were used during the development of the project
- Routing: Mux
- Database driver: Mysql
- JWT: go – JWT
- Test: Testify
[
[# get-started] # get-started
If you haven’t touched Go before, you should visit this website.
After installing Go, you should run the following command to experience the project
# download the starter code
git clone https://github.com/Kivanc10/golang-rest-api-with-mysql.git
# open the code
Copy the code
After that, you have a RESTful API running at http://127.0.0.1:8080. It gives us the following endpoints
GET /users
: It gives us a list of all the logged in users.POST /signUp
: It allows users to register. It stores user information in the database and creates tokens using JWT. It accepts such additional data.PersonID
It can be anything, because the database schedules automatic increments.-
{ Copy the code
POST /signIn
: Authenticates and logs in. It creates the token again with JWT. It accepts additional data, as described above.GET /users/me
: It allows the user to access his information. To do this, the user must be authenticated or the system will not let it happen.PUT /users/update/me
: It updates the current authenticated user with the received data. To do this, the user must be authenticated. The attachment data it accepts is as follows.-
{ Copy the code
-
DELETE /user/me
: It deletes the current authenticated user. To do this, the user must be authenticated.GET /users/logout/me
: it allows the user to unregister all tokens. To do this, the user must be authenticated. The user will not be removed from the database.POST /todo
: it allows users to create todos. To do this, the user must be authenticated. It accepts such attachment data.-
{ Copy the code
-
GET /todos
: It lists all todos created by authenticated users.GET /todos/me
: It lists only the Todos belonging to the current authenticated user.
[
[# if-you-have-api-client-tools-like-postman-you-can-handle-operations-easily] [#if-you-have-api-client-tools-like-postman-you can handle-operations-easily] [#if-you-have-api-client-tools-like-postman-you can handle-operations-easily] [#if-you-have-api-client-tools-like-postman-you can handle-operations-easily] You can handle complex operations with ease.
If you create a new environment in Postman and declare the variables you want to use, you make everything clear.
You should also add a set of code to the test section of some requests that automatically schedule them with the payload token of the request header. (signup, login, getme, update, logout) before the code, you should be in the authorization section of the collection editor define an environment called authToken token.
Then paste the code to signup, login, getme, update, logout request.
if
Copy the code
After that, your request header will be automatically updated with a valid token for authentication.
You have to make sure you choose the environment
[
](# how-to-use-endPoints) How to use endpoints
# sign up the user via POST /signUp curl -X POST -H "Content-Type: application/json" -d `{ "PersonID":0,"UserName":"sample user name","Password":"12312321"}` http://localhost:8080/signUp # it should return response.header with jwt and token # sign in with user via POST /signIn curl -X POST -H "Content-Type: application/json" -d `{ "PersonID":0,"UserName":"sample user name","Password":"12312321"}` http://localhost:8080/signIn # it should return response.Header with jwt and token # save token during the loggedin and inherit auth from postman environment,it handles itself curl -X GET -H "Authorization: Bearer ... JWT token here..." http://localhost:8080/users/me # to create todos for the user authenticated curl -X POST -H "Authorization: Bearer ... JWT token here..." -d `{"Context" : "sample todo"}` http://localhost:8080/todo # it returns the saved todo belong to the user authenticatedCopy the code
[
](#project-layout
.
Copy the code
[
](# working-with-JwT-based-authenticaton-and-auth-middleware) works with JWt-based authentication and authentication middleware
[
](#jwt)JWT
- JSON Web Token (JWT) is a standalone way to securely transfer information between parties in the form of JSON objects. If you will be dealing with authorization and information exchange, your best bet is to use JWT.
[
](#auth-middleware) authenticates middleware
- We already have the authentication service with its adapters and the login middleware that we can create to check the authenticated user and redirect to/login page if the user is not authenticated.
In this project, if necessary, we create tokens such as signUp,signIn… To make and save changes. We then use Auth middleware to access the current user if its token is valid. Auth middleware enables us to design a true security system.
[
[#to-create-tokens] Create tokens
“, atClaims)
return token, nil // return token created and no error if succeed
}
“>
func
Copy the code
[
](#to-integrate-auth-middleware) integrate certified middleware
%s and len -> %d/n”, authHeader, len(authHeader)) if len(authHeader) ! = 2 || authHeader[0] == “null” { // [“Bearer”, “Token…”] If not, // ftt.println (“Malformed Token”) w.rite header (http.statusunauthorized) w.rite ([]byte(“Malformed Token”)) Log.Fatal(“Malformed token”)} jwtToken := authHeader[1] // obtained
The token
token, err := jwt.
Parse(jwtToken)
Parse(jwtToken, func(token *jwt.Token) (interface{}, error) { // parse the token if _, ok := token.(*jwt.SigningMethodHMAC); ! ok { return nil, fmt.Errorf(“Unexpected signing method: %v”, token.Header[“alg”])} return []byte(mySignInKey), nil}) If claims, ok := token.(jwt.mapClaims); CTX := context.withValue (r.coltext (), “props”, Claims) // props is the context keyword // Access the context value in the handler next.ServeHTTP(w, r.ithContext (CTX)
))
// If successful, Println(“token err -> “, err) // r.haader.Set(” token err -> “, err) jwtToken) //DelTokenIfExpired(jwtToken) // usernameInter := claims[“user_name”] // if username, ok := usernameInter.Stringer); ok { // person := dbop.GetPersonToDelToken(username.String()) // dbop.DeleteTokenIfExpired(person
) // }
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(“you are Unauthorized or your token is expired”) ) }
}
“>
func
Copy the code
[
](#database-scheme
GitHub
Github.com/Kivanc10/go…