Skip to content

Commit

Permalink
chore: add example project to expose multiple kind of ports
Browse files Browse the repository at this point in the history
  • Loading branch information
YuukanOO committed Apr 24, 2024
1 parent 4c1cda8 commit cae1223
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
examples
Dockerfile
docker-compose.yml
compose.yml
docs
node_modules
**/Dockerfile
Expand Down
2 changes: 2 additions & 0 deletions examples/go-api/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
compose.yml
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions examples/multiple-ports/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
compose.yml
14 changes: 14 additions & 0 deletions examples/multiple-ports/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN go build -o app main.go

FROM alpine:3.16 AS runner
RUN addgroup --system app
RUN adduser --system app
USER app
WORKDIR /app
COPY --from=builder --chown=app:app /app/app ./
ENTRYPOINT ["./app"]
20 changes: 20 additions & 0 deletions examples/multiple-ports/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# multiple-ports

Quick & dirty project to test the **seelf** ability to handle multiple ports of specific types and check how they are managed by traefik.

## Usage

```sh
go run main.go -web 8080,8081 -tcp 9854,9855 -udp 9856,9857
```

## How to test

Quick & dirty ways to test if the server is actually listening.

```sh
curl http://localhost:8080 # HTTP
curl telnet://localhost:9855 <<< text # TCP
nc -v localhost 9855 # Other way for TCP
nc -v -u localhost 9856 # UDP
```
11 changes: 11 additions & 0 deletions examples/multiple-ports/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
app:
build: .
command: -web 8080,8081 -tcp 8082,8083 -udp 8084,8085
ports:
- "8080:8080"
- "8081:8081"
- "8082:8082/tcp"
- "8083:8083/tcp"
- "8084:8084/udp"
- "8085:8085/udp"
3 changes: 3 additions & 0 deletions examples/multiple-ports/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/YuukanOO/seelf/examples/multiple-ports

go 1.21.5
206 changes: 206 additions & 0 deletions examples/multiple-ports/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package main

import (
"context"
"errors"
"flag"
"log"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"strings"
"sync"
"syscall"
)

func main() {
var (
web, tcp, udp string
wg sync.WaitGroup
)

flag.StringVar(&web, "web", "", "Comma separated list of ports on which to expose a tiny echo web server")
flag.StringVar(&tcp, "tcp", "", "Comma separated list of ports on which to expose a tiny echo TCP server")
flag.StringVar(&udp, "udp", "", "Comma separated list of ports on which to expose a tiny echo UDP server")

flag.Parse()

exposeHttp(&wg, parsePorts(web)...)
exposeTCP(&wg, parsePorts(tcp)...)
exposeUDP(&wg, parsePorts(udp)...)

wg.Wait()
}

func exposeHttp(wg *sync.WaitGroup, ports ...int) {
for _, port := range ports {
server := http.Server{
Addr: ":" + strconv.Itoa(port),
}

server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from " + server.Addr))
})

wg.Add(1)

go func() {
defer wg.Done()

exit := makeExitChannel()

go func() {
log.Printf("Starting HTTP server on %s", server.Addr)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Printf("Failed to start HTTP server on %s: %v", server.Addr, err)
exit <- syscall.SIGTERM
}
}()

<-exit
log.Printf("Shutting down HTTP server on %s", server.Addr)
server.Shutdown(context.Background())
}()
}
}

func exposeTCP(wg *sync.WaitGroup, ports ...int) {
for _, port := range ports {
addr := net.TCPAddr{Port: port}
wg.Add(1)

go func() {
defer wg.Done()

var (
exit = makeExitChannel()
listener *net.TCPListener
err error
)

go func() {
log.Printf("Starting TCP server on %s", addr.String())

listener, err = net.ListenTCP("tcp", &addr)

if err != nil {
log.Printf("Failed to start TCP server on %s: %v", addr.String(), err)
exit <- syscall.SIGTERM
return
}

for {
conn, err := listener.Accept()

if errors.Is(err, net.ErrClosed) {
return
}

if err != nil {
log.Printf("Failed to accept connection on %s: %v", addr.String(), err)
continue
}

conn.Write([]byte("Hello from " + conn.LocalAddr().String()))
conn.Close()
}
}()

<-exit

if listener == nil {
return
}

log.Printf("Shutting down TCP server on %s", addr.String())
listener.Close()
}()
}
}

func exposeUDP(wg *sync.WaitGroup, ports ...int) {
for _, port := range ports {
addr := net.UDPAddr{Port: port}
wg.Add(1)

go func() {
defer wg.Done()

var (
exit = makeExitChannel()
conn *net.UDPConn
err error
)

go func() {
log.Printf("Starting UDP server on %s", addr.String())

conn, err = net.ListenUDP("udp", &addr)

if err != nil {
log.Printf("Failed to start UDP server on %s: %v", addr.String(), err)
exit <- syscall.SIGTERM
return
}

buf := make([]byte, 1024)

for {
_, addr, err := conn.ReadFrom(buf)

if errors.Is(err, net.ErrClosed) {
return
}

if err != nil {
log.Printf("Failed to read from UDP connection on %s: %v", addr.String(), err)
continue
}

conn.WriteTo([]byte("Hello from "+conn.LocalAddr().String()), addr)
}
}()

<-exit

if conn == nil {
return
}

log.Printf("Shutting down UDP server on %s", addr.String())
conn.Close()
}()
}
}

func makeExitChannel() chan os.Signal {
exit := make(chan os.Signal, 1)
signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM)
return exit
}

func parsePorts(value string) []int {
strs := strings.Split(value, ",")
ports := make([]int, 0, len(strs))

for _, str := range strs {
str = strings.TrimSpace(str)

if str == "" {
continue
}

p, err := strconv.Atoi(str)

if err != nil {
log.Printf("Failed to parse port %s: %v", str, err)
continue
}

ports = append(ports, p)
}

return ports
}
1 change: 1 addition & 0 deletions examples/sveltekit-hello/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Dockerfile
compose.yml
node_modules

0 comments on commit cae1223

Please sign in to comment.