rewrite proxy part
parent
15d3e5d050
commit
4debfbd3b8
@ -1,145 +1,33 @@
|
||||
# vim: set ft=yaml:
|
||||
|
||||
# when provide certficate file, server will listen https and enable http2
|
||||
|
||||
|
||||
# http config
|
||||
-
|
||||
# listen address
|
||||
host: 0.0.0.0
|
||||
|
||||
# listen port
|
||||
# when provide certficate file, server will listen https and enable http2
|
||||
listen:
|
||||
-
|
||||
addr: 0.0.0.0
|
||||
port: 9001
|
||||
certificates:
|
||||
-
|
||||
addr: 0.0.0.0
|
||||
port: 9002
|
||||
certificates:
|
||||
-
|
||||
certfile: /etc/letsencrypt/live/ratafee.nl/fullchain.pem
|
||||
keyfile: /etc/letsencrypt/live/ratafee.nl/privkey.pem
|
||||
|
||||
# default document root
|
||||
# virtual host support
|
||||
vhost:
|
||||
-
|
||||
hostname: www.ratafee.nl
|
||||
docroot: /srv/www
|
||||
|
||||
enableproxy: true
|
||||
enableauth: true
|
||||
passwdfile: ./passwdfile
|
||||
realm: example.com
|
||||
|
||||
# default host's url rule
|
||||
# urlrules:
|
||||
# -
|
||||
# urlprefix: /a
|
||||
# type: alias
|
||||
# target:
|
||||
# type: dir
|
||||
# path: /home/user1/a
|
||||
# -
|
||||
# urlprefix: /b/a.txt
|
||||
# type: alias
|
||||
# target:
|
||||
# type: file
|
||||
# path: /home/user1/a/b/a.txt
|
||||
|
||||
# virtual host config
|
||||
# vhost:
|
||||
# - &example1_www
|
||||
# hostname: www.example1.com
|
||||
# docroot: /var/www/html/
|
||||
# # cert:
|
||||
# # key:
|
||||
#
|
||||
# # url rule for www.example.com
|
||||
# urlrules:
|
||||
# -
|
||||
# # url start with /APIv1/ forward to uwsg socket
|
||||
# urlprefix: /APIv1/
|
||||
# type: uwsgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /run/uwsgi/APIv1.sock
|
||||
# -
|
||||
# # run php script on /phpmyadmin/ subdirectory
|
||||
# urlprefix: /phpmyadmin/
|
||||
# type: fastcgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /var/run/php-fpm/www.sock
|
||||
# -
|
||||
# # pass php to fastcgi socket
|
||||
# urlprefix: \.php$|\.php/.*
|
||||
# isregex: true
|
||||
# type: fastcgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /var/run/php-fpm/www.sock
|
||||
# -
|
||||
# # run php script on other location
|
||||
# urlprefix: /a/
|
||||
# docroot: /home/user/php
|
||||
# type: fastcgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /var/run/php-fpm/www.sock
|
||||
# -
|
||||
# # url start with /proxy/ reverse proxy for http://10.10.1.1/
|
||||
# # this act as reverse proxy
|
||||
# urlprefix: /proxy/
|
||||
# type: reverse
|
||||
# target:
|
||||
# type: http
|
||||
# host: 10.10.1.1
|
||||
# port: 8080
|
||||
# path: /
|
||||
# - &example1
|
||||
# <<: *example1_www
|
||||
# hostname: example1.com
|
||||
#
|
||||
# - &example_www
|
||||
# hostname: www.example.com
|
||||
# docroot: /var/www/example
|
||||
# urlrules:
|
||||
# -
|
||||
# urlprefix: /APIv2
|
||||
# type: uwsgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /run/uwsgi/APIv2.sock
|
||||
# - &example
|
||||
# <<: *example_www
|
||||
# hostname: example.com
|
||||
#
|
||||
# - &example_bbs
|
||||
# hostname: bbs.example.com
|
||||
# docroot: /var/www/example_bbs/
|
||||
# urlrules:
|
||||
# -
|
||||
# #urlprefix: \.php$|\.php\/.*
|
||||
# #isregex: true
|
||||
#
|
||||
# urlprefix: /
|
||||
# type: fastcgi
|
||||
# target:
|
||||
# type: unix
|
||||
# path: /var/run/php-fpm/www.sock
|
||||
#
|
||||
# https config
|
||||
#-
|
||||
# host: 0.0.0.0
|
||||
# port: 9002
|
||||
# docroot: /srv/www
|
||||
# enableproxy: false
|
||||
# vhost:
|
||||
# -
|
||||
# <<: *example1
|
||||
# cert: /home/user1/cert/example1.com.crt
|
||||
# key: /home/user1/cert/example1.com.key
|
||||
# -
|
||||
# <<: *example1_www
|
||||
# cert: /home/user1/cert/example1.com.crt
|
||||
# key: /home/user1/cert/example1.com.key
|
||||
# -
|
||||
# <<: *example_www
|
||||
# cert: /etc/letsencrypt/live/example.com/fullchain.pem
|
||||
# key: /etc/letsencrypt/live/example.com/privkey.pem
|
||||
# -
|
||||
# <<: *example
|
||||
# cert: /etc/letsencrypt/live/example.com/fullchain.pem
|
||||
# key: /etc/letsencrypt/live/example.com/privkey.pem
|
||||
# -
|
||||
# <<: *example_bbs
|
||||
# cert: /etc/letsencrypt/live/bbs.example.com/fullchain.pem
|
||||
# key: /etc/letsencrypt/live/bbs.example.com/privkey.pem
|
||||
proxypass: http://nginx:80/
|
||||
proxy:
|
||||
http1-proxy: false
|
||||
http2-proxy: true
|
||||
# trust the follow domains as local virtual host
|
||||
# when http2 proxy enabled
|
||||
localdomains:
|
||||
- localhost
|
||||
- localdomain
|
||||
- 127.0.0.1
|
||||
- ratafee.nl
|
||||
- 98.142.138.194
|
||||
|
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
|
||||
proxyproto "github.com/pires/go-proxyproto"
|
||||
)
|
||||
|
||||
type listener struct {
|
||||
net.Listener
|
||||
}
|
||||
|
||||
type conn struct {
|
||||
net.Conn
|
||||
headerDone bool
|
||||
r *bufio.Reader
|
||||
proxy *proxyproto.Header
|
||||
}
|
||||
|
||||
func (l *listener) Accept() (net.Conn, error) {
|
||||
c, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &conn{Conn: c}, err
|
||||
}
|
||||
|
||||
func (c *conn) Read(buf []byte) (int, error) {
|
||||
var err error
|
||||
if !c.headerDone {
|
||||
c.r = bufio.NewReader(c.Conn)
|
||||
c.proxy, err = proxyproto.Read(c.r)
|
||||
if err != nil && err != proxyproto.ErrNoProxyProtocol {
|
||||
return 0, err
|
||||
}
|
||||
c.headerDone = true
|
||||
return c.r.Read(buf)
|
||||
}
|
||||
return c.r.Read(buf)
|
||||
}
|
||||
|
||||
func (c *conn) RemoteAddr() net.Addr {
|
||||
if c.proxy == nil {
|
||||
return c.Conn.RemoteAddr()
|
||||
}
|
||||
return &net.TCPAddr{
|
||||
IP: c.proxy.SourceAddress,
|
||||
Port: int(c.proxy.SourcePort)}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type digestPwFile struct {
|
||||
path string
|
||||
entry []pwEntry
|
||||
mtime time.Time
|
||||
mu *sync.Mutex
|
||||
}
|
||||
|
||||
type pwEntry struct {
|
||||
user string
|
||||
realm string
|
||||
hashPw string
|
||||
}
|
||||
|
||||
func newDigestSecret(f string) (*digestPwFile, error) {
|
||||
a := &digestPwFile{path: f, mu: new(sync.Mutex)}
|
||||
if err := a.loadFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go a.tryReload()
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (df *digestPwFile) tryReload() {
|
||||
for {
|
||||
time.Sleep(10 * time.Second)
|
||||
fi, _ := os.Stat(df.path)
|
||||
t1 := fi.ModTime()
|
||||
if t1 != df.mtime {
|
||||
df.loadFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (df *digestPwFile) loadFile() error {
|
||||
df.mu.Lock()
|
||||
defer df.mu.Unlock()
|
||||
|
||||
fp, err := os.Open(df.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer fp.Close()
|
||||
|
||||
entry := []pwEntry{}
|
||||
|
||||
r := bufio.NewReader(fp)
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
line1 := strings.Trim(line, " \r\n")
|
||||
if line1 == "" || line1[0] == '#' {
|
||||
continue
|
||||
}
|
||||
fields := strings.SplitN(line1, ":", 3)
|
||||
entry = append(entry, pwEntry{fields[0], fields[1], fields[2]})
|
||||
}
|
||||
|
||||
df.entry = entry
|
||||
fi, _ := os.Stat(df.path)
|
||||
df.mtime = fi.ModTime()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (df *digestPwFile) getPw(user, realm string) string {
|
||||
df.mu.Lock()
|
||||
defer df.mu.Unlock()
|
||||
|
||||
for i := range df.entry {
|
||||
if df.entry[i].user == user && df.entry[i].realm == realm {
|
||||
return df.entry[i].hashPw
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# format
|
||||
# user:realm:hashed_passwd
|
||||
#
|
||||
# hashed_passwd = MD5(user:realm:plain_passwd)
|
||||
|
||||
#
|
||||
# user "test", realm "example.com", password "test"
|
||||
# MD5("test:example:test") = 3441b753b98a6dc702183c989e35970f
|
||||
# the entry is
|
||||
test:example.com:3441b753b98a6dc702183c989e35970f
|
@ -1,262 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
auth "github.com/fangdingjun/go-http-auth"
|
||||
"github.com/fangdingjun/gofast"
|
||||
loghandler "github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"sync"
|
||||
//"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type logwriter struct {
|
||||
w io.Writer
|
||||
l *sync.Mutex
|
||||
}
|
||||
|
||||
func (lw *logwriter) Write(buf []byte) (int, error) {
|
||||
lw.l.Lock()
|
||||
defer lw.l.Unlock()
|
||||
return lw.w.Write(buf)
|
||||
}
|
||||
|
||||
func initRouters(cfg conf) {
|
||||
|
||||
logout := os.Stdout
|
||||
|
||||
if logfile != "" {
|
||||
fp, err := os.OpenFile(logfile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
} else {
|
||||
logout = fp
|
||||
}
|
||||
}
|
||||
|
||||
w := &logwriter{logout, new(sync.Mutex)}
|
||||
|
||||
for _, l := range cfg {
|
||||
router := mux.NewRouter()
|
||||
domains := []string{}
|
||||
certs := []tls.Certificate{}
|
||||
|
||||
// initial virtual host
|
||||
for _, h := range l.Vhost {
|
||||
h2 := h.Hostname
|
||||
if h1, _, err := net.SplitHostPort(h.Hostname); err == nil {
|
||||
h2 = h1
|
||||
}
|
||||
domains = append(domains, h2)
|
||||
if h.Cert != "" && h.Key != "" {
|
||||
if cert, err := tls.LoadX509KeyPair(h.Cert, h.Key); err == nil {
|
||||
certs = append(certs, cert)
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
r := router.Host(h2).Subrouter()
|
||||
for _, rule := range h.URLRules {
|
||||
switch rule.Type {
|
||||
case "alias":
|
||||
registerAliasHandler(rule, r)
|
||||
case "uwsgi":
|
||||
registerUwsgiHandler(rule, r)
|
||||
case "fastcgi":
|
||||
registerFastCGIHandler(rule, h.Docroot, r)
|
||||
case "reverse":
|
||||
registerHTTPHandler(rule, r)
|
||||
default:
|
||||
fmt.Printf("invalid type: %s\n", rule.Type)
|
||||
}
|
||||
}
|
||||
r.PathPrefix("/").Handler(http.FileServer(http.Dir(h.Docroot)))
|
||||
}
|
||||
|
||||
// default host config
|
||||
for _, rule := range l.URLRules {
|
||||
switch rule.Type {
|
||||
case "alias":
|
||||
registerAliasHandler(rule, router)
|
||||
case "uwsgi":
|
||||
registerUwsgiHandler(rule, router)
|
||||
case "fastcgi":
|
||||
docroot := l.Docroot
|
||||
if rule.Docroot != "" {
|
||||
docroot = rule.Docroot
|
||||
}
|
||||
registerFastCGIHandler(rule, docroot, router)
|
||||
case "reverse":
|
||||
registerHTTPHandler(rule, router)
|
||||
default:
|
||||
fmt.Printf("invalid type: %s\n", rule.Type)
|
||||
}
|
||||
}
|
||||
|
||||
router.PathPrefix("/").Handler(http.FileServer(http.Dir(l.Docroot)))
|
||||
|
||||
go func(l server) {
|
||||
addr := fmt.Sprintf("%s:%d", l.Host, l.Port)
|
||||
hdlr := &handler{
|
||||
handler: router,
|
||||
enableProxy: l.EnableProxy,
|
||||
enableAuth: l.EnableAuth,
|
||||
localDomains: domains,
|
||||
}
|
||||
|
||||
if l.EnableAuth {
|
||||
if l.PasswdFile == "" {
|
||||
log.Fatal("passwdfile required")
|
||||
}
|
||||
du, err := newDigestSecret(l.PasswdFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
digestAuth := auth.NewDigestAuthenticator(l.Realm, du.getPw)
|
||||
digestAuth.Headers = auth.ProxyHeaders
|
||||
hdlr.authMethod = digestAuth
|
||||
}
|
||||
|
||||
if len(certs) > 0 {
|
||||
tlsconfig := &tls.Config{
|
||||
Certificates: certs,
|
||||
}
|
||||
|
||||
tlsconfig.BuildNameToCertificate()
|
||||
|
||||
srv := http.Server{
|
||||
Addr: addr,
|
||||
TLSConfig: tlsconfig,
|
||||
Handler: loghandler.CombinedLoggingHandler(w, hdlr),
|
||||
}
|
||||
log.Printf("listen https on %s", addr)
|
||||
if err := srv.ListenAndServeTLS("", ""); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Printf("listen http on %s", addr)
|
||||
if err := http.ListenAndServe(
|
||||
addr,
|
||||
loghandler.CombinedLoggingHandler(w, hdlr),
|
||||
); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}(l)
|
||||
}
|
||||
}
|
||||
|
||||
func registerAliasHandler(r rule, router *mux.Router) {
|
||||
switch r.Target.Type {
|
||||
case "file":
|
||||
registerFileHandler(r, router)
|
||||
case "dir":
|
||||
registerDirHandler(r, router)
|
||||
default:
|
||||
fmt.Printf("invalid type: %s, only file, dir allowed\n", r.Target.Type)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
func registerFileHandler(r rule, router *mux.Router) {
|
||||
router.HandleFunc(r.URLPrefix,
|
||||
func(w http.ResponseWriter, req *http.Request) {
|
||||
http.ServeFile(w, req, r.Target.Path)
|
||||
})
|
||||
}
|
||||
|
||||
func registerDirHandler(r rule, router *mux.Router) {
|
||||
p := strings.TrimRight(r.URLPrefix, "/")
|
||||
router.PathPrefix(r.URLPrefix).Handler(
|
||||
http.StripPrefix(p,
|
||||
http.FileServer(http.Dir(r.Target.Path))))
|
||||
}
|
||||
|
||||
func registerUwsgiHandler(r rule, router *mux.Router) {
|
||||
var p string
|
||||
switch r.Target.Type {
|
||||
case "unix":
|
||||
p = r.Target.Path
|
||||
case "tcp":
|
||||
p = fmt.Sprintf("%s:%d", r.Target.Host, r.Target.Port)
|
||||
default:
|
||||
fmt.Printf("invalid scheme: %s, only support unix, tcp", r.Target.Type)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
if r.IsRegex {
|
||||
m1 := myURLMatch{regexp.MustCompile(r.URLPrefix)}
|
||||
u := NewUwsgi(r.Target.Type, p, "")
|
||||
router.MatcherFunc(m1.match).Handler(u)
|
||||
} else {
|
||||
u := NewUwsgi(r.Target.Type, p, r.URLPrefix)
|
||||
router.PathPrefix(r.URLPrefix).Handler(u)
|
||||
}
|
||||
}
|
||||
|
||||
func registerFastCGIHandler(r rule, docroot string, router *mux.Router) {
|
||||
var n, p string
|
||||
switch r.Target.Type {
|
||||
case "unix":
|
||||
n = "unix"
|
||||
p = r.Target.Path
|
||||
case "tcp":
|
||||
n = "tcp"
|
||||
p = fmt.Sprintf("%s:%d", r.Target.Host, r.Target.Port)
|
||||
default:
|
||||
fmt.Printf("invalid scheme: %s, only support unix, tcp", r.Target.Type)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
u := gofast.NewHandler(gofast.NewPHPFS(docroot), n, p)
|
||||
if r.IsRegex {
|
||||
m1 := myURLMatch{regexp.MustCompile(r.URLPrefix)}
|
||||
router.MatcherFunc(m1.match).Handler(u)
|
||||
} else {
|
||||
router.PathPrefix(r.URLPrefix).Handler(u)
|
||||
}
|
||||
}
|
||||
|
||||
func registerHTTPHandler(r rule, router *mux.Router) {
|
||||
var u http.Handler
|
||||
var addr string
|
||||
switch r.Target.Type {
|
||||
case "unix":
|
||||
addr = r.Target.Path
|
||||
u = newProxy(addr, r.URLPrefix)
|
||||
case "http":
|
||||
addr = fmt.Sprintf("%s:%d", r.Target.Host, r.Target.Port)
|
||||
u1 := &url.URL{
|
||||
Scheme: "http",
|
||||
Host: addr,
|
||||
Path: r.Target.Path,
|
||||
}
|
||||
u = httputil.NewSingleHostReverseProxy(u1)
|
||||
default:
|
||||
fmt.Printf("invalid scheme: %s, only support unix, http", r.Target.Type)
|
||||
os.Exit(-1)
|
||||
}
|
||||
p := strings.TrimRight(r.URLPrefix, "/")
|
||||
router.PathPrefix(r.URLPrefix).Handler(
|
||||
http.StripPrefix(p, u))
|
||||
}
|
||||
|
||||
type myURLMatch struct {
|
||||
re *regexp.Regexp
|
||||
}
|
||||
|
||||
func (m myURLMatch) match(r *http.Request, route *mux.RouteMatch) bool {
|
||||
ret := m.re.MatchString(r.URL.Path)
|
||||
return ret
|
||||
}
|
@ -1,23 +1,142 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
//"fmt"
|
||||
"log"
|
||||
//"net/http"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/fangdingjun/go-log"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
var logfile string
|
||||
func initServer(c *conf) error {
|
||||
|
||||
mux := mux.NewRouter()
|
||||
|
||||
for _, vh := range c.Vhosts {
|
||||
subroute := mux.Host(vh.Hostname)
|
||||
subroute.PathPrefix("/").Handler(http.FileServer(http.Dir(vh.Docroot)))
|
||||
}
|
||||
|
||||
if len(c.Vhosts) > 0 {
|
||||
mux.PathPrefix("/").Handler(http.FileServer(http.Dir(c.Vhosts[0].Docroot)))
|
||||
} else {
|
||||
mux.PathPrefix("/").Handler(http.FileServer(http.Dir("/var/www/html")))
|
||||
}
|
||||
|
||||
for _, _l := range c.Listens {
|
||||
var err error
|
||||
certs := []tls.Certificate{}
|
||||
tlsconfig := &tls.Config{}
|
||||
for _, cert := range _l.Certificates {
|
||||
if cert.CertFile != "" && cert.KeyFile != "" {
|
||||
_cert, err := tls.LoadX509KeyPair(cert.CertFile, cert.KeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certs = append(certs, _cert)
|
||||
}
|
||||
}
|
||||
|
||||
var h http.Handler
|
||||
|
||||
h = &handler{handler: mux, cfg: c}
|
||||
h = handlers.CombinedLoggingHandler(&logout{}, h)
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", _l.Addr, _l.Port),
|
||||
Handler: h,
|
||||
}
|
||||
|
||||
var l net.Listener
|
||||
|
||||
l, err = net.Listen("tcp", srv.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l = &listener{Listener: l}
|
||||
|
||||
if len(certs) > 0 {
|
||||
tlsconfig.Certificates = certs
|
||||
tlsconfig.BuildNameToCertificate()
|
||||
srv.TLSConfig = tlsconfig
|
||||
http2.ConfigureServer(srv, nil)
|
||||
l = tls.NewListener(l, srv.TLSConfig)
|
||||
}
|
||||
|
||||
go func(l net.Listener) {
|
||||
defer l.Close()
|
||||
err = srv.Serve(l)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
}(l)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type logout struct{}
|
||||
|
||||
func (l *logout) Write(buf []byte) (int, error) {
|
||||
log.Debugf("%s", buf)
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var configfile string
|
||||
var loglevel string
|
||||
var logfile string
|
||||
var logFileCount int
|
||||
var logFileSize int64
|
||||
flag.StringVar(&logfile, "log_file", "", "log file, default stdout")
|
||||
flag.IntVar(&logFileCount, "log_count", 10, "max count of log to keep")
|
||||
flag.Int64Var(&logFileSize, "log_size", 10, "max log file size MB")
|
||||
flag.StringVar(&loglevel, "log_level", "INFO",
|
||||
"log level, values:\nOFF, FATAL, PANIC, ERROR, WARN, INFO, DEBUG")
|
||||
flag.StringVar(&configfile, "c", "config.yaml", "config file")
|
||||
flag.StringVar(&logfile, "log", "", "log file")
|
||||
flag.Parse()
|
||||
|
||||
if logfile != "" {
|
||||
log.Default.Out = &log.FixedSizeFileWriter{
|
||||
MaxCount: logFileCount,
|
||||
Name: logfile,
|
||||
MaxSize: logFileSize * 1024 * 1024,
|
||||
}
|
||||
}
|
||||
|
||||
if loglevel != "" {
|
||||
lv, err := log.ParseLevel(loglevel)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Default.Level = lv
|
||||
}
|
||||
|
||||
c, err := loadConfig(configfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
initRouters(c)
|
||||
select {}
|
||||
|
||||
log.Infof("%+v", c)
|
||||
err = initServer(c)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
ch := make(chan os.Signal, 2)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
select {
|
||||
case sig := <-ch:
|
||||
log.Errorf("received signal %s, exit", sig)
|
||||
}
|
||||
log.Debug("exited.")
|
||||
}
|
||||
|
@ -1,107 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
uwsgi "github.com/fangdingjun/go-uwsgi"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Uwsgi is a struct for uwsgi
|
||||
type Uwsgi struct {
|
||||
Passenger *uwsgi.Passenger
|
||||
URLPrefix string
|
||||
}
|
||||
|
||||
// NewUwsgi create a new Uwsgi
|
||||
func NewUwsgi(network, addr, urlPrefix string) *Uwsgi {
|
||||
u := strings.TrimRight(urlPrefix, "/")
|
||||
return &Uwsgi{
|
||||
Passenger: &uwsgi.Passenger{
|
||||
Net: network,
|
||||
Addr: addr,
|
||||
},
|
||||
URLPrefix: u,
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP implements http.Handler interface
|
||||
func (u *Uwsgi) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
u.UwsgiPass(w, r)
|
||||
}
|
||||
|
||||
// UwsgiPass pass the request to uwsgi interface
|
||||
func (u *Uwsgi) UwsgiPass(w http.ResponseWriter, r *http.Request) {
|
||||
params := buildParams(r, u.URLPrefix)
|
||||
u.Passenger.UwsgiPass(w, r, params)
|
||||
}
|
||||
|
||||
func buildParams(req *http.Request, urlPrefix string) map[string][]string {
|
||||
var err error
|
||||
|
||||
header := make(map[string][]string)
|
||||
|
||||
if urlPrefix != "" {
|
||||
header["SCRIPT_NAME"] = []string{urlPrefix}
|
||||
p := strings.Replace(req.URL.Path, urlPrefix, "", 1)
|
||||
header["PATH_INFO"] = []string{p}
|
||||
} else {
|
||||
header["PATH_INFO"] = []string{req.URL.Path}
|
||||
}
|
||||
|
||||
//fmt.Printf("url: %s, scheme: %s\n", req.URL.String(), req.URL.Scheme)
|
||||
|
||||
scheme := "http"
|
||||
if req.TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
header["REQUEST_SCHEME"] = []string{scheme}
|
||||
|
||||
header["HTTPS"] = []string{"off"}
|
||||
|
||||
/* https */
|
||||
if scheme == "https" {
|
||||
header["HTTPS"] = []string{"on"}
|
||||
}
|
||||
|
||||
/* speicial port */
|
||||
host, port, err := net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
host = req.Host
|
||||
if scheme == "http" {
|
||||
port = "80"
|
||||
} else {
|
||||
port = "443"
|
||||
}
|
||||
}
|
||||
header["SERVER_NAME"] = []string{host}
|
||||
header["SERVER_PORT"] = []string{port}
|
||||
|
||||
host, port, err = net.SplitHostPort(req.RemoteAddr)
|
||||
if err != nil {
|
||||
host = req.RemoteAddr
|
||||
port = "80"
|
||||
}
|
||||
header["REMOTE_PORT"] = []string{port}
|
||||
header["REMOTE_ADDR"] = []string{host}
|
||||
|
||||
header["REQUEST_METHOD"] = []string{req.Method}
|
||||
header["REQUEST_URI"] = []string{req.RequestURI}
|
||||
header["CONTENT_LENGTH"] = []string{strconv.Itoa(int(req.ContentLength))}
|
||||
header["SERVER_PROTOCOL"] = []string{req.Proto}
|
||||
header["QUERY_STRING"] = []string{req.URL.RawQuery}
|
||||
|
||||
if ctype := req.Header.Get("Content-Type"); ctype != "" {
|
||||
header["CONTENT_TYPE"] = []string{ctype}
|
||||
}
|
||||
|
||||
for k, v := range req.Header {
|
||||
k = "HTTP_" + strings.ToUpper(strings.Replace(k, "-", "_", -1))
|
||||
if _, ok := header[k]; ok == false {
|
||||
header[k] = v
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
Loading…
Reference in New Issue