Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
go-version: 'stable'
cache: true
- name: lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v9
- run: go mod tidy
- run: go get .
- name: Build
Expand Down
28 changes: 28 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
version: "2"
linters:
enable:
- asciicheck
- bidichk
- canonicalheader
- copyloopvar
#- cyclop
#- funlen
#- gocognit
#- gocyclo
- maintidx
#- nestif
#- lll
- decorder
- dupword
- durationcheck
- errname
- gosmopolitan
- misspell
- predeclared
- sloglint
- staticcheck
disable:
- errcheck
formatters:
enable:
- gofmt
1 change: 0 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !docker
// +build !docker

package main

Expand Down
22 changes: 11 additions & 11 deletions config_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ package main
import "time"

type SrvConfigBase struct {
Verbose bool `short:"v" long:"verbose" description:"log verbose"`
Quiet bool `short:"q" long:"quiet" description:"log quiet"`
Addr string `short:"l" long:"listen" default:"localhost:" value-name:"[host]:port"`
Proto string `long:"protocol" default:"tcp" value-name:"tcp/unix"`
Prefix string `short:"p" long:"prefix" default:"/" value-name:"url-prefix"`
BaseDir string `short:"b" long:"base-dir" default:"." value-name:"dirname"`
Suffix string `short:"s" long:"suffix" value-name:".ext"`
JSONLog bool `long:"json-log"`
Runner string `long:"runner" default:"os" value-name:"name"`
Version bool `short:"V" long:"version"`
OtelProvider string `long:"opentelemetry" choice:"stdout" choice:"zipkin" choice:"otlp" choice:"otlp-http"`
Verbose bool `short:"v" long:"verbose" description:"log verbose"`
Quiet bool `short:"q" long:"quiet" description:"log quiet"`
Addr string `short:"l" long:"listen" default:"localhost:" value-name:"[host]:port"`
Proto string `long:"protocol" default:"tcp" value-name:"tcp/unix"`
Prefix string `short:"p" long:"prefix" default:"/" value-name:"url-prefix"`
BaseDir string `short:"b" long:"base-dir" default:"." value-name:"dirname"`
Suffix string `short:"s" long:"suffix" value-name:".ext"`
JSONLog bool `long:"json-log"`
Runner string `long:"runner" default:"os" value-name:"name"`
Version bool `short:"V" long:"version"`
OtelProvider string `long:"opentelemetry" choice:"stdout" choice:"zipkin" choice:"otlp" choice:"otlp-http"`
Timeout time.Duration `short:"t" long:"timeout" default:"1m"`
}
1 change: 0 additions & 1 deletion config_docker.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build docker
// +build docker

package main

Expand Down
1 change: 0 additions & 1 deletion exec_docker.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build docker
// +build docker

package main

Expand Down
1 change: 0 additions & 1 deletion exec_docker_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build docker
// +build docker

package main

Expand Down
27 changes: 10 additions & 17 deletions exec_if.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ type Runner interface {
}

// OutputFilter converts CGI output to http.ResponseWriter
func OutputFilter(stdout io.Reader, w http.ResponseWriter, wg *sync.WaitGroup) error {
if wg != nil {
defer wg.Done()
}
func OutputFilter(stdout io.Reader, w http.ResponseWriter) error {
rd := bufio.NewReader(stdout)
statusCode := http.StatusOK
for {
Expand Down Expand Up @@ -156,20 +153,19 @@ func RunBy(opts SrvConfig, runner Runner, w http.ResponseWriter, r *http.Request
}
pr, pw := io.Pipe()
var wg sync.WaitGroup
wg.Add(1)
go func() {
if err := OutputFilter(pr, w, &wg); err != nil {
wg.Go(func() {
if err := OutputFilter(pr, w); err != nil {
slog.Error("output filter", "error", err)
}
span.AddEvent("ofilter finished")
}()
})
_, span2 := otel.Tracer("").Start(ctx, "run")
span2.SetAttributes(attribute.String("script", bn2))
if span2.IsRecording() {
carrier := propagation.MapCarrier{}
otel.GetTextMapPropagator().Inject(ctx, carrier)
for k, v := range carrier {
escaped := strings.Replace(strings.ToUpper(k), "-", "_", -1)
escaped := strings.ReplaceAll(strings.ToUpper(k), "-", "_")
env[fmt.Sprintf("HTTP_%s", escaped)] = v
}
}
Expand All @@ -187,11 +183,8 @@ func RunBy(opts SrvConfig, runner Runner, w http.ResponseWriter, r *http.Request
return nil
}

// DoPipe calls io.Copy() and wg.Done()
func DoPipe(input io.Reader, output io.Writer, wg *sync.WaitGroup) error {
if wg != nil {
defer wg.Done()
}
// DoPipe calls io.Copy()
func DoPipe(input io.Reader, output io.Writer) error {
ilen, err := io.Copy(output, input)
if err != nil {
slog.Error("pipe error:", "error", err)
Expand All @@ -203,14 +196,14 @@ func DoPipe(input io.Reader, output io.Writer, wg *sync.WaitGroup) error {

func timeoutWait(wg *sync.WaitGroup, timeout time.Duration) bool {
c := make(chan struct{})
go func(){
go func() {
defer close(c)
wg.Wait()
}()
select {
case <-c:
return false // normal
return false // normal
case <-time.After(timeout):
return true // timeout
return true // timeout
}
}
22 changes: 12 additions & 10 deletions exec_if_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,27 @@ func TestDoPipeWriteClose(t *testing.T) {
rd, wr := io.Pipe()
var wg sync.WaitGroup
wr.Close()
wg.Add(1)
err := DoPipe(rd, wr, &wg)
wg.Go(func() {
err := DoPipe(rd, wr)
if err != nil {
t.Errorf("pipe error: %s", err)
}
})
wg.Wait()
if err != nil {
t.Errorf("pipe error: %s", err)
}
}

func TestDoPipeReadClose(t *testing.T) {
t.Parallel()
rd, wr := io.Pipe()
var wg sync.WaitGroup
rd.Close()
wg.Add(1)
err := DoPipe(rd, wr, &wg)
wg.Go(func() {
err := DoPipe(rd, wr)
if err == nil {
t.Error("pipe no-error")
}
})
wg.Wait()
if err == nil {
t.Error("pipe no-error")
}
}

type runner1 struct{}
Expand Down
25 changes: 11 additions & 14 deletions exec_os.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,27 +60,24 @@ func (runner *OsRunner) Run(conf SrvConfig, cmdname string, envvar map[string]st
}
}()
var wg sync.WaitGroup
wg.Add(1)
go func() {
if err := DoPipe(stdin, cmdStdin, &wg); err != nil {
wg.Go(func() {
if err := DoPipe(stdin, cmdStdin); err != nil {
slog.Error("stdin", "error", err)
}
}()
wg.Add(1)
go func() {
if err := DoPipe(cmdStderr, stderr, &wg); err != nil {
})
wg.Go(func() {
if err := DoPipe(cmdStderr, stderr); err != nil {
slog.Error("stderr", "error", err)
}
}()
wg.Add(1)
go func() {
if err := DoPipe(cmdStdout, stdout, &wg); err != nil {
})
wg.Go(func() {
if err := DoPipe(cmdStdout, stdout); err != nil {
slog.Error("stdout", "error", err)
}
}()
if timeoutWait(&wg, conf.Timeout){
})
if timeoutWait(&wg, conf.Timeout) {
slog.Warn("timeout")
if err := cmd.Process.Kill(); err != nil{
if err := cmd.Process.Kill(); err != nil {
slog.Error("kill failed", "error", err)
}
return fmt.Errorf("timeout %v", conf.Timeout)
Expand Down
6 changes: 2 additions & 4 deletions exec_os_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ func TestOsRun(t *testing.T) {
runner := OsRunner{}
conf := SrvConfig{}
conf.Timeout = time.Duration(1000_000_000)
tmpd, err := os.MkdirTemp("", "")
tmpd, err := os.MkdirTemp("/var/tmp", "")
if err != nil {
t.Error("tmpdir", err)
}
defer os.RemoveAll(tmpd)
conf.BaseDir = tmpd
ctx := context.Background()
if err = os.WriteFile(filepath.Join(tmpd, "cmd1"), []byte("#! /bin/sh\n"), 0755); err != nil {
Expand All @@ -70,8 +69,7 @@ func TestOsRun(t *testing.T) {
stdin := io.NopCloser(&bytes.Buffer{})
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
err = runner.Run(conf, "cmd1", env, stdin, stdout, stderr, ctx)
if err != nil {
if err = runner.Run(conf, "cmd1", env, stdin, stdout, stderr, ctx); err != nil {
t.Error("error", err)
}
if stdout.Len() != 0 {
Expand Down
19 changes: 5 additions & 14 deletions exec_wasmer.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wasmer
// +build wasmer

package main

Expand All @@ -18,10 +17,7 @@ import (
type WasmerRunner struct {
}

func (runner *WasmerRunner) pipeStdout(wasiEnv *wasmer.WasiEnvironment, output io.Writer, wg *sync.WaitGroup) error {
if wg != nil {
defer wg.Done()
}
func (runner *WasmerRunner) pipeStdout(wasiEnv *wasmer.WasiEnvironment, output io.Writer) error {
data := wasiEnv.ReadStdout()
slog.Info("stdout", "length", len(data))
dlen, err := output.Write(data)
Expand All @@ -33,10 +29,7 @@ func (runner *WasmerRunner) pipeStdout(wasiEnv *wasmer.WasiEnvironment, output i
return nil
}

func (runner *WasmerRunner) pipeStderr(wasiEnv *wasmer.WasiEnvironment, output io.Writer, wg *sync.WaitGroup) error {
if wg != nil {
defer wg.Done()
}
func (runner *WasmerRunner) pipeStderr(wasiEnv *wasmer.WasiEnvironment, output io.Writer) error {
data := wasiEnv.ReadStderr()
slog.Info("stderr", "length", len(data))
dlen, err := output.Write(data)
Expand Down Expand Up @@ -96,11 +89,9 @@ func (runner *WasmerRunner) Run(conf SrvConfig, cmdname string, envvar map[strin
return err
}
var wg sync.WaitGroup
wg.Add(1)
go runner.pipeStdout(wasiEnv, stdout, &wg)
wg.Add(1)
go runner.pipeStderr(wasiEnv, stderr, &wg)
if timeoutWait(&wg, conf.Timeout){
wg.Go(func() { runner.pipeStdout(wasiEnv, stdout) })
wg.Go(func() { runner.pipeStderr(wasiEnv, stderr) })
if timeoutWait(&wg, conf.Timeout) {
slog.Warn("timeout")
return nil
}
Expand Down
1 change: 0 additions & 1 deletion exec_wasmer_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wasmer
// +build wasmer

package main

Expand Down
1 change: 0 additions & 1 deletion exec_wasmtime.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wasmtime
// +build wasmtime

package main

Expand Down
1 change: 0 additions & 1 deletion exec_wasmtime_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wasmtime
// +build wasmtime

package main

Expand Down
1 change: 0 additions & 1 deletion exec_wazero.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wazero
// +build wazero

package main

Expand Down
1 change: 0 additions & 1 deletion exec_wazero_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wazero
// +build wazero

package main

Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/wtnb75/httpcgi

go 1.24.0

toolchain go1.24.1
go 1.25.0

require (
github.com/bytecodealliance/wasmtime-go v1.0.0
Expand Down
10 changes: 6 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,25 +70,27 @@ func main() {
if err != nil {
slog.Error("abs", "error", err)
}
if opts.OtelProvider == "stdout" {
switch opts.OtelProvider {

case "stdout":
if fin, err := initOtelStdout(); err != nil {
slog.Error("otel-stdout", "error", err)
} else {
defer fin()
}
} else if opts.OtelProvider == "zipkin" {
case "zipkin":
if fin, err := initOtelZipkin(); err != nil {
slog.Error("otel-zipkin", "error", err)
} else {
defer fin()
}
} else if opts.OtelProvider == "otlp" {
case "otlp":
if fin, err := initOtelOtlp(); err != nil {
slog.Error("otel-otlp", "error", err)
} else {
defer fin()
}
} else if opts.OtelProvider == "otlp-http" {
case "otlp-http":
if fin, err := initOtelOtlpHttp(); err != nil {
slog.Error("otel-otlp-http", "error", err)
} else {
Expand Down
1 change: 0 additions & 1 deletion wasm_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build wazero || wasmtime || wasmer
// +build wazero wasmtime wasmer

package main

Expand Down