mirror of
https://codeberg.org/tiff/goload.git
synced 2025-01-31 05:59:15 +00:00
Compare commits
No commits in common. "f94d0b33afdcaec1aa4560b7643db09bc8640543" and "fbca89e751d0fd6546568a191a06193267e34488" have entirely different histories.
f94d0b33af
...
fbca89e751
46
.air.toml
Normal file
46
.air.toml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = []
|
||||||
|
bin = "./main"
|
||||||
|
cmd = "make build"
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata", "node_modules"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
post_cmd = []
|
||||||
|
pre_cmd = []
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = false
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
42
.goreleaser.yml
Normal file
42
.goreleaser.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
version: 2
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
|
||||||
|
env:
|
||||||
|
- PACKAGE_PATH=github.com/<user>/<repo>/cmd
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- binary: "{{ .ProjectName }}"
|
||||||
|
main: ./cmd/api
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
ldflags:
|
||||||
|
- -s -w -X {{.Env.PACKAGE_PATH}}={{.Version}}
|
||||||
|
release:
|
||||||
|
prerelease: auto
|
||||||
|
|
||||||
|
universal_binaries:
|
||||||
|
- replace: true
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- name_template: >
|
||||||
|
{{- .ProjectName }}_{{- .Version }}_{{- title .Os }}_{{- if eq .Arch "amd64" }}x86_64{{- else if eq .Arch "386" }}i386{{- else }}{{ .Arch }}{{ end }}{{- if .Arm }}v{{ .Arm }}{{ end -}}
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
format: zip
|
||||||
|
builds_info:
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
43
Makefile
Normal file
43
Makefile
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Simple Makefile for a Go project
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
all: build test
|
||||||
|
|
||||||
|
build:
|
||||||
|
@echo "Building..."
|
||||||
|
|
||||||
|
|
||||||
|
@go build -o main cmd/api/main.go
|
||||||
|
|
||||||
|
# Run the application
|
||||||
|
run:
|
||||||
|
@go run cmd/api/main.go
|
||||||
|
|
||||||
|
# Test the application
|
||||||
|
test:
|
||||||
|
@echo "Testing..."
|
||||||
|
@go test ./... -v
|
||||||
|
|
||||||
|
# Clean the binary
|
||||||
|
clean:
|
||||||
|
@echo "Cleaning..."
|
||||||
|
@rm -f main
|
||||||
|
|
||||||
|
# Live Reload
|
||||||
|
watch:
|
||||||
|
@if command -v air > /dev/null; then \
|
||||||
|
air; \
|
||||||
|
echo "Watching...";\
|
||||||
|
else \
|
||||||
|
read -p "Go's 'air' is not installed on your machine. Do you want to install it? [Y/n] " choice; \
|
||||||
|
if [ "$$choice" != "n" ] && [ "$$choice" != "N" ]; then \
|
||||||
|
go install github.com/air-verse/air@latest; \
|
||||||
|
air; \
|
||||||
|
echo "Watching...";\
|
||||||
|
else \
|
||||||
|
echo "You chose not to install air. Exiting..."; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: all build run test clean watch
|
57
cmd/api/main.go
Normal file
57
cmd/api/main.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"goload/internal/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func gracefulShutdown(apiServer *http.Server, done chan bool) {
|
||||||
|
// Create context that listens for the interrupt signal from the OS.
|
||||||
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
// Listen for the interrupt signal.
|
||||||
|
<-ctx.Done()
|
||||||
|
|
||||||
|
log.Println("shutting down gracefully, press Ctrl+C again to force")
|
||||||
|
|
||||||
|
// The context is used to inform the server it has 5 seconds to finish
|
||||||
|
// the request it is currently handling
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := apiServer.Shutdown(ctx); err != nil {
|
||||||
|
log.Printf("Server forced to shutdown with error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Server exiting")
|
||||||
|
|
||||||
|
// Notify the main goroutine that the shutdown is complete
|
||||||
|
done <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
server := server.NewServer()
|
||||||
|
|
||||||
|
// Create a done channel to signal when the shutdown is complete
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
|
||||||
|
// Run graceful shutdown in a separate goroutine
|
||||||
|
go gracefulShutdown(server, done)
|
||||||
|
|
||||||
|
err := server.ListenAndServe()
|
||||||
|
if err != nil && err != http.ErrServerClosed {
|
||||||
|
panic(fmt.Sprintf("http server error: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the graceful shutdown to complete
|
||||||
|
<-done
|
||||||
|
log.Println("Graceful shutdown complete.")
|
||||||
|
}
|
2
go.mod
2
go.mod
@ -1,3 +1,5 @@
|
|||||||
module goload
|
module goload
|
||||||
|
|
||||||
go 1.23.2
|
go 1.23.2
|
||||||
|
|
||||||
|
require github.com/joho/godotenv v1.5.1
|
||||||
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
49
internal/server/routes.go
Normal file
49
internal/server/routes.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) RegisterRoutes() http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
// Register routes
|
||||||
|
mux.HandleFunc("/", s.HelloWorldHandler)
|
||||||
|
|
||||||
|
// Wrap the mux with CORS middleware
|
||||||
|
return s.corsMiddleware(mux)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) corsMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Set CORS headers
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", "*") // Replace "*" with specific origins if needed
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, X-CSRF-Token")
|
||||||
|
w.Header().Set("Access-Control-Allow-Credentials", "false") // Set to "true" if credentials are required
|
||||||
|
|
||||||
|
// Handle preflight OPTIONS requests
|
||||||
|
if r.Method == http.MethodOptions {
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with the next handler
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) HelloWorldHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
resp := map[string]string{"message": "Hello World"}
|
||||||
|
jsonResp, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to marshal response", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if _, err := w.Write(jsonResp); err != nil {
|
||||||
|
log.Printf("Failed to write response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
31
internal/server/routes_test.go
Normal file
31
internal/server/routes_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHandler(t *testing.T) {
|
||||||
|
s := &Server{}
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(s.HelloWorldHandler))
|
||||||
|
defer server.Close()
|
||||||
|
resp, err := http.Get(server.URL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error making request to server. Err: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
// Assertions
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("expected status OK; got %v", resp.Status)
|
||||||
|
}
|
||||||
|
expected := "{\"message\":\"Hello World\"}"
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error reading response body. Err: %v", err)
|
||||||
|
}
|
||||||
|
if expected != string(body) {
|
||||||
|
t.Errorf("expected response body to be %v; got %v", expected, string(body))
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -8,6 +8,8 @@ import (
|
|||||||
// "strconv"
|
// "strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
//
|
//
|
||||||
// type Server struct {
|
// type Server struct {
|
Loading…
x
Reference in New Issue
Block a user