Today we'll be making a REST API using Go Fiber. The API returns dummy data for different entities like users, posts, employees, etc., that can be used for development and testing purposes.
Prerequisites:
Go installed on your system
AWS account
Setting up the Project
mkdir dummy-data
cd dummy-data
go mod init github.com/omeiirr/dummy-data
go get github.com/gofiber/fiber/v2
Create a file main.go
in the root directory.
package main
import (
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Server is running normally")
})
app.Listen(":3000")
}
Now start the server with go run .
in the terminal and visit localhost:3000
in your browser. You should see "Server is running normally".
Generating Fake Data
We'll use the [faker](github.com/jaswdr/faker) library to generate the fake data. Install this as a dependency with go get github.com/jaswdr/faker
Let us now define a struct for a User. Create a file models/user.go
package models
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"username"`
Email string `json:"email"`
}
We also need a helper function that will generate n
number of fake users. Create a file helpers/generate_users.go
package helpers
import (
"github.com/jaswdr/faker"
"github.com/omeiirr/dummy-data/models"
)
func GenerateUsers(n int) []models.User {
fake := faker.New()
var users []models.User
for i := 0; i < n; i++ {
user := models.User{
ID: fake.Int(),
Name: fake.Person().FirstName(),
Username: fake.Internet().User(),
Email: fake.Person().Contact().Email,
}
users = append(users, user)
}
return users
}
Lastly, we will create a handler function that will be called on the API endpoint, and will return fake users in JSON format. Create a file handlers/return_users.go
package handlers
import (
"github.com/gofiber/fiber/v2"
"github.com/omeiirr/dummy-data-api/helpers"
)
func ReturnUsers(c *fiber.Ctx) error {
users := helpers.GenerateUsers(5)
return c.JSON(users)
}
Now we need to call this function in our main.go
file at the endpoint users
. We can also move the HealthCheck function to handlers
to keep our code modular and concise.
Our main.go
file looks like this:
...
func main() {
app := fiber.New()
app.Get("/", handlers.HealthCheck)
app.Get("/users", handlers.ReturnUsers)
app.Listen(":3000")
}
Let's check if this works as expected or not. Restart the development server with go run .
and visit localhost:3000/users
in your browser. You should see data of 5 users like so:
[
...
{
"id": 2665926480750013400,
"name": "Taylor",
"username": "garth.hackett",
"email": "marcelle@hte.com"
},
{
"id": 5321523606392798000,
"name": "Roxane",
"username": "lourdes.runolfsdottir",
"email": "silas.lemke@uay.com"
},
...
]
Running Code on Lambda
Great! The API is working as expected on localhost. Now we need to put it on AWS Lambda to execute it as a serverless function. But for that, we need to make certain modifications to our code.
main.go
var fiberLambda *fiberadapter.FiberLambda
fiberLambda = fiberadapter.New(app)
lambda.Start(Handler)
func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return fiberLambda.ProxyWithContext(ctx, request)
}
We also need this function to run on both localhost (for development) and Lambda. We will create a helper function to determine whether the function is running in a Lambda environment or not. We can do so by checking the existence of an environment variable LAMBDA_TASK_ROOT
, that will only be present in a Lambda execution environment.
helpers/is_lambda.go
package helpers
import "os"
func IsLambda() bool {
if lambdaTaskRoot := os.Getenv("LAMBDA_TASK_ROOT"); lambdaTaskRoot != "" {
return true
}
return false
}
This is how the main
function looks now:
package main
import (
"context"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
fiberadapter "github.com/awslabs/aws-lambda-go-api-proxy/fiber"
"github.com/gofiber/fiber/v2"
"github.com/omeiirr/dummy-data/handlers"
"github.com/omeiirr/dummy-data/helpers"
)
var fiberLambda *fiberadapter.FiberLambda
func main() {
app := fiber.New()
app.Get("/", handlers.HealthCheck)
app.Get("/users", handlers.ReturnUsers)
if helpers.IsLambda() {
fiberLambda = fiberadapter.New(app)
lambda.Start(Handler)
} else {
app.Listen(":3000")
}
}
func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return fiberLambda.ProxyWithContext(ctx, request)
}
Creating Executable File
We need to create an executable so it can be deployed on Lambda.
Create the executable file with GOOS=linux GOARCH=amd64 go build -o main
If you're working on a non-Linux device, you need to specify the GOOS
and GOARCH
variables like so because the Lambda function runs on these specifications. These variables tell the Go compiler to create the executable which is compatible with such specs. This is known as cross-compiling.
An executable with the main
is created in the root directory. Now zip it before uploading it to Lambda using the command zip main.zip main
Creating Lambda Function
Log in to your AWS account
Go to Services > Lambda
Click on 'Create Function'
Choose the option 'Author from Scratch', name the function, and select 'Go 1.x' as the runtime. Leave the other options as the default. Click on 'Create Function'.
Choose the option to upload as a .zip file and upload the zip file we created earlier.
Change the name of Handler in 'Runtime settings' from 'hello' to 'main'.
Test the function.
Connecting to API Gateway
Now that our Lambda function is working properly, we need to connect it to Amazon API Gateway, so it can be accessed through an endpoint URL.
Select 'Add Trigger'
Select 'API Gateway' and select the intent as 'Create a new API'. Select 'REST API' and security as 'Open'. Click on 'Add'.
Configuring API Gateway
If we try to access the endpoint, it shows: Cannot GET /dummy-data-api
We need to make some minor configurations on our API Gateway. Click on the API name.
- Select the root (
/
) resource, go to Actions > Create Method. Choose ANY as the method.
- Configure the following for the method and then click on Save.
- Grant permission to API Gateway to invoke the Lambda function.
- Again go to Actions, then click on Deploy API
- Create a new stage for the deployment
v1
and click on Deploy.
Check the API by clicking on the 'Invoke URL'
You should see
Server is running normally
in the browser.Now we need to create a similar method for accessing the
/users
endpoint.
Go to the 'Resources' in the left sidebar, click on Actions > Create a new resource, and configure it for the/users
endpoint as shown. Click on Create Resource.Then select the
/users
resource, go to Actions > Create a method, and select GET. Configure as we did before. The result should look like this.Go to Actions > Deploy API. Click on the 'Invoke URL' and you should see the data of the fake users on your screen.
Perfect! We have created a RESTful API, deployed it to AWS Lambda, and connected it to API Gateway, so it can be accessed using the endpoint anywhere.
The source code for this tutorial can be accessed [here]().
Scope for Improvement
This tutorial is a very basic demo of how to create REST APIs using Go and connecting them to different AWS Services.
You can implement more features like:
Adding more resources like posts, items, employees, etc.
Authorization using token
Pagination
I hope you found this helpful. Feel free to like this article and share it with your friends.