Skip to content

Commit 095c7de

Browse files
authored
Add indigo go networking framework (#9965)
* Add indigo * Fix paths * Fix paths * More correct naming * Add missing headers * Rename from go to indigo * Fix logic * Do not error on n != int * Update go version * Add charset to fortunes endpoint * Update dependencies * Update code to lookup for n instead of get
1 parent 04c7616 commit 095c7de

File tree

15 files changed

+2058
-4
lines changed

15 files changed

+2058
-4
lines changed

frameworks/Go/fiber/src/server_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package main
22

33
import (
4-
"encoding/json"
5-
"io/ioutil"
4+
"io"
65
"net/http"
76
"net/http/httptest"
87
"testing"
@@ -37,7 +36,7 @@ func Benchmark_Plaintext(b *testing.B) {
3736
utils.AssertEqual(b, nil, err, "app.Test(req)")
3837
utils.AssertEqual(b, 200, resp.StatusCode, "Status code")
3938
utils.AssertEqual(b, fiber.MIMETextPlainCharsetUTF8, resp.Header.Get("Content-Type"))
40-
body, _ := ioutil.ReadAll(resp.Body)
39+
body, _ := io.ReadAll(resp.Body)
4140
utils.AssertEqual(b, helloworldRaw, body)
4241
}
4342

@@ -66,6 +65,6 @@ func Benchmark_JSON(b *testing.B) {
6665
utils.AssertEqual(b, nil, err, "app.Test(req)")
6766
utils.AssertEqual(b, 200, resp.StatusCode, "Status code")
6867
utils.AssertEqual(b, fiber.MIMEApplicationJSON, resp.Header.Get("Content-Type"))
69-
body, _ := ioutil.ReadAll(resp.Body)
68+
body, _ := io.ReadAll(resp.Body)
7069
utils.AssertEqual(b, `{"message":"Hello, World!"}`, string(body))
7170
}

frameworks/Go/indigo/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# [Indigo](https://github.com/indigo-web/indigo) (Go) Benchmarking Test
2+
3+
This is the go portion of a [benchmarking test suite](https://www.techempower.com/benchmarks/) comparing a variety of web development platforms.
4+
5+
> Indigo is a web-framework focusing at performance, elegancy and robustness.
6+
7+
## Test URLs
8+
* http://localhost:8080/json
9+
* http://localhost:8080/db
10+
* http://localhost:8080/query?n=[1-500]
11+
* http://localhost:8080/update?n=[1-500]
12+
* http://localhost:8080/cached-query?n=[1-500]
13+
* http://localhost:8080/fortune
14+
* http://localhost:8080/plaintext
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"framework": "indigo",
3+
"tests": [
4+
{
5+
"default": {
6+
"json_url": "/json",
7+
"db_url": "/db",
8+
"query_url": "/query?n=",
9+
"update_url": "/update?n=",
10+
"cached_query_url": "/cached-query?n=",
11+
"fortune_url": "/fortunes",
12+
"plaintext_url": "/plaintext",
13+
"port": 8080,
14+
"approach": "Realistic",
15+
"classification": "Platform",
16+
"database": "Postgres",
17+
"framework": "indigo",
18+
"language": "Go",
19+
"flavor": "None",
20+
"orm": "Raw",
21+
"platform": "None",
22+
"webserver": "None",
23+
"os": "Linux",
24+
"database_os": "Linux",
25+
"display_name": "Indigo",
26+
"notes": "",
27+
"versus": "go"
28+
}
29+
}
30+
]
31+
}

frameworks/Go/indigo/config.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[framework]
2+
name = "indigo"
3+
4+
[main]
5+
urls.json = "/json"
6+
urls.db = "/db"
7+
urls.query = "/query?n="
8+
urls.update = "/update?n="
9+
urls.cached_query = "/cached-query?n="
10+
urls.fortune = "/fortunes"
11+
urls.plaintext = "/plaintext"
12+
approach = "Realistic"
13+
classification = "Platform"
14+
database = "Postgres"
15+
database_os = "Linux"
16+
os = "Linux"
17+
orm = "Raw"
18+
platform = "None"
19+
webserver = "None"
20+
versus = "go"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM golang:1.25-alpine3.22 as builder
2+
3+
WORKDIR /indigo
4+
5+
COPY ./src /indigo
6+
7+
RUN go mod download && \
8+
go generate -x ./templates && \
9+
GOAMD64=v3 go build -ldflags="-s -w" -o app .
10+
11+
FROM alpine:3.22
12+
13+
WORKDIR /indigo
14+
15+
COPY --from=builder /indigo/app .
16+
17+
EXPOSE 8080
18+
19+
CMD ./app

frameworks/Go/indigo/src/app.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"math/rand/v2"
6+
"slices"
7+
"strconv"
8+
"time"
9+
10+
"github.com/indigo-web/indigo/http"
11+
"github.com/indigo-web/indigo/http/mime"
12+
13+
"indigo/app/models"
14+
"indigo/app/templates"
15+
)
16+
17+
type (
18+
App struct {
19+
DB *DB
20+
Cache models.Worlds
21+
}
22+
)
23+
24+
func NewApp(DB *DB) *App {
25+
return &App{DB: DB}
26+
}
27+
28+
func (app *App) PopulateCache(ctx context.Context) error {
29+
cache := make(models.Worlds, 10000)
30+
31+
err := app.DB.FillWorlds(context.Background(), cache)
32+
if err != nil {
33+
return err
34+
}
35+
36+
app.Cache = cache
37+
38+
return nil
39+
}
40+
41+
func (app *App) HandleJSON(request *http.Request) *http.Response {
42+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&models.Message{
43+
Message: "Hello, World!",
44+
})
45+
}
46+
47+
func (app *App) HandleDB(request *http.Request) *http.Response {
48+
world := &models.World{
49+
ID: rand.IntN(10000) + 1,
50+
}
51+
52+
err := app.DB.FillWorldByID(context.Background(), world)
53+
if err != nil {
54+
return http.Error(request, err)
55+
}
56+
57+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(world)
58+
}
59+
60+
func (app *App) HandleQuery(request *http.Request) *http.Response {
61+
n := normalizeNumber(request.Params.Lookup("n"))
62+
63+
i, worlds := 0, make(models.Worlds, n)
64+
65+
for i = range worlds {
66+
worlds[i].ID = rand.IntN(10000) + 1
67+
}
68+
69+
err := app.DB.FillWorldsByID(context.Background(), worlds)
70+
if err != nil {
71+
return http.Error(request, err)
72+
}
73+
74+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)
75+
}
76+
77+
func (app *App) HandleUpdate(request *http.Request) *http.Response {
78+
n := normalizeNumber(request.Params.Lookup("n"))
79+
80+
i, worlds := 0, make(models.Worlds, n)
81+
82+
for i = range worlds {
83+
worlds[i].ID = rand.IntN(10000) + 1
84+
}
85+
86+
err := app.DB.FillWorldsByID(context.Background(), worlds)
87+
if err != nil {
88+
return http.Error(request, err)
89+
}
90+
91+
for i = range worlds {
92+
worlds[i].RandomNumber = rand.IntN(10000) + 1
93+
}
94+
95+
slices.SortFunc(worlds, func(a, b models.World) int {
96+
return a.ID - b.ID
97+
})
98+
99+
err = app.DB.UpdateWorlds(context.Background(), worlds)
100+
if err != nil {
101+
return http.Error(request, err)
102+
}
103+
104+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)
105+
}
106+
107+
func (app *App) HandleCachedQuery(request *http.Request) *http.Response {
108+
n := normalizeNumber(request.Params.Lookup("n"))
109+
110+
i, worlds := 0, make(models.Worlds, n)
111+
112+
for i = range worlds {
113+
worlds[i] = app.Cache[rand.Int32N(10000)]
114+
}
115+
116+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)
117+
}
118+
119+
func (app *App) HandleFortune(request *http.Request) *http.Response {
120+
fortunes, err := app.DB.GetFortunes(context.Background())
121+
if err != nil {
122+
return http.Error(request, err)
123+
}
124+
125+
fortunes = append(fortunes, models.Fortune{
126+
Message: "Additional fortune added at request time.",
127+
})
128+
129+
slices.SortFunc(fortunes, func(a, b models.Fortune) int {
130+
if a.Message < b.Message {
131+
return -1
132+
} else if a.Message > b.Message {
133+
return 1
134+
}
135+
136+
return 0
137+
})
138+
139+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").ContentType(mime.HTML + "; charset=UTF-8").String(templates.HTMLFortunes(fortunes))
140+
}
141+
142+
func (app *App) HandlePlaintext(request *http.Request) *http.Response {
143+
return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").ContentType(mime.Plain).String("Hello, World!")
144+
}
145+
146+
func normalizeNumber(nString string, found bool) int {
147+
if !found {
148+
nString = "0"
149+
}
150+
151+
n, err := strconv.Atoi(nString)
152+
if err != nil {
153+
n = 0
154+
}
155+
156+
if n < 1 {
157+
n = 1
158+
} else if n > 500 {
159+
n = 500
160+
}
161+
162+
return n
163+
}

0 commit comments

Comments
 (0)