Skip to content
Open
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
File renamed without changes.
11 changes: 11 additions & 0 deletions examples/html/hello-world2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World2</title>
</head>
<body>
<h1>Hello, World2!</h1>
</body>
</html>
9 changes: 8 additions & 1 deletion examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import (

func main() {
// Create a new server instance with the specified address
srv := statix.NewServer(":8080")
srv, err := statix.NewServer(
statix.WithPort(8080),
statix.WithStaticDir("./html"),
)

if err != nil {
panic(err) // Handle error appropriately
}

// Start the server
if err := srv.Start(); err != nil {
Expand Down
78 changes: 73 additions & 5 deletions pkg/statix/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
package server

import (
"errors"
"fmt"
"log"
"net/http"
"path/filepath"
Expand All @@ -13,16 +15,82 @@ type server struct {
server http.Server
}

type options struct {
host *string
port *int
staticDir *string
}

type Option func(*options) error

// WithHost sets the host for the server.
func WithHost(host string) Option {
return func(opts *options) error {
if host == "" {
return errors.New("host cannot be empty") // Empty host
}
opts.host = &host
return nil
}
}

// WithPort sets the port for the server.
func WithPort(port int) Option {
return func(opts *options) error {
if port < 1 || port > 65535 {
return errors.New("invalid port number") // Invalid port number
}
opts.port = &port
return nil
}
}

// WithStaticDir sets the directory to serve static files from.
func WithStaticDir(dir string) Option {
return func(opts *options) error {
if dir == "" {
return errors.New("static directory cannot be empty") // Empty directory path
}
opts.staticDir = &dir
return nil
}
}

// NewServer creates a new server instance with the specified address.
func NewServer(addr string) *server {
handler := http.DefaultServeMux
func NewServer(opts ...Option) (*server, error) {
// Apply options
var o options
for _, opt := range opts {
if err := opt(&o); err != nil {
return nil, err // Return error if option fails
}
}

handler.HandleFunc("/", staticFileHandler(defaultStaticDir))
// Apply default options if not set
applyDefaultOptions(&o)

handler := http.DefaultServeMux
handler.HandleFunc("/", staticFileHandler(*o.staticDir))

return &server{server: http.Server{
Addr: addr,
Addr: fmt.Sprintf("%s:%d", *o.host, *o.port),
Handler: handler,
}}
}}, nil
}

func applyDefaultOptions(opts *options) {
if opts.host == nil {
defaultHost := "localhost"
opts.host = &defaultHost // Default host if not set
}
if opts.port == nil {
defaultPort := 8080
opts.port = &defaultPort // Default port if not set
}
if opts.staticDir == nil {
defaultStaticDir := defaultStaticDir
opts.staticDir = &defaultStaticDir // Default static directory
}
}

func staticFileHandler(dir string) http.HandlerFunc {
Expand Down
73 changes: 71 additions & 2 deletions pkg/statix/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ import (

// TestNewServer tests the NewServer function.
func TestNewServer(t *testing.T) {
addr := ":8080"
srv := NewServer(addr)
addr := "localhost:8080"
srv, err := NewServer(
WithPort(8080),
WithStaticDir("./static"),
)

if err != nil {
t.Fatalf("expected no error, got %v", err)
}

if srv.server.Addr != addr {
t.Errorf("expected server Addr %s, got %s", addr, srv.server.Addr)
Expand Down Expand Up @@ -63,3 +70,65 @@ func TestStaticFileHandler(t *testing.T) {
t.Errorf("expected status code 404, got %d", rr.Code)
}
}

func TestWithHost(t *testing.T) {
opts := &options{}
host := "localhost"

err := WithHost(host)(opts)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if opts.host == nil || *opts.host != host {
t.Errorf("expected host %s, got %v", host, opts.host)
}

// Test empty host
err = WithHost("")(opts)
if err == nil || err.Error() != "host cannot be empty" {
t.Errorf("expected error for empty host, got %v", err)
}
}

func TestWithPort(t *testing.T) {
opts := &options{}
port := 8080

err := WithPort(port)(opts)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if opts.port == nil || *opts.port != port {
t.Errorf("expected port %d, got %v", port, opts.port)
}

// Test invalid ports
err = WithPort(0)(opts)
if err == nil || err.Error() != "invalid port number" {
t.Errorf("expected error for invalid port, got %v", err)
}

err = WithPort(70000)(opts)
if err == nil || err.Error() != "invalid port number" {
t.Errorf("expected error for invalid port, got %v", err)
}
}

func TestWithStaticDir(t *testing.T) {
opts := &options{}
dir := "/static"

err := WithStaticDir(dir)(opts)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if opts.staticDir == nil || *opts.staticDir != dir {
t.Errorf("expected static directory %s, got %v", dir, opts.staticDir)
}

// Test empty directory
err = WithStaticDir("")(opts)
if err == nil || err.Error() != "static directory cannot be empty" {
t.Errorf("expected error for empty directory, got %v", err)
}
}
Loading