Low cost cloud web app with fastrex-serverless
Tags: go, cloud, fastrex, firebase
Published: 2021-06-13 13:40:23

Google provides a very efficient serverless service. [Cloud function](https://cloud.google.com/functions) will serve if someone uses it and will iddle if no one is using it. You pay nothing when your function is idle. *So cheap, right?*

With [fastrex-serverless](https://github.com/fastrodev/fastrex#cloud-function) you can develop a golang based fullstack web application: create multiple routes, handlers, middlewares, handle static files, and render html templates. 

After that, you can associate the app with the entry point in [the cloud function](https://cloud.google.com/functions). The entry point is then redirected to [firebase hosting](https://firebase.google.com/docs/hosting) according to the domain and url you want.

Live demo: [https://phonic-altar-274306.web.app](https://phonic-altar-274306.web.app)
Source code: [https://github.com/fastrodev/serverless](https://github.com/fastrodev/serverless)

## Getting started
Create serverless webapp folder: `serverless`
```
mkdir serverless && cd serverless
go mod init github.com/fastrodev/serverless
go get github.com/fastrodev/fastrex
```
You can rename the module `github.com/fastrodev/serverless` to anything.

## Create web application
create an app folder: `internal`
```
mkdir internal
```

create a webapp file: `internal/app.go`
```go
package internal

import "github.com/fastrodev/fastrex"

func CreateApp() fastrex.App {
	app := fastrex.New()
	app.Get("/", handler)
	return app
}

func handler(req fastrex.Request, res fastrex.Response) {
	res.Json(`{"message":"ok"}`)
}

```

> *You can add new routes, handlers, templates and static files later. See the full source code at: [internal/app.go](https://github.com/fastrodev/serverless/blob/main/internal/app.go)*

## Localhost entrypoint
To test locally, you can create a localhost webapp entrypoint file: `cmd/main.go`
```go
package main

import (
	"github.com/fastrodev/serverless/internal"
)

func main() {
	internal.CreateApp().Listen(9000)
}

```

> *You can see the full source code at: [cmd/main.go](https://github.com/fastrodev/serverless/blob/main/cmd/main.go)*

You can run by this command:
```
go run cmd/main.go
```
You can access it via url:
```
http://localhost:9000
```

## Serverless entrypoint
To see the serverless endpoint, you must create a serverless webapp entrypoint file: `serverless.go`
```go
package serverless

import (
	"net/http"

	"github.com/fastrodev/serverless/internal"
)

func Main(w http.ResponseWriter, r *http.Request) {
	internal.CreateApp().ServeHTTP(w, r)
}
```

> *You can see the full source code at: [serverless.go](https://github.com/fastrodev/serverless/blob/main/serverless.go)*


## Cloud function deployment
> *Prerequisite: [install cloud sdk](https://cloud.google.com/sdk/docs/quickstart)*

To see live serverless endpoint, you must deploy to google cloud function:
```
gcloud functions deploy Main --runtime go113 --trigger-http --allow-unauthenticated
```

Live demo: [https://us-central1-phonic-altar-274306.cloudfunctions.net/Main](https://us-central1-phonic-altar-274306.cloudfunctions.net/Entrypoint)

## Firebase domain setup

> *Prerequisite: [install firebase-cli](https://firebase.google.com/docs/cli)*

We will redirect above url to firebase domain. You can change it with your own from firebase dashboard.

Init hosting files:
```
firebase init hosting
```

Remove public folder:
```
rm -rf public
```

Change firebase config:
```json
{
  "hosting": {
    "rewrites": [
      {
        "source": "**",
        "function": "Main"
      }
    ],
    "ignore": [
      "**/cmd/**",
      "**/internal/**",
      "**/static/**",
      "**/template/**",
      ".gitignore",
      "cloudbuild.yaml",
      "firebase.json",
      "go.mod",
      "go.sum",
      "README.md",
      "serverless.go",
      "**/.*"
    ]
  }
}
```

Deploy to firebase:
```
firebase deploy
```

Live demo: [https://phonic-altar-274306.web.app](https://phonic-altar-274306.web.app)