Cara menggunakan rest-api php mysql github

Cara menggunakan rest-api php mysql github

Golang is a general-purpose programming language built for the multi-core reality of today’s computers (upwork).

In this article:

We will build a blog application where a user can:

  • Signup (Register)
  • Edit his account
  • Shutdown (Delete his account)
  • Create a blog post
  • Edit blog post created by him
  • View all blog posts
  • View a particular blog post
  • View other blog posts published by other users
  • Delete blog post created by him

This API will be built with:

  • Go
  • GORM (A Golang ORM)
  • JWT
  • Postgres
  • Mysql
  • Gorilla Mux (For HTTP routing and URL matcher)

You might be wondering seeing Postgres and Mysql. The API will be built in a way that you can decide to use Mysql or Postgres driver, simply by changing the configuration in the .env.

All methods and endpoints will be thoroughly tested. Table tests will also be used to test every possible case for a particular functionality.

In Future Articles:

This article is just the first part. There will be future articles that will explain how to:

  • Dockerize the API
  • Deploy on Kubernetes
  • Integrate Travis, Coveralls, Code Climate, etc
  • Host the API on AWS, Digital Ocean and/or Heroku.
  • Consume the API endpoints using React/Vue

I actually summed everything together in this article here. Where I built a Forum App using Gin Framework. React is used as the Frontend Stack.

Let’s Begin!

In case you just want to see the code, Get the source code for this article on github

Step 1: Basic Setup

Create the directory the project will live in. This can be created anywhere on your computer. Trust me!

Let’s call it fullstack

mkdir fullstack

Next, initiate go modules which makes dependency version information explicit and easier to manage

go mod init github.com/{username}/{projectdir}

Where {username} is your github username and {projectdir} is the directory created above. For my case, I will have:

go mod init github.com/victorsteven/fullstack

We will be using third party packages in this application. If you have never installed them before, you can run the following commands:

go get github.com/badoux/checkmail
go get github.com/jinzhu/gorm
go get golang.org/x/crypto/bcrypt
go get github.com/dgrijalva/jwt-go
go get github.com/gorilla/mux
go get github.com/jinzhu/gorm/dialects/mysql" //If using mysql
go get github.com/jinzhu/gorm/dialects/postgres //If using postgres
go get github.com/joho/godotenv
go get gopkg.in/go-playground/assert.v1

Next, create an api and tests directory inside the fullstack directory

mkdir api && mkdir tests

Create the .env file to house our environmental variables

touch .env

At this point this is the structure we have:

fullstack
├── api
├── tests
├── .env
└── go.mod

Step 2: Env Details

Let’s settle the database connection details now.

Open the fullstack folder in your favorite editor (VSCode, Goland, etc). Then open the .env file

Observe that we have the postgres and mysql details in the .env file.

The default connection is postgres. If you want to use mysql, simply comment the postgres and uncomment the mysql details in the .env.

Note, you can only use one connection at a time. But you can make things fancy (not recommended) by using Postgres for live and mysql for testing. Well, you decide what to do.

Step 3: Create Models

Inside the api create the models directory

mkdir models

Since we are building a blog, we will have two model files for now: “User” and “Post

It is better that the entire file is posted, rather than parts, to avoid any confusion.

The User model:

In the path api/models create the user model:

touch User.go

The Post model:

In the path api/models create the post model

touch Post.go

Step 4: Create a Custom Response

Before we create controllers that will interact with the above defined models, we will create a custom response package. This will be used for the http responses.

Inside the api directory, create the responses directory

mkdir responses

Then create the json.go file in the path: api/responses

touch json.go
json.go

Step 5: Create JSON Web Tokens (JWT)

Remember that users need to be authenticated before they can: Update or Shutdown their accounts, Create, Update, and Delete Posts.

Let’s write a package that will help us generate a JWT token that will enable the user to perform the above actions.

Inside the api directory, create the auth package (directory).

mkdir auth

Create the token.go file in the path: api/auth

touch token.go

This is the content:

token.go

Observe from the token.go file that we assigned the import: “github.com/dgrijalva/jwt-go” to jwt.

Step 6: Create Middlewares

We will create two main middlewares:

  • SetMiddlewareJSON: This will format all responses to JSON
  • SetMiddlewareAuthentication: This will check for the validity of the authentication token provided.

Inside the api directory, create the middlewares package(directory)

mkdir middlewares

Then create a middlewares.go file in the path api/middlewares

touch middlewares.go
middlewares.go

Step 7: Create Custom Error Handling

To format some error messages in a more readable manner, we need to a create a package to help us achieve that.

Remember we created a utils directory earlier. We will create that package inside this directory.

In the path api/utils create the package formaterror

mkdir formaterror

Then create a formaterror.go file in the path: api/utils/formaterror

formaterror.go

When we “wire” the controllers and routes package, the above will make sense to you.

Step 8: Create Controllers

Now we have reached the meat of the application. Let's create the controllers package that will interact with our models package:

Inside the api directory, create the controllers (directory)

mkdir controllers

In the path api/controllers create a file called base.go

touch base.go

This file will have our database connection information, initialise our routes, and start our server:

base.go

Observe the underscore we used when we imported the mysql and postgres packages. You can simply import the one you need, except if you want to experiment with both.

Also observe that we called the initializeRoutes()method. It will be defined in the routes.go file shortly.

Let’s create a home_controller.go file that welcomes us to the API:

In the path: api/controllers

touch home_controller.go
home_controller.go

Let’s Create the users_controller.go file:

In the path: api/controllers

touch users_controller.go

Let’s create the posts_controller.go file:

In the path: api/controllers

touch posts_controller.go

Let's create the login_controller.go file:

In the path: api/controllers

touch login_controller.go
login_controller.go

Now, let’s light up the whole place up by creating the routes.go file

In the path: api/controllers

touch routes.go
routes.go

Step 9: Seeding the Database with Dummy Data

If you wish, you can add dummy data to the database before adding a real one.

Let’s create a seed package to achieve that:

In the path api/, create the seed package

mkdir seed

Then create the seeder.go file:

touch seeder.go

Step 10: Create an Entry File to the API Directory

We need to call the initialize() method we defined in the base.go file and also the seeder we define above. We will create a file called server.go.

In the path api/

touch server.go

This is the content:

Step 11: Create app entry file: main.go

Create the main.go file in the root of the fullstack directory

touch main.go

This is the file that actually “start the engine”. We will call the Run method that was defined in server.go file

This is the content:

main.go

Before we run the app, let's confirm your directory structure:

fullstack
├── api
│ └── auth
│ │ └── token.go
│ ├── controllers
│ │ ├── base.go
│ │ ├── home_controller.go
│ │ ├── login_controller.go
│ │ ├── posts_controller.go
│ │ ├── users_controller.go
│ │ └── routes.go
│ ├── middlewares
│ │ └── middlewares.go
│ ├── models
│ │ ├── User.go
│ │ └── Post.go
│ ├── responses
│ │ └── json.go
│ ├── seed
│ │ └── seeder.go
│ ├── utils
│ │ └── formaterror
│ │ └── formaterror.go
│ │
│ │
│ └── server.go
├── tests
├── .env
├── go.mod
├── go.sum
└── main.go

Also ensure that your database(s) are created and you have entered relevant data in the .env file.

Now without further ado, let’s run the app:

go run main.go

This will start up the app and run migrations.

Cara menggunakan rest-api php mysql github

starting the application

Yes! You did it. Well done.

Step 12: Testing the Endpoints in Postman

You can use Postman or your favorite testing tool, then in the next step, we will write test cases.

Lets test endpoints at random:

a. GetUsers (/users):

Remember we seeded the users table

Cara menggunakan rest-api php mysql github

b. GetPosts (/posts):

Remember we also seeded the posts table

Cara menggunakan rest-api php mysql github

c. Login (/login)

Lets Login User 1: We will use that token to update the post in the next test.

Cara menggunakan rest-api php mysql github

d. UpdatePost (/posts/{id}):

To update a post, we will need the authentication token for a user and in the above, we generated a token when we logged in user 1. The token look like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE1NjY5NDE3MzgsInVzZXJfaWQiOjF9.CK8rJ-3IG3xHdCj3iHKA4ihizepij5HNXz4RWrXe50

I will use this token and put it in Authorization: Bearer Token in Postman:

Cara menggunakan rest-api php mysql github

Then I will use JSON in the body to send data to update:

Cara menggunakan rest-api php mysql github

If user 2 tries to update user 1 post, the response will be authorized

Cara menggunakan rest-api php mysql github

e. DeleteUser (/users/{id}):

For the user to shut down his account, he needs to be logged in first, so as to generate the JWT token.

Let us login user 2 and delete him.

Cara menggunakan rest-api php mysql github

Grab the token, insert it in Authorization: Bearer Token. Then use a “DELETE” method in your Postman.

Cara menggunakan rest-api php mysql github

Observe that Status Code is 204, which means No Content. And the response is 1, which means success.

f. UpdateUser (/users/{id}):

Remember to login the ‘user to update’ and use the Token. Since User 2 is deleted, let’s update User 1:

Cara menggunakan rest-api php mysql github

g. CreateUser (/users):

We don’t need to be authenticated to create a user (signup). Let’s create a third user:

Cara menggunakan rest-api php mysql github

h. CreatePost (/posts):

Let the new user create a post. Remember again, he must log in and his token used in Authorization: Bearer Token

Cara menggunakan rest-api php mysql github

You can test the remaining endpoints:

i. GetUser (/users/{id})— Get one user (No token required)

j. GetPost(/posts/{id}) — Get one post (No token required)

k. DeletePost(/posts/{id}) — An authenticated User deletes a post he created( Token required)

l. Home(/) — Get Home page (No token required)

Step 13: Writing Test Cases For Endpoints

We have proven that then endpoints are working. But that is not enough, we still need really test each of them to further proof.

Remember we defined a test database in our .env so, you can create a new database for the tests alone.

I am aware that we can use Interfaces and mock database calls, but I decided to be replicate the exact same process that happens in real life for testing.

At the start of this project, we created the tests directory.

Now, we will create two packages inside it: modeltests and controllertests

a. Models Tests

We are going to test the methods in the models package defined in step 3

In the path tests/ create the modeltests package:

mkdir modeltests

cd into the package and create a file model_test.go

cd modeltests && touch model_test.go

Inside the model_test.go file:

TestMain() does the necessary setup before testing. It loads the .env file and calls the Database() function to connect to the test database.

You can also see that we wrote other helper functions that we will use in the actual test, such as refreshing the test database and seeding it, this will be done for every test. So no test depends on another to pass.

i. user_model_test.go

Now, let’s create tests for the methods in the User model. Create the file user_model_test.go in the path same as the model_test.go: tests/modeltests

touch user_model_test.go

This is the content:

user_model_test.go

We can run individual tests in user_model_test.go. To run TestFindAllUsers, simply do:

go test --run TestFindAllUsers

Cara menggunakan rest-api php mysql github

Get a more detailed output by attaching the -v flag:

go test -v --run TestFindAllUsers

Cara menggunakan rest-api php mysql github

ii. post_model_test.go

Let’s also create tests for the methods in the Post model. Create the file post_model_test.go in the path same as the model_test.go: tests/modeltests

This is the content:

Let's run one test:

go test -v --run TestUpdateAPost

Output:

Cara menggunakan rest-api php mysql github

Let’s make a test FAIL so that you can see what it looks like for a failing test. For the TestUpdateAPost test, I will change this assertion:

assert.Equal(t, updatedPost.ID, postUpdate.ID)toassert.Equal(t, updatedPost.ID, 543) //where 543 is invalid

Now, when we run this test, it will fail:

Cara menggunakan rest-api php mysql github

You can see that line:

post_model_test.go:101 1 does not equal 543

Running all tests in the modeltests package:

To run the test suite in the modeltests package, make sure in your terminal, you are in the path: tests/modeltests .

Then run:

go test -v

Yay! All tests in the modeltests package are run and all passed.

b. Controllers Tests

In the tests paths: /tests, we will create a package called controllertests, which is in the same directory path as modeltests.

mkdir controllertests

Next, will we create the controller_test.go file where we will define the TestMain()which loads the .env file, setup database connection, and call seeder functions.

In the path: tests/controllertests

touch controller_test.go

i. login_controller_test.go

We will use TABLE TEST here. The idea behind the table test is that all possible cases defined in a struct, which uses a loop to run each test case. This saves us a lot of time as we tend to test all cases for a particular functionality with just one test function.

In the same directory path as controller_test.go, we create a file

touch login_controller_test.go

With the content:

Running the TestLogin:

go test -v --run TestLogin

Cara menggunakan rest-api php mysql github

TestLogin

ii. user_controller_test.go

This test file extensively uses TABLE TEST to test all possible cases, rather creating separate test functions for each case, hence saving us a lot of time.

In the same path as controller_test.go, create the user_controller_test.go file

touch user_controller_test.go file

Let’s run one test function inside that file to demonstrate.

Running TestCreateUser

go test -v --run TestCreateUser

Cara menggunakan rest-api php mysql github

TestCreateUser

Observe this:

Cara menggunakan rest-api php mysql github

This is one of the cases in our table test:

{
inputJSON: `{"nickname":"Pet", "email": "", "password": "password"}`,
statusCode: 500,errorMessage: "Nickname Already Taken",
},

Since this test hits the database and identified that the Nickname already exist and cannot insert that record, an error is returned, this is exactly what we want in that test. Hence the test passed. The same thing applies when the email is duplicated.

iii. post_controller_test.go

TABLE TEST is also extensively used in this file. In the same directory as controller_test.go, create the post_controller_test.go file

touch post_controller_test.go

With the content:

In this test file, we can run TestDeletePost function

go test -v --run TestDeletePost

Cara menggunakan rest-api php mysql github

TestDeletePost

Running all tests in the controllertests package

We can also run the test suite for the controllertests package.

In the path tests/controllertests run:

go test -v 

All Tests passed. Feels Good!

c. Running the Entire Tests in the app.

At this point, your folder structure should look like this:

Cara menggunakan rest-api php mysql github

Now, to run the test suite, you should be in the tests/ directory.

Then run:

go test -v ./...

This will run all the tests in the modeltests and the controllertests packages.

Cara menggunakan rest-api php mysql github

Not one test failing. How Sweet.

Wrapping up.

Frankly, I did a lot of research to put this article together. Because of writing test cases, I had to change the entire app structure. This was really a pain in the butt. I think is all worth it now, testing every single function/method ships a better software. Really, I feel good.

What Next?

  • Dockerizing the application(Part 2 of the article here)
  • Deploying on Kubernetes(Part 3 of the article here)
  • Integrate Travis, Code Climate and Coveralls
  • Deploy the application on AWS, Digital Ocean or Heroku.
  • Consuming the API with React/Vue.

I actually summed everything together in this article here. Where I built a Forum App using Gin Framework. React is used as the Frontend Stack.

You can follow me on medium to get updates. You can also follow me on twitter

Get the source code for this article on github

Happy Coding!