Skip to content

Commit

Permalink
Merge pull request #2 from pollystack/add-proxy-2
Browse files Browse the repository at this point in the history
Add proxy
  • Loading branch information
allnash authored Sep 13, 2024
2 parents 2399b4d + f0e9d21 commit bdf1506
Show file tree
Hide file tree
Showing 6 changed files with 325 additions and 185 deletions.
90 changes: 50 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
# FAST - HTTP Static Site Server
# FAST - HTTP Static Site Server and Reverse Proxy

FAST (File Access Speedy Transfer) is a lightweight, high-performance web server designed specifically for serving static content. It prioritizes speed and efficiency, making it ideal for quickly delivering HTML, CSS, JavaScript, images, and other static assets to web browsers.
FAST (File Access Speedy Transfer) is a lightweight,
high-performance web server designed for serving static content and acting as a reverse proxy.
It prioritizes speed and efficiency, making it ideal for quickly delivering static assets and proxying requests to
backend services.

## Features

- Multi-domain support
- SSL/TLS encryption
- HTTP to HTTPS redirection
- Domain-specific public directories
- Reverse proxy support
- Easy configuration via YAML
- Systemd service integration
- Minimal configuration required, allowing for quick setup and deployment
- Optimized for serving static files, without the overhead of dynamic content processing
- Optimized for serving static files and proxying requests
- High concurrency, able to handle multiple simultaneous connections efficiently
- Low memory footprint, making it suitable for various hosting environments
- Built-in caching mechanisms to further enhance performance
Expand All @@ -27,7 +31,7 @@ FAST (File Access Speedy Transfer) is a lightweight, high-performance web server
## Installation

1. Clone the repository:

```bash
git clone https://github.com/pollystack/fast.git
cd fast-server
Expand All @@ -39,8 +43,8 @@ FAST (File Access Speedy Transfer) is a lightweight, high-performance web server
```bash
sudo make install
```
This will:

This will:
- Build the server for Linux
- Copy the binary to `/usr/local/bin/fast_server`
- Copy the configuration to `/etc/fast/config.yaml`
Expand All @@ -58,34 +62,40 @@ The server is configured via the `config.yaml` file. Here's an example configura
```yaml
server:
port: 443
http_port: 80 # for HTTP to HTTPS redirect
port: 443
http_port: 80 # for HTTP to HTTPS redirect
domains:
- name: example.com
public_dir: /var/www/fast/example.com
ssl:
cert_file: /etc/fast/ssl/example.com/fullchain.pem
key_file: /etc/fast/ssl/example.com/privkey.pem
- name: another-domain.com
public_dir: /var/www/fast/another-domain.com
ssl:
cert_file: /etc/fast/ssl/another-domain.com/fullchain.pem
key_file: /etc/fast/ssl/another-domain.com/privkey.pem
- name: example.com
type: static
public_dir: /var/www/fast/example.com
ssl:
cert_file: /etc/fast/ssl/example.com/fullchain.pem
key_file: /etc/fast/ssl/example.com/privkey.pem
- name: api.example.com
type: proxy
proxy:
host: 192.168.1.100
port: 8000
ssl:
cert_file: /etc/fast/ssl/api.example.com/fullchain.pem
key_file: /etc/fast/ssl/api.example.com/privkey.pem
global_ssl:
cert_file: /etc/fast/ssl/global/fullchain.pem
key_file: /etc/fast/ssl/global/privkey.pem
cert_file: /etc/fast/ssl/global/fullchain.pem
key_file: /etc/fast/ssl/global/privkey.pem
log:
file: /var/log/fast/server.log
level: info # Options: debug, info, warn, error
file: /var/log/fast/server.log
level: info # Options: debug, info, warn, error
settings:
read_timeout: 5s
write_timeout: 10s
graceful_shutdown_timeout: 30s
read_timeout: 5s
write_timeout: 10s
graceful_shutdown_timeout: 30s
is_development: false
```
Expand Down Expand Up @@ -164,20 +174,20 @@ go install github.com/google/gops@latest
```azure
fast-server/
├── main.go
├── config/
│ └── config.go
├── server/
│ └── server.go
├── handlers/
│ └── handlers.go
├── public/
│ └── ... (static files)
├── Makefile
├── config.yaml.exmple
└── README.md
└── Dockerfile
└── LICENSE
├── main.go
├── config/
│ └── config.go
├── server/
│ └── server.go
├── handlers/
│ └── handlers.go
├── public/
│ └── ... (static files)
├── Makefile
├── config.yaml.exmple
└── README.md
└── Dockerfile
└── LICENSE
```
### Building
Expand Down
153 changes: 79 additions & 74 deletions fast-server/config/config.go
Original file line number Diff line number Diff line change
@@ -1,98 +1,103 @@
package config

import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
)

var ProductionConfigPath = "/etc/fast/config.yaml"

type Domain struct {
Name string `yaml:"name"`
PublicDir string `yaml:"public_dir"`
SSL struct {
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
} `yaml:"ssl"`
Name string `yaml:"name"`
Type string `yaml:"type"`
PublicDir string `yaml:"public_dir"`
Proxy struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
} `yaml:"proxy"`
SSL struct {
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
} `yaml:"ssl"`
}

type Config struct {
Server struct {
Port int `yaml:"port"`
HTTPPort int `yaml:"http_port"`
} `yaml:"server"`
Domains []Domain `yaml:"domains"`
GlobalSSL struct {
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
} `yaml:"global_ssl"`
Log struct {
File string `yaml:"file"`
Level string `yaml:"level"`
} `yaml:"log"`
Settings struct {
ReadTimeout string `yaml:"read_timeout"`
WriteTimeout string `yaml:"write_timeout"`
GracefulShutdownTimeout string `yaml:"graceful_shutdown_timeout"`
} `yaml:"settings"`
IsDevelopment bool `yaml:"is_development"`
Server struct {
Port int `yaml:"port"`
HTTPPort int `yaml:"http_port"`
} `yaml:"server"`
Domains []Domain `yaml:"domains"`
GlobalSSL struct {
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
} `yaml:"global_ssl"`
Log struct {
File string `yaml:"file"`
Level string `yaml:"level"`
} `yaml:"log"`
Settings struct {
ReadTimeout string `yaml:"read_timeout"`
WriteTimeout string `yaml:"write_timeout"`
GracefulShutdownTimeout string `yaml:"graceful_shutdown_timeout"`
} `yaml:"settings"`
IsDevelopment bool `yaml:"is_development"`
}

func isLaunchedByDebugger() bool {
// Check if gops is available
_, err := exec.LookPath("gops")
if err != nil {
// If gops is not available, fall back to a simple check
return strings.Contains(os.Args[0], "debugger") || strings.Contains(os.Args[0], "___go_build_")
}
// Check if gops is available
_, err := exec.LookPath("gops")
if err != nil {
// If gops is not available, fall back to a simple check
return strings.Contains(os.Args[0], "debugger") || strings.Contains(os.Args[0], "___go_build_")
}

// Use gops to check the parent process
gopsOut, err := exec.Command("gops", strconv.Itoa(os.Getppid())).Output()
if err != nil {
log.Printf("Error running gops: %v", err)
return false
}
// Use gops to check the parent process
gopsOut, err := exec.Command("gops", strconv.Itoa(os.Getppid())).Output()
if err != nil {
log.Printf("Error running gops: %v", err)
return false
}

gopsOutStr := string(gopsOut)
gopsOutStr := string(gopsOut)

switch runtime.GOOS {
case "windows":
return strings.Contains(gopsOutStr, "\\dlv.exe")
case "darwin":
return strings.Contains(gopsOutStr, "/dlv") ||
strings.Contains(gopsOutStr, "/dlv-dap") ||
strings.Contains(gopsOutStr, "debugserver")
default: // linux and others
return strings.Contains(gopsOutStr, "/dlv")
}
switch runtime.GOOS {
case "windows":
return strings.Contains(gopsOutStr, "\\dlv.exe")
case "darwin":
return strings.Contains(gopsOutStr, "/dlv") ||
strings.Contains(gopsOutStr, "/dlv-dap") ||
strings.Contains(gopsOutStr, "debugserver")
default: // linux and others
return strings.Contains(gopsOutStr, "/dlv")
}
}

func LoadConfig() (*Config, error) {
var configPath string
if isLaunchedByDebugger() {
configPath = "fast-server/test/config.yaml" // Local path for development
log.Println("Debug mode detected. Using local config.yaml")
} else {
configPath = ProductionConfigPath // Default production path
}
var configPath string
if isLaunchedByDebugger() {
configPath = "test/config.yaml" // Local path for development
log.Println("Debug mode detected. Using local config.yaml")
} else {
configPath = ProductionConfigPath // Default production path
}

data, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %v", err)
}
data, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %v", err)
}

var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
return nil, fmt.Errorf("failed to parse config file: %v", err)
}
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
return nil, fmt.Errorf("failed to parse config file: %v", err)
}

return &config, nil
return &config, nil
}
Loading

0 comments on commit bdf1506

Please sign in to comment.