Compare commits
62 Commits
e6bef16366
...
renovate/g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2955fd0121 | ||
| 6caee54f4d | |||
|
|
fb075a8820 | ||
| 5af162aff2 | |||
|
|
e20373f556 | ||
| 9a0a7b8d6c | |||
|
|
8a1ef68a01 | ||
| 50fdbd1c30 | |||
|
|
a042e01d3e | ||
| 208afccaf5 | |||
|
|
ea74f04f3c | ||
| 149f347510 | |||
|
|
ae18004048 | ||
| 31f5a7649f | |||
|
|
f1830bed2f | ||
| b72a8e751c | |||
|
|
8c8b64dddd | ||
| be3661ae1c | |||
|
|
c924f7e360 | ||
| 9d4af9e7c5 | |||
|
|
25cf893cb7 | ||
| 2c84486945 | |||
|
|
6aa2d6d2c8 | ||
| cfe6bbaef3 | |||
|
|
37bb111127 | ||
| 55e0a6bd5c | |||
|
|
1e43763d8c | ||
| d9a029b3d1 | |||
|
|
b9746793f4 | ||
| 6c3d34143b | |||
|
|
fee35e60af | ||
| d68005b17c | |||
|
|
d5f7b40e24 | ||
| f50e12bdef | |||
|
|
2bc5373924 | ||
| 6d5cc4045c | |||
|
|
a1cc5cd483 | ||
| 688d0c9ca8 | |||
| ef067ec0d0 | |||
|
|
9adc35e806 | ||
|
|
79a907e618 | ||
| 74939c8456 | |||
|
|
3ddbe87d97 | ||
| 4b37041dff | |||
|
|
4ed91e01a9 | ||
| ea0cf4622f | |||
|
|
6a2a4d217f | ||
| 7cfbe3cd34 | |||
|
|
73ee86eb9f | ||
| a7368c182a | |||
|
|
88cd7a4ce9 | ||
|
68d7d1b481
|
|||
|
d703edb282
|
|||
|
a45deac7c8
|
|||
|
5521a326cf
|
|||
|
373013a74d
|
|||
|
2064a593d1
|
|||
|
6f13e4021e
|
|||
|
b91b9b2ed0
|
|||
|
038ef99183
|
|||
|
15a7690e36
|
|||
|
e56a541a40
|
@@ -9,20 +9,32 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
container: catthehacker/ubuntu:act-latest
|
||||||
matrix:
|
|
||||||
go: [ '1.21' ]
|
|
||||||
name: Go ${{ matrix.go }} test
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set up Go
|
# - name: Set up Go
|
||||||
uses: actions/setup-go@v4
|
# uses: actions/setup-go@v4
|
||||||
|
# with:
|
||||||
|
# go-version: 1.21
|
||||||
|
|
||||||
|
# - name: Build
|
||||||
|
# run: go build -v ./...
|
||||||
|
|
||||||
|
- name: Login to Docker registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
registry: git.nice.net.nz
|
||||||
|
username: hads
|
||||||
|
password: ${{ secrets.PAT }}
|
||||||
|
|
||||||
- name: Build
|
- name: Set up Docker Buildx
|
||||||
run: go build -v ./...
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
# - name: Test
|
- name: Build and push
|
||||||
# run: go test -v ./...
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: git.nice.net.nz/hads/snice:latest
|
||||||
|
|||||||
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
|
ENV VERSION 0.1.0
|
||||||
|
ENV CGO_ENABLED 0
|
||||||
|
ENV GOOS linux
|
||||||
|
ENV BUILD_DIR /build
|
||||||
|
|
||||||
|
RUN mkdir -p ${BUILD_DIR}
|
||||||
|
WORKDIR ${BUILD_DIR}
|
||||||
|
|
||||||
|
RUN adduser --system --no-create-home --uid 1000 --shell /sbin/nologin app
|
||||||
|
|
||||||
|
COPY go.* ./
|
||||||
|
COPY *.go ./
|
||||||
|
RUN go build -v -o / ./...
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
USER app
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
HEALTHCHECK --timeout=10s CMD ["/snice", "healthcheck"]
|
||||||
|
|
||||||
|
COPY --from=builder /etc/passwd /etc/passwd
|
||||||
|
COPY README.md /srv/README.md
|
||||||
|
COPY --from=builder /snice /
|
||||||
|
|
||||||
|
VOLUME /srv
|
||||||
|
|
||||||
|
ENTRYPOINT ["/snice"]
|
||||||
|
CMD ["serve"]
|
||||||
26
README.md
26
README.md
@@ -1,3 +1,27 @@
|
|||||||
# snice
|
# snice
|
||||||
|
|
||||||
Simple Static Server
|
Simple Static Server designed to be run in Docker and served behind [Traefik](https://doc.traefik.io/traefik/)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME:
|
||||||
|
snice - Serve Static Files
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
snice [global options] command [command options] [arguments...]
|
||||||
|
|
||||||
|
VERSION:
|
||||||
|
v0.2.0
|
||||||
|
|
||||||
|
COMMANDS:
|
||||||
|
serve, s Serve directory
|
||||||
|
healthcheck, hc Call healthcheck endpoint
|
||||||
|
help, h Shows a list of commands or help for one command
|
||||||
|
|
||||||
|
GLOBAL OPTIONS:
|
||||||
|
--quiet, -q (default: false)
|
||||||
|
--port value, -p value Port to serve on (default: "3000") [$PORT]
|
||||||
|
--help, -h show help
|
||||||
|
--version, -v print the version
|
||||||
|
```
|
||||||
10
go.mod
10
go.mod
@@ -1,14 +1,14 @@
|
|||||||
module git.nice.net.nz/hads/snice
|
module git.nice.net.nz/hads/snice
|
||||||
|
|
||||||
go 1.21.3
|
go 1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/lmittmann/tint v1.1.2
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
github.com/urfave/cli/v3 v3.6.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
46
go.sum
46
go.sum
@@ -1,10 +1,52 @@
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/lmittmann/tint v1.0.2 h1:9XZ+JvEzjvd3VNVugYqo3j+dl0NRju8k9FquAusJExM=
|
||||||
|
github.com/lmittmann/tint v1.0.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.0.3 h1:W5PHeA2D8bBJVvabNfQD/XW9HPLZK1XoPZH0cq8NouQ=
|
||||||
|
github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc=
|
||||||
|
github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw=
|
||||||
|
github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.0.6 h1:vkkuDAZXc0EFGNzYjWcV0h7eEX+uujH48f/ifSkJWgc=
|
||||||
|
github.com/lmittmann/tint v1.0.6/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y=
|
||||||
|
github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.1.0 h1:0hDmvuGv3U+Cep/jHpPxwjrCFjT6syam7iY7nTmA7ug=
|
||||||
|
github.com/lmittmann/tint v1.1.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.1.1 h1:xmmGuinUsCSxWdwH1OqMUQ4tzQsq3BdjJLAAmVKJ9Dw=
|
||||||
|
github.com/lmittmann/tint v1.1.1/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
|
github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w=
|
||||||
|
github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||||
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
|
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
|
||||||
|
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
|
||||||
|
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
||||||
|
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
||||||
|
github.com/urfave/cli/v2 v2.27.3 h1:/POWahRmdh7uztQ3CYnaDddk0Rm90PyOgIxgW2rr41M=
|
||||||
|
github.com/urfave/cli/v2 v2.27.3/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
|
||||||
|
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
|
||||||
|
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
|
||||||
|
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
|
|||||||
175
main.go
175
main.go
@@ -2,44 +2,120 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log/slog"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/lmittmann/tint"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/exp/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func serveLogger(logger *log.Logger, next http.Handler) http.Handler {
|
type (
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
// struct for holding response details
|
||||||
remoteHost, _, _ := strings.Cut(r.RemoteAddr, ":")
|
responseData struct {
|
||||||
logger.Printf("%v %v %v\n", remoteHost, r.Method, r.URL.Path)
|
status int
|
||||||
next.ServeHTTP(w, r)
|
size int
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// our http.ResponseWriter implementation
|
||||||
|
loggingResponseWriter struct {
|
||||||
|
http.ResponseWriter // compose original http.ResponseWriter
|
||||||
|
responseData *responseData
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *loggingResponseWriter) Write(b []byte) (int, error) {
|
||||||
|
size, err := r.ResponseWriter.Write(b) // write response using original http.ResponseWriter
|
||||||
|
r.responseData.size += size // capture size
|
||||||
|
return size, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func timeHandler(w http.ResponseWriter, r *http.Request) {
|
func (r *loggingResponseWriter) WriteHeader(statusCode int) {
|
||||||
fmt.Fprint(w, time.Now().Format("02 Jan 2006 15:04:05 MST"))
|
r.ResponseWriter.WriteHeader(statusCode) // write status code using original http.ResponseWriter
|
||||||
|
r.responseData.status = statusCode // capture status code
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithLogging(h http.Handler) http.Handler {
|
||||||
|
loggingFn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
remoteAddr := r.RemoteAddr
|
||||||
|
fwdAddress := r.Header.Get("X-Forwarded-For")
|
||||||
|
if fwdAddress != "" {
|
||||||
|
remoteAddr = fwdAddress
|
||||||
|
ips := strings.Split(fwdAddress, ", ")
|
||||||
|
if len(ips) > 1 {
|
||||||
|
remoteAddr = ips[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remoteAddr, _, err := net.SplitHostPort(remoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Failed to format remoteAddr", slog.Any("err", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData := &responseData{
|
||||||
|
status: 0,
|
||||||
|
size: 0,
|
||||||
|
}
|
||||||
|
lrw := loggingResponseWriter{
|
||||||
|
ResponseWriter: w, // compose original http.ResponseWriter
|
||||||
|
responseData: responseData,
|
||||||
|
}
|
||||||
|
h.ServeHTTP(&lrw, r) // inject our implementation of http.ResponseWriter
|
||||||
|
|
||||||
|
duration := time.Since(start)
|
||||||
|
|
||||||
|
// t=2023-10-27T18:08:47.231895532+13:00
|
||||||
|
slog.Info("Request Completed:",
|
||||||
|
slog.String("method", r.Method),
|
||||||
|
slog.String("path", r.RequestURI),
|
||||||
|
slog.String("url", r.URL.Path),
|
||||||
|
slog.String("host", r.Host),
|
||||||
|
slog.String("referer", r.Referer()),
|
||||||
|
slog.String("remote_addr", remoteAddr),
|
||||||
|
slog.Int("status", responseData.status),
|
||||||
|
slog.String("duration", duration.String()),
|
||||||
|
slog.Int("size", responseData.size),
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
return http.HandlerFunc(loggingFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pingHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("OK"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// handler := slog.NewJSONHandler(os.Stdout, nil)
|
logLevel := &slog.LevelVar{} // INFO
|
||||||
handler := slog.NewTextHandler(os.Stdout, nil)
|
|
||||||
slog.SetDefault(slog.New(handler))
|
opts := tint.Options{
|
||||||
logger := slog.NewLogLogger(handler, slog.LevelError)
|
Level: logLevel,
|
||||||
|
}
|
||||||
|
logLevel.Set(slog.LevelDebug)
|
||||||
|
handler := tint.NewHandler(os.Stdout, &opts)
|
||||||
|
logger := slog.New(handler)
|
||||||
|
slog.SetDefault(logger)
|
||||||
|
|
||||||
var host string
|
var host string
|
||||||
var port string
|
var port string
|
||||||
var directory string
|
var directory string
|
||||||
|
|
||||||
app := &cli.App{
|
app := &cli.App{
|
||||||
Name: "snice",
|
Name: "snice",
|
||||||
Usage: "Serve Static Files",
|
Usage: "Serve Static Files",
|
||||||
Version: "v0.1.0",
|
Version: "v0.2.0",
|
||||||
DefaultCommand: "",
|
EnableBashCompletion: true,
|
||||||
|
Compiled: time.Time{},
|
||||||
|
Authors: []*cli.Author{
|
||||||
|
{Name: "Hadley Rich", Email: "hads@nice.net.nz"},
|
||||||
|
},
|
||||||
|
SliceFlagSeparator: "",
|
||||||
|
UseShortOptionHandling: true,
|
||||||
|
Suggest: true,
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "serve",
|
Name: "serve",
|
||||||
@@ -48,24 +124,30 @@ func main() {
|
|||||||
Action: func(cCtx *cli.Context) error {
|
Action: func(cCtx *cli.Context) error {
|
||||||
var addr string = host + ":" + port
|
var addr string = host + ":" + port
|
||||||
|
|
||||||
srv := &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
ErrorLog: logger,
|
|
||||||
}
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/time", timeHandler)
|
mux.Handle("/ping", http.HandlerFunc(pingHandler))
|
||||||
fileHandler := serveLogger(logger, http.FileServer(http.Dir(directory)))
|
fileHandler := http.FileServer(http.Dir(directory))
|
||||||
mux.Handle("/", fileHandler)
|
mux.Handle("/", fileHandler)
|
||||||
srv.Handler = mux
|
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
ReadTimeout: 5 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
IdleTimeout: 120 * time.Second,
|
||||||
|
}
|
||||||
|
srv.Handler = WithLogging(mux)
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", addr)
|
listener, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println(err)
|
slog.Error("Listen error", err)
|
||||||
}
|
}
|
||||||
scheme := "http://"
|
slog.Info("Starting server",
|
||||||
logger.Printf("Serving directory %q on %v%v", directory, scheme, listener.Addr())
|
slog.String("dir", directory),
|
||||||
|
slog.String("addr", fmt.Sprintf(":%s", listener.Addr())),
|
||||||
|
)
|
||||||
err = srv.Serve(listener)
|
err = srv.Serve(listener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println(err)
|
slog.Error("Serve error", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@@ -74,14 +156,14 @@ func main() {
|
|||||||
Name: "directory",
|
Name: "directory",
|
||||||
Aliases: []string{"dir", "d"},
|
Aliases: []string{"dir", "d"},
|
||||||
EnvVars: []string{"DIRECTORY"},
|
EnvVars: []string{"DIRECTORY"},
|
||||||
Value: ".",
|
Value: "/srv",
|
||||||
Usage: "Directory to serve",
|
Usage: "Directory to serve",
|
||||||
Destination: &directory,
|
Destination: &directory,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "host",
|
Name: "host",
|
||||||
EnvVars: []string{"HOST"},
|
EnvVars: []string{"HOST"},
|
||||||
Value: "127.0.0.1",
|
Value: "0.0.0.0",
|
||||||
Usage: "Host to listen on",
|
Usage: "Host to listen on",
|
||||||
Destination: &host,
|
Destination: &host,
|
||||||
}},
|
}},
|
||||||
@@ -91,11 +173,20 @@ func main() {
|
|||||||
Aliases: []string{"hc"},
|
Aliases: []string{"hc"},
|
||||||
Usage: "Call healthcheck endpoint",
|
Usage: "Call healthcheck endpoint",
|
||||||
Action: func(cCtx *cli.Context) error {
|
Action: func(cCtx *cli.Context) error {
|
||||||
_, err := http.Get(fmt.Sprintf("http://127.0.0.1:%s/health", port))
|
url := fmt.Sprintf("http://127.0.0.1:%s/ping", port)
|
||||||
if err != nil {
|
slog.Debug("Healthcheck: ", slog.String("url", url))
|
||||||
os.Exit(1)
|
client := http.Client{
|
||||||
|
Timeout: 1 * time.Second,
|
||||||
}
|
}
|
||||||
return nil
|
res, err := client.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return cli.Exit("FAIL", 1)
|
||||||
|
}
|
||||||
|
if res.StatusCode == 200 {
|
||||||
|
return cli.Exit("OK", 0)
|
||||||
|
}
|
||||||
|
slog.Debug(fmt.Sprintf("Status: %d\n", res.StatusCode))
|
||||||
|
return cli.Exit("FAIL", 1)
|
||||||
}}},
|
}}},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{Name: "quiet", Aliases: []string{"q"}},
|
&cli.BoolFlag{Name: "quiet", Aliases: []string{"q"}},
|
||||||
@@ -108,21 +199,9 @@ func main() {
|
|||||||
Destination: &port,
|
Destination: &port,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EnableBashCompletion: true,
|
|
||||||
Compiled: time.Time{},
|
|
||||||
Authors: []*cli.Author{},
|
|
||||||
Reader: nil,
|
|
||||||
Writer: nil,
|
|
||||||
ErrWriter: nil,
|
|
||||||
SliceFlagSeparator: "",
|
|
||||||
DisableSliceFlagSeparator: false,
|
|
||||||
UseShortOptionHandling: true,
|
|
||||||
Suggest: true,
|
|
||||||
AllowExtFlags: false,
|
|
||||||
SkipFlagParsing: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
log.Fatal(err)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
renovate.json
Normal file
6
renovate.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"local>hads/renovate-config"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user