Develop REST API using Go with API versioning, Basic Auth and Query String
Saravanan Gnanaguru
Posted on May 4, 2022
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
- Conclusion
Introduction
We have learnt how to create simple REST API in the previous blog.
We will see the below topics in this blog,
How to,
- Add REST API versioning
- Create query string parameters
- Add basic authentication to REST API
- Write Go unit testing for API authentication code
- 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/Id432
Source Repo
Checkout the full source repo here in GitHub
Let us start break the code into blocks,
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)
}
- Refer my previous blog section
Write go test program
to know more about writing go test code
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
Localhost method
Run curl
with basic authentication user-password
curl -u admin:adminpass -i -X GET http://localhost:1357/api/v1/PersonId/Id456
- This will show the output as below in Console
"GetMethod Called With Param: Id456"
- In Ubuntu, Access the
localhost
URL in browser and enter the basic auth username and password when prompted - After entering the credential, the browser should show,
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
Conclusion
We have seen the below 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
This article was previously published on my dev community personal profile, re-publishing for the benefit of a wider audience.
Hope this article is helpful to people getting started with kubernetes concepts.
Follow me on,
Posted on May 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.