Saravanan Gnanaguru
Posted on August 14, 2020
Table of content
- Introduction
- Objective
- Source Repo
- Function main
- Get Method
- Full Source Code
- Go REST API Unit testing
- Executing Go Unit Testing
- Go Source Build and Run
- Real time test
Introduction
We have learnt how to create simple REST API in the previous blog.
We will now see the below topics in this blog,
- How to add REST API versioning
- How to create query string parameters
- How to add basic authentication to REST API
- How to write Go unit testing for API authentication code
- How to test the REST API with authentication in real time
Objective
- We will be creating REST API that listens on
localhost
port1357
and has the API versioning with query string parameter. - Sample URL format we are planning to create,
http://localhost:1357/api/v1/PersonId/Id456
Source Repo
Checkout the full source repo here in GitHub
Now let us start break the blocks and create the code!
Function main
Add the below code function main()
Adding API Versioning and Basic authentication
// Define gin router
router := gin.Default()
// Create Sub Router for customized API version and basic auth
subRouterAuthenticated := router.Group("/api/v1/PersonId", gin.BasicAuth(gin.Accounts{
"basic_auth_user": "userpass",
}))
Passing Query String Parameters
subRouterAuthenticated.GET("/:IdValue", GetMethod)
REST API Listening on Port
listenPort := "1357"
// Listen and Server on the LocalHost:Port
router.Run(":"+listenPort)
Get Method
- Define a
GetMethod
function and add the following code - It fetches and prints the
Person IdValue
from the query string parameter passed in the API URL
func GetMethod(c *gin.Context) {
fmt.Println("\n'GetMethod' called")
IdValue := c.Params.ByName("IdValue")
message := "GetMethod Called With Param: " + IdValue
c.JSON(http.StatusOK, message)
// Print the Request Payload in console
ReqPayload := make([]byte, 1024)
ReqPayload, err := c.GetRawData()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Request Payload Data: ", string(ReqPayload))
}
Full Source Code
// Golang REST API with API versioning and Basic Auth
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func GetMethod(c *gin.Context) {
fmt.Println("\n'GetMethod' called")
IdValue := c.Params.ByName("IdValue")
message := "GetMethod Called With Param: " + IdValue
c.JSON(http.StatusOK, message)
ReqPayload := make([]byte, 1024)
ReqPayload, err := c.GetRawData()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Request Payload Data: ", string(ReqPayload))
}
func main() {
router := gin.Default()
// Create Sub Router for customised API version
subRouterAuthenticated := router.Group("/api/v1/PersonId", gin.BasicAuth(gin.Accounts{
"admin": "adminpass",
}))
subRouterAuthenticated.GET("/:IdValue", GetMethod)
listenPort := "1357"
// Listen and Server on the LocalHost:Port
router.Run(":"+listenPort)
}
Go REST API Unit testing
Go
testing
module can be used for creating unit testing code for Go sourceGo Unit testing code looks as below,
// Golang REST API unit testing program
package main
import (
"testing"
"net/http"
"net/http/httptest"
"fmt"
"bytes"
"github.com/gin-gonic/gin"
)
func TestGetMethod(t *testing.T) {
// Switch to test mode so you don't get such noisy output
gin.SetMode(gin.TestMode)
// Create the mock request you'd like to test. Make sure the second argument
// here is the same as one of the routes you defined in the router setup
// block!
body := bytes.NewBuffer([]byte("{\"ApiTest\":\"GetReq\"}"))
req, err := http.NewRequest("GET", "/api/v1/PersonId/Id456", body)
if err != nil {
t.Fatalf("Couldn't create request: %v\n", err)
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("admin", "adminpass")
// Setup your router, just like you did in your main function, and
// register your routes
router := gin.Default()
router.GET("/api/v1/PersonId/:IdValue", GetMethod)
// Create a response recorder so you can inspect the response
w := httptest.NewRecorder()
// Perform the request
router.ServeHTTP(w, req)
fmt.Println(w.Body)
}
Executing Go Unit Testing
Run the command go test
and it shows the below output in console,
'GetMethod' called
Request Payload Data: {"ApiTest":"GetReq"}
[GIN] 2020/08/03 - 12:26:29 | 200 | 7.2µs | | GET "/api/v1/PersonId/Id456"
"GetMethod Called With Param: Id456"
PASS
ok apiauth 0.008s
This confirms the REST API code we have created is working fine.
Go Source Build and Run
- If we want to test the API in our server, on which the code is created, run the below command
go run apiauth.go
- This command invokes the REST API on
localhost
port1357
& console shows the below output,
[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 /api/v1/PersonId/:IdValue --> main.GetMethod (4 handlers)
[GIN-debug] Listening and serving HTTP on :1357
- Then proceed to test the REST API real-time
Real time test
CURL method
Run curl
with basic authentication user-password
curl -u username:password -i -X GET http://localhost:1357/api/v1/PersonId/Id456
- This will show the output as below in Console
"GetMethod Called With Param: Id456"
Ngrok method
- Execute the
go run
command to start the API,go run apiauth.go
- To verify our REST API, we need to expose the localhost of the server to internet
- So we can use "ngrok" for this purpose
- Download ngrok here
- Extract the ngrok executable in some location on your server.
- Start ngrok on port 1357(Port defined in go API code) as below,
./ngrok http 1357
and prints the output as follows in console
ngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Session Expires 7 hours, 12 minutes
Version 2.3.35
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://ca6d2c4cee3e.ngrok.io -> http://localhost:4000
Forwarding https://ca6d2c4cee3e.ngrok.io -> http://localhost:4000
ngrok generates a dynamic URL. For ex:
http://ca6d2c4cee3e.ngrok.io
The REST API can be tested by adding the URL in browser address bar,
http://ca6d2c4cee3e.ngrok.io/api/v1/PersonId/Id456
Browser will prompt to enter the authentication details. So enter credentials
After entering the credential, the browser should show,
GetMethod Called With Param: Id456
Key Take away
We have seen the below major topics in this blog,
- Adding basic authentication to REST API
- Go unit testing for API authentication code
- Testing the REST API with basic authentication in real time
Posted on August 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.