116 lines
2.6 KiB
Go
116 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"runtime"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
type row struct {
|
|
ID int64 `json:"id"`
|
|
Text string `json:"text"`
|
|
Weight float64 `json:"weight"`
|
|
Note *string `json:"note"`
|
|
}
|
|
|
|
type payload struct {
|
|
Rows []row `json:"rows"`
|
|
Raw json.RawMessage `json:"raw"`
|
|
}
|
|
|
|
type envelope struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data any `json:"data"`
|
|
}
|
|
|
|
func handle(writer http.ResponseWriter, request *http.Request) {
|
|
typed := request.URL.Path == "/benchmark/echo/echo"
|
|
if request.Method != http.MethodPost || (!typed && request.URL.Path != "/benchmark/echo/raw") {
|
|
http.NotFound(writer, request)
|
|
return
|
|
}
|
|
body := http.MaxBytesReader(writer, request.Body, 16*1024*1024)
|
|
defer body.Close()
|
|
decoder := json.NewDecoder(body)
|
|
decoder.DisallowUnknownFields()
|
|
var result any
|
|
var err error
|
|
if typed {
|
|
var input struct {
|
|
Payload payload `json:"payload"`
|
|
}
|
|
err = decoder.Decode(&input)
|
|
result = input.Payload
|
|
} else {
|
|
var input struct {
|
|
Source json.RawMessage `json:"source"`
|
|
}
|
|
err = decoder.Decode(&input)
|
|
result = input.Source
|
|
}
|
|
var extra any
|
|
if err != nil || decoder.Decode(&extra) != io.EOF {
|
|
http.Error(writer, "invalid JSON", http.StatusBadRequest)
|
|
return
|
|
}
|
|
encoded, err := json.Marshal(envelope{0, "ok", result})
|
|
if err != nil {
|
|
http.Error(writer, "invalid response", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
writer.Header().Set("Content-Type", "application/json")
|
|
writer.Write(encoded)
|
|
}
|
|
|
|
func run() error {
|
|
runtime.GOMAXPROCS(1)
|
|
content, err := os.ReadFile("config/setting.json")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var settings struct {
|
|
HTTP struct {
|
|
Port uint16 `json:"port"`
|
|
} `json:"http"`
|
|
}
|
|
if err := json.Unmarshal(content, &settings); err != nil {
|
|
return err
|
|
}
|
|
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", settings.HTTP.Port))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
server := &http.Server{Handler: http.HandlerFunc(handle), ReadHeaderTimeout: 10 * time.Second, IdleTimeout: 10 * time.Second}
|
|
stopping := make(chan os.Signal, 1)
|
|
signal.Notify(stopping, syscall.SIGTERM)
|
|
defer signal.Stop(stopping)
|
|
closed := make(chan error, 1)
|
|
go func() {
|
|
<-stopping
|
|
context, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
closed <- server.Shutdown(context)
|
|
}()
|
|
if err := server.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
|
|
return err
|
|
}
|
|
return <-closed
|
|
}
|
|
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|