Welcome to this step-by-step guide on deploying a GoFiber application to Firebase Functions. If you’re looking to leverage the power of GoFiber, a fast and lightweight web framework for Go, and host your application on Firebase, you’re in the right place. In this tutorial, we’ll walk through the process of setting up your GoFiber app to run seamlessly on Firebase Functions.
- Go installed on your machine.
- Firebase CLI installed.
- A Firebase project created.
- Firestore and Cloud Functions enabled.
Start by initializing your GoFiber application. Use the following commands in your terminal:
go mod init example.com/GofiberFirebaseBoilerplate
Create a server file (src/server.go)
with a CreateServer
function that sets up your GoFiber server.
package src
import (
"example.com/GofiberFirebaseBoilerplate/src/routes"
"github.com/gofiber/fiber/v2"
)
func CreateServer() *fiber.App {
version := "v1.0.0"
app := fiber.New(fiber.Config{
ServerHeader: "Gofiber Firebase Boilerplate",
AppName: "Gofiber Firebase Boilerplate " + version,
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Gofiber Firebase Boilerplate " + version)
})
routes.New().Setup(app)
return app
}
Now that your GoFiber application is initialized, let’s delve into setting up and configuring routes. This section is crucial for defining how your application handles incoming requests. Open the src/routes/routes.go
file to manage your routes.
package routes
import (
"example.com/GofiberFirebaseBoilerplate/src/database"
"example.com/GofiberFirebaseBoilerplate/src/repositories"
"github.com/gofiber/fiber/v2"
)
type Routes struct {
mainRepository *repositories.MainRepository
}
func New() *Routes {
db := database.NewConnection()
return &Routes{mainRepository: &repositories.MainRepository{DB: db}}
}
func (r *Routes) Setup(app *fiber.App) {
app.Post("message", r.insertMessage)
}
func (r *Routes) insertMessage(c *fiber.Ctx) error {
return c.SendString("ok")
}
Configure your Firestore database connection in the src/database/database.go
file. Make sure to replace the placeholder credentials with your Firebase project's actual credentials.
package database
import (
"context"
"encoding/json"
"log"
"cloud.google.com/go/firestore"
firebase "firebase.google.com/go"
"google.golang.org/api/option"
)
type Config struct {
Host string
Port string
Password string
User string
DBName string
SSLMode string
}
func NewConnection() *firestore.Client {
ctx := context.Background()
sa := option.WithCredentialsJSON(credentials())
app, err := firebase.NewApp(ctx, nil, sa)
if err != nil {
log.Fatalf("functions.init: NewApp %v\n", err)
}
db, err := app.Firestore(ctx)
if err != nil {
log.Fatalf("functions.init: Database init : %v\n", err)
}
return db
}
func credentials() []byte {
// TODO: Replace with your Credentials
data := map[string]interface{}{
"type": "",
"project_id": "",
"private_key_id": "",
"private_key": "",
"client_email": "",
"client_id": "",
"auth_uri": "",
"token_uri": "",
"auth_provider_x509_cert_url": "",
"client_x509_cert_url": "",
"universe_domain": "",
}
bytes, err := json.Marshal(data)
if err != nil {
panic(err)
}
return bytes
}
Implement the repository pattern in the src/repositories/main.repository.go
file to interact with Firestore. This file includes an example of inserting a message into the database.
package repositories
import (
"context"
"cloud.google.com/go/firestore"
"example.com/GofiberFirebaseBoilerplate/src/models"
"github.com/google/uuid"
)
type MainRepository struct {
DB *firestore.Client
}
func (r *MainRepository) InsertMessage(body *models.MessageInputBody) error {
id := uuid.New().String()
_, err := r.DB.Collection("messages").Doc(id).Set(context.Background(), body)
return err
}
Define a message input model in src/models/message_input_body.go to structure the data you'll be working with.
package models
type MessageInputBody struct {
From string `json:"from"`
To string `json:"to"`
Message string `json:"message"`
}
In functions.go
, convert Google Cloud Function requests to Fiber and route them to your application. This file includes functions to facilitate the integration of Google Cloud Functions and GoFiber.
package app
import (
"bytes"
"context"
"fmt"
"io"
"log"
"net"
"net/http"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/valyala/fasthttp/fasthttputil"
)
// CloudFunctionRouteToFiber route cloud function http.Handler to *fiber.App
// Internally, google calls the function with the /execute base URL
func CloudFunctionRouteToFiber(fiberApp *fiber.App, w http.ResponseWriter, r *http.Request) error {
return RouteToFiber(fiberApp, w, r, "/execute")
}
// RouteToFiber route http.Handler to *fiber.App
func RouteToFiber(fiberApp *fiber.App, w http.ResponseWriter, r *http.Request, rootURL ...string) error {
ln := fasthttputil.NewInmemoryListener()
defer ln.Close()
// Copy request
body, err := io.ReadAll(r.Body)
if err != nil {
return err
}
url := fmt.Sprintf("%s://%s%s", "http", "0.0.0.0", r.RequestURI)
if len(rootURL) > 0 {
url = strings.Replace(url, rootURL[0], "", -1)
}
proxyReq, err := http.NewRequest(r.Method, url, bytes.NewReader(body))
if err != nil {
return err
}
proxyReq.Header = r.Header
// Create http client
client := http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return ln.Dial()
},
},
}
// Serve request to internal HTTP client
go func() {
log.Fatal(fiberApp.Listener(ln))
}()
// Call internal Fiber API
response, err := client.Do(proxyReq)
if err != nil {
return err
}
// Copy response and headers
for k, values := range response.Header {
for _, v := range values {
w.Header().Set(k, v)
}
}
w.WriteHeader(response.StatusCode)
io.Copy(w, response.Body)
response.Body.Close()
return nil
}
In main.go
, initialize your GoFiber app and start the server. This file also includes an exported Cloud Function handler for deployment.
package app
import (
"fmt"
"net/http"
"strings"
"example.com/GofiberFirebaseBoilerplate/src"
"github.com/gofiber/fiber/v2"
)
var app *fiber.App
func init() {
app = src.CreateServer()
}
// Start start Fiber app with normal interface
func Start(addr string) error {
if -1 == strings.IndexByte(addr, ':') {
addr = ":" + addr
}
return app.Listen(addr)
}
// MyCloudFunction Exported http.HandlerFunc to be deployed to as a Cloud Function
func MyCloudFunction(w http.ResponseWriter, r *http.Request) {
err := CloudFunctionRouteToFiber(app, w, r)
if err != nil {
fmt.Fprintf(w, "err : %v", err)
return
}
}
For local development, utilize the cmd/main.go
file. If you prefer hot reloading, the .air.toml
configuration file is included for use Air.
package main
import (
"log"
"os"
app "example.com/GofiberFirebaseBoilerplate"
)
func main() {
port := "3001"
if envPort := os.Getenv("PORT"); envPort != "" {
port = envPort
}
if err := app.Start(port); err != nil {
log.Fatalf("app.Start: %v\n", err)
}
}
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ./cmd"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true
Deploy your Cloud Function using the following commands, replacing <YourProjectID>
with your Firebase project ID:
gcloud config set project <YourProjectID>
gcloud functions deploy MyCloudFunction --runtime go120 --trigger-http
Congratulations! You’ve successfully configured and deployed a GoFiber application on Firebase Functions. This powerful combination allows you to build fast and efficient serverless applications. Experiment further with GoFiber features and Firebase integrations to unlock the full potential of your serverless architecture. Happy coding!
https://medium.com/@kmltrk07/how-to-deploy-gofiber-app-to-firebase-functions-8d4d537a4464