Skip to content

Commit 6258aa6

Browse files
committed
add skeleton
1 parent 89425c6 commit 6258aa6

File tree

22 files changed

+1091
-16
lines changed

22 files changed

+1091
-16
lines changed

.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
APP_NAME=Go Application Programming Interface (API) Gateway
2+
APP_PORT=10000
3+
APP_LOCATION=Asia/Jakarta
4+
APP_DEBUG=false
5+
APP_VERSION=v1.0.0
6+
APP_KEY=
7+
8+
USE_BODY_DUMP_LOG=false
9+
10+
DEFAULT_TIMEOUT=1
11+
12+
HEADER_PREFIX=X-Go-Api-Gateway-
13+
14+
ALLOWED_ORIGINS=http://localhost:1000

.gitignore

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,65 @@
1-
# If you prefer the allow list template instead of the deny list, see community template:
2-
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3-
#
4-
# Binaries for programs and plugins
1+
# Environment files
2+
.env
3+
4+
# Binaries for programs and plugins (remove the comment below to include it)
55
*.exe
66
*.exe~
77
*.dll
88
*.so
99
*.dylib
10+
# *.app
11+
# *.war
12+
13+
# Log files
14+
*.log
15+
16+
# Large media files
17+
*.mp4
18+
*.tiff
19+
*.avi
20+
*.flv
21+
*.mov
22+
*.wmv
23+
24+
# Temporary files (remove the comment below to include it)
25+
# tmp/*
26+
27+
# Generated by macos
28+
.DS_Store
29+
30+
# Generated by windows
31+
Thumbs.db
1032

1133
# Test binary, built with `go test -c`
1234
*.test
1335

14-
# Code coverage profiles and other test artifacts
36+
# Output of the go coverage tool, specifically when used with LiteIDE
1537
*.out
16-
coverage.*
17-
*.coverprofile
18-
profile.cov
38+
39+
# Unit test reports (remove the comment below to include it)
40+
# TEST*.xml
1941

2042
# Dependency directories (remove the comment below to include it)
2143
# vendor/
2244

23-
# Go workspace file
24-
go.work
25-
go.work.sum
45+
# Node artifact directories (remove the comment below to include it)
46+
# node_modules/
47+
# dist/
2648

27-
# env file
28-
.env
49+
# Compiled java class files (remove the comment below to include it)
50+
# *.class
51+
52+
# Compiled python bytecode files (remove the comment below to include it)
53+
# *.py[cod]
2954

30-
# Editor/IDE
55+
# Package files (remove the comment below to include it)
56+
# *.jar
57+
58+
# Maven (remove the comment below to include it)
59+
# target/
60+
61+
# JetBrains IDE (remove the comment below to include it)
3162
# .idea/
63+
64+
# Editor IDE (remove the comment below to include it)
3265
# .vscode/

Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM golang:1.24-alpine3.22
2+
3+
ENV TZ=Asia/Jakarta
4+
5+
RUN apk update && \
6+
apk add --no-cache nano curl gcc g++ make libwebp-dev
7+
8+
RUN mkdir /app
9+
10+
ADD . /app
11+
12+
WORKDIR /app
13+
14+
COPY .env.example .env
15+
16+
COPY go.mod .
17+
18+
RUN go mod tidy
19+
20+
RUN go build -o engine ./
21+
22+
CMD ["./engine"]

README.md

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,86 @@
1-
# goapigateway
2-
A skeleton uses the Go Programming Language (GoLang) for The Application Programming Interface (API) Gateway.
1+
# MrAndreID / Go Application Programming Interface (API) Gateway
2+
3+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4+
5+
The `MrAndreID/GoAPIGateway` is a skeleton uses the Go Programming Language (GoLang) with The Echo Framework for The Application Programming Interface (API) Gateway.
6+
7+
## Table of Contents
8+
9+
* [Requirements](#requirements)
10+
* [Installation](#installation)
11+
* [Usage](#usage)
12+
* [Versioning](#versioning)
13+
* [Authors](#authors)
14+
* [Contributing](#contributing)
15+
* [Official Documentation for Go Language](#official-documentation-for-go-language)
16+
* [License](#license)
17+
18+
## Requirements
19+
20+
To use The `MrAndreID/GoAPIGateway`, you must ensure that you meet the following requirements:
21+
- [Go](https://golang.org/) >= 1.24
22+
23+
## Installation
24+
25+
To use The `MrAndreID/GoAPIGateway`, you must follow the steps below:
26+
- Clone a Repository
27+
```git
28+
# git clone https://github.com/MrAndreID/goapigateway.git
29+
```
30+
- Get Dependancies
31+
```go
32+
# go mod download
33+
# go mod tidy
34+
```
35+
- Create .env file from .env.example (Linux)
36+
```sh
37+
# cp .env.example .env
38+
```
39+
- Configuring .env file
40+
41+
## Usage
42+
43+
To use The `MrAndreID/GoAPIGateway`, you must ensure that you meet the following requirements:
44+
- Directory Structure The `MrAndreID/GoAPIGateway`
45+
| Name | Description |
46+
| :---------------------- | :-------------------------------------------------------- |
47+
| `application` | Initialization of Echo Framework, Middleware, and Routes. |
48+
| `configs` | Configuration from Env File |
49+
| `internal/handlers` | HTTP Handlers |
50+
| `internal/services` | Main Business Logic |
51+
| `internal/repositories` | Connector to Database or API External |
52+
| `internal/types` | Data |
53+
- Run The `MrAndreID/GoAPIGateway`
54+
```go
55+
# go run main.go
56+
```
57+
- Run The `MrAndreID/GoAPIGateway` with Docker
58+
```docker
59+
# docker build --no-cache -t goapigateway:1.0.0 .
60+
# docker run --name goapigateway --restart=always -d -p -v /path/to/folder:/app/storages -v /path/to/folder:/app/tests/storages 10000:10000 goapigateway:1.0.0
61+
```
62+
- Set The `MrAndreID/GoAPIGateway` to Maintenance Mode in Storages Folder
63+
```sh
64+
# touch storages/maintenance.flag
65+
```
66+
67+
## Versioning
68+
69+
I use [Semanting Versioning](https://semver.org/). For the versions available, see the tags on this repository.
70+
71+
## Authors
72+
73+
- **Andrea Adam** - [MrAndreID](https://github.com/MrAndreID)
74+
75+
## Contributing
76+
77+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
78+
Please make sure to update tests as appropriate.
79+
80+
## Official Documentation for Go Language
81+
82+
Documentation for Go Language can be found on the [Go Package website](https://pkg.go.dev/).
83+
84+
## License
85+
86+
The `MrAndreID/GoAPIGateway` is released under the [MIT License](https://opensource.org/licenses/MIT). See the `LICENSE` file for more information.

applications/main.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package applications
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strconv"
7+
"strings"
8+
"time"
9+
10+
"github.com/MrAndreID/goapigateway/configs"
11+
"github.com/MrAndreID/goapigateway/internal/handlers"
12+
13+
"github.com/MrAndreID/gomiddleware"
14+
"github.com/MrAndreID/gopackage"
15+
"github.com/fatih/color"
16+
"github.com/labstack/echo/v4"
17+
"github.com/labstack/echo/v4/middleware"
18+
"github.com/labstack/gommon/log"
19+
"github.com/sirupsen/logrus"
20+
"github.com/spf13/cast"
21+
"github.com/unrolled/secure"
22+
"go.elastic.co/apm/module/apmechov4"
23+
)
24+
25+
type Application struct {
26+
Config *configs.Config
27+
TimeLocation *time.Location
28+
}
29+
30+
func Start(toggle bool) any {
31+
var tag string = "Applications.Main.New."
32+
33+
cfg, err := configs.New(toggle)
34+
35+
if err != nil {
36+
logrus.WithFields(logrus.Fields{
37+
"tag": tag + "01",
38+
"error": err.Error(),
39+
}).Error("failed to initiate configuration")
40+
41+
return nil
42+
}
43+
44+
timeLocation, err := time.LoadLocation(cfg.AppLocation)
45+
46+
if err != nil {
47+
logrus.WithFields(logrus.Fields{
48+
"tag": tag + "02",
49+
"error": err.Error(),
50+
}).Error("failed to load location for time")
51+
52+
return nil
53+
}
54+
55+
app := Application{
56+
Config: cfg,
57+
TimeLocation: timeLocation,
58+
}
59+
60+
echo.NotFoundHandler = func(c echo.Context) error {
61+
logrus.WithFields(logrus.Fields{
62+
"tag": tag + "03",
63+
}).Error("route not found")
64+
65+
return c.JSON(http.StatusNotFound, map[string]string{
66+
"code": fmt.Sprintf("%04d", http.StatusNotFound),
67+
"description": strings.ToUpper(strings.ReplaceAll(http.StatusText(http.StatusNotFound), " ", "_")),
68+
})
69+
}
70+
71+
echo.MethodNotAllowedHandler = func(c echo.Context) error {
72+
logrus.WithFields(logrus.Fields{
73+
"tag": tag + "04",
74+
}).Error("method not allowed")
75+
76+
return c.JSON(http.StatusMethodNotAllowed, map[string]string{
77+
"code": fmt.Sprintf("%04d", http.StatusMethodNotAllowed),
78+
"description": strings.ToUpper(strings.ReplaceAll(http.StatusText(http.StatusMethodNotAllowed), " ", "_")),
79+
})
80+
}
81+
82+
e := echo.New()
83+
84+
e.Validator = gopackage.CustomValidator()
85+
86+
e.HTTPErrorHandler = gopackage.EchoCustomHTTPErrorHandler
87+
88+
e.JSONSerializer = gopackage.CustomJSON()
89+
90+
e.Pre(middleware.RemoveTrailingSlash())
91+
92+
e.Pre(gomiddleware.EchoSetRequestID)
93+
94+
e.Use(apmechov4.Middleware())
95+
96+
e.Use(middleware.Recover())
97+
98+
e.Use(middleware.SecureWithConfig(middleware.SecureConfig{
99+
XSSProtection: "1; mode=block",
100+
ContentTypeNosniff: "nosniff",
101+
XFrameOptions: "SAMEORIGIN",
102+
HSTSMaxAge: 3600,
103+
ContentSecurityPolicy: "default-src 'self'",
104+
}))
105+
106+
secureMiddleware := secure.Options{
107+
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"},
108+
STSSeconds: 63072000,
109+
STSIncludeSubdomains: true,
110+
STSPreload: true,
111+
ForceSTSHeader: true,
112+
IsDevelopment: true,
113+
}
114+
115+
e.Use(echo.WrapMiddleware(secure.New(secureMiddleware).Handler))
116+
117+
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
118+
AllowOrigins: cfg.AllowedOrigins,
119+
AllowHeaders: []string{"*"},
120+
AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE},
121+
}))
122+
123+
e.Use(gomiddleware.EchoSetNoCache)
124+
125+
e.Use(gomiddleware.EchoSetMaintenanceMode("storages/maintenance.flag"))
126+
127+
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
128+
return func(c echo.Context) error {
129+
start := time.Now().In(timeLocation)
130+
131+
err := next(c)
132+
133+
stop := time.Now().In(timeLocation)
134+
135+
dateTime := stop.Format(time.DateTime)
136+
137+
redBackground := color.New(color.FgWhite).Add(color.BgRed).SprintFunc()
138+
greenBackground := color.New(color.FgWhite).Add(color.BgGreen).SprintFunc()
139+
140+
redForeground := color.New(color.FgRed).SprintFunc()
141+
greenForeground := color.New(color.FgGreen).SprintFunc()
142+
143+
var status, statusType string
144+
145+
if c.Response().Status >= 400 {
146+
status = redBackground(" " + strconv.Itoa(c.Response().Status) + " ")
147+
148+
statusType = redForeground("[ ERROR ]")
149+
} else {
150+
status = greenBackground(" " + strconv.Itoa(c.Response().Status) + " ")
151+
152+
statusType = greenForeground("[ SUCCESS ]")
153+
}
154+
155+
fmt.Printf(
156+
"%s %s %s %s %s | %s | %s\n",
157+
dateTime,
158+
status,
159+
statusType,
160+
c.Request().Method,
161+
c.Request().URL.String(),
162+
stop.Sub(start).String(),
163+
cast.ToString(c.Get("RequestID")),
164+
)
165+
166+
return err
167+
}
168+
})
169+
170+
if cfg.AppDebug {
171+
e.Logger.SetLevel(log.DEBUG)
172+
173+
e.Debug = true
174+
}
175+
176+
initService(&app)
177+
178+
if toggle {
179+
handlers.NewGatewayHandler(e, GatewayService)
180+
181+
return e.Start(":" + cfg.AppPort)
182+
}
183+
184+
return e
185+
}

0 commit comments

Comments
 (0)