Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
dingjun | 350ec51345 | 5 years ago |
dingjun | c39fc8c107 | 5 years ago |
dingjun | c39cbf826a | 5 years ago |
dingjun | 4e6417da8b | 6 years ago |
dingjun | 341802505f | 6 years ago |
dingjun | ff7f97d9a2 | 6 years ago |
dingjun | 61fbd7ab0a | 6 years ago |
dingjun | 764434b372 | 6 years ago |
dingjun | 4cdd0c60f7 | 6 years ago |
dingjun | d0e5f8bb6a | 6 years ago |
dingjun | 5f176382ba | 6 years ago |
dingjun | 4ba30bdcfb | 6 years ago |
dingjun | 2973574537 | 6 years ago |
fangdingjun | 36da7093b2 | 6 years ago |
fangdingjun | 4734592a04 | 6 years ago |
fangdingjun | 4debfbd3b8 | 6 years ago |
@ -0,0 +1,53 @@
|
||||
local http = require "http"
|
||||
local json = require "json"
|
||||
local mysql = require "mysql"
|
||||
local redis = require "redis"
|
||||
|
||||
infolog(string.format("%s %s %s", request:GetIP(),request.Method,request.RequestURI))
|
||||
|
||||
-- response:Write(string.format("hello %s\n",request:GetIP()))
|
||||
if request.URL.Path == "/api/ip" then
|
||||
local resp = http.get("http://httpbin.org/ip")
|
||||
local d = json.decode(resp.body)
|
||||
print(d)
|
||||
infolog(string.format("ip %s",d.origin))
|
||||
local hdr = response:Header()
|
||||
hdr:Set("content-type","application/json")
|
||||
response:Write(resp.body)
|
||||
return
|
||||
end
|
||||
|
||||
if request.URL.Path == "/api/user" then
|
||||
local c = mysql.new()
|
||||
local ok, err = c:connect({host="127.0.0.1",user="root",password="112233",database="game"})
|
||||
if not ok then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
|
||||
local res, err = c:query("select * from `user` limit 3")
|
||||
if err ~= nil then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
for k,v in pairs(res) do
|
||||
print(k,v)
|
||||
for k1,v1 in pairs(v) do
|
||||
print(k1,v1)
|
||||
end
|
||||
end
|
||||
local hdr = response:Header()
|
||||
hdr:Set("content-type","application/json")
|
||||
response:Write(json.encode(res))
|
||||
c:close()
|
||||
return
|
||||
end
|
||||
|
||||
if request.URL.Path == "/api/user2" then
|
||||
local c = redis.new({host="127.0.0.1"})
|
||||
local keys = c:Do("keys", "wallet*"):Val()
|
||||
for k, v in keys() do
|
||||
response:Write(string.format("%s %s\n", k, v))
|
||||
end
|
||||
c:Close()
|
||||
end
|
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/fangdingjun/go-log"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
"github.com/yuin/gopher-lua/parse"
|
||||
)
|
||||
|
||||
// from https://github.com/yuin/gophoer-lua
|
||||
|
||||
// CompileLua reads the passed lua file from disk and compiles it.
|
||||
func CompileLua(filePath string) (*lua.FunctionProto, error) {
|
||||
file, err := os.Open(filePath)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader := bufio.NewReader(file)
|
||||
chunk, err := parse.Parse(reader, filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proto, err := lua.Compile(chunk, filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return proto, nil
|
||||
}
|
||||
|
||||
// DoCompiledFile takes a FunctionProto, as returned by CompileLua, and runs it in the LState. It is equivalent
|
||||
// to calling DoFile on the LState with the original source file.
|
||||
func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
|
||||
lfunc := L.NewFunctionFromProto(proto)
|
||||
L.Push(lfunc)
|
||||
return L.PCall(0, lua.MultRet, nil)
|
||||
}
|
||||
|
||||
type filecache struct {
|
||||
filepath string
|
||||
proto *lua.FunctionProto
|
||||
lastMod int64
|
||||
}
|
||||
|
||||
var cache = map[string]*filecache{}
|
||||
var mu = new(sync.Mutex)
|
||||
|
||||
func runFile(vm *lua.LState, filepath string) error {
|
||||
mu.Lock()
|
||||
c, ok := cache[filepath]
|
||||
if !ok {
|
||||
c = &filecache{
|
||||
filepath: filepath,
|
||||
lastMod: 0,
|
||||
}
|
||||
cache[filepath] = c
|
||||
}
|
||||
|
||||
fi, err := os.Stat(filepath)
|
||||
if err != nil {
|
||||
mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
t := fi.ModTime().Unix()
|
||||
if t > c.lastMod {
|
||||
log.Debugf("file %s changed, reload", filepath)
|
||||
proto, err := CompileLua(filepath)
|
||||
if err != nil {
|
||||
mu.Unlock()
|
||||
return err
|
||||
}
|
||||
c.proto = proto
|
||||
c.lastMod = t
|
||||
}
|
||||
mu.Unlock()
|
||||
// log.Println(c.proto)
|
||||
return DoCompiledFile(vm, c.proto)
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
# vim: set ft=yaml:
|
||||
|
||||
# when provide certficate file, server will listen https and enable http2
|
||||
listen:
|
||||
-
|
||||
addr: 0.0.0.0
|
||||
port: 9001
|
||||
certificates:
|
||||
|
||||
# virtual host support
|
||||
vhost:
|
||||
-
|
||||
hostname: www.ratafee.nl
|
||||
docroot: .
|
||||
# proxypass: http://nginx:80/
|
||||
url_rules:
|
||||
- prefix: /api/
|
||||
lua_file: api.lua
|
||||
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
|
@ -1,145 +1,36 @@
|
||||
# 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/
|
||||
url_rules:
|
||||
- prefix: /api/
|
||||
lua_file: api.lua
|
||||
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
|
||||
|
@ -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 ""
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
module github.com/fangdingjun/gserver
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20190104103309-101c19a37344
|
||||
github.com/fangdingjun/go-log v0.0.0-20190821073628-ae332053d6dc
|
||||
github.com/fangdingjun/gopher-redis v0.0.0-20190823083833-93d88f74dd35
|
||||
github.com/fangdingjun/protolistener v0.0.0-20190821093313-6d5d2138f296
|
||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/gorilla/mux v1.7.3
|
||||
github.com/junhsieh/goexamples v0.0.0-20190721045834-1c67ae74caa6 // indirect
|
||||
github.com/tengattack/gluasql v0.0.0-20181229041402-2e5ed630c4cf
|
||||
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
|
||||
layeh.com/gopher-json v0.0.0-20190114024228-97fed8db8427
|
||||
layeh.com/gopher-luar v1.0.7
|
||||
)
|
@ -0,0 +1,49 @@
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20190104103309-101c19a37344 h1:nTK6O2RY1nHC4jNEJd1nixVP7ygY3QE4CNxCX07dHKU=
|
||||
github.com/cjoudrey/gluahttp v0.0.0-20190104103309-101c19a37344/go.mod h1:X97UjDTXp+7bayQSFZk2hPvCTmTZIicUjZQRtkwgAKY=
|
||||
github.com/fangdingjun/go-log v0.0.0-20190821073628-ae332053d6dc h1:Tdk7VsmsFo3d0NqHTy3SRoRnkduOxwXgR65gQsq8kXY=
|
||||
github.com/fangdingjun/go-log v0.0.0-20190821073628-ae332053d6dc/go.mod h1:oi7jbIScCbha6TbVzmrJP6igIHt+jcvvEgSJ7Ww1GkI=
|
||||
github.com/fangdingjun/gopher-redis v0.0.0-20190823083833-93d88f74dd35 h1:ylhL3mOAVv+xPvF7ml4mPJkacGyc4hDAxBRl8/DGATk=
|
||||
github.com/fangdingjun/gopher-redis v0.0.0-20190823083833-93d88f74dd35/go.mod h1:mJh0kXIkwwPbU3KnTswNRDtHUtA+xlFJRHnbxuFg33Y=
|
||||
github.com/fangdingjun/protolistener v0.0.0-20190821093313-6d5d2138f296 h1:2c6agkdoPVSyvdJ0B+5DhOb1BQpso7a7zlBxXUnttmY=
|
||||
github.com/fangdingjun/protolistener v0.0.0-20190821093313-6d5d2138f296/go.mod h1:RoT81rjdN8gQ1w/z7NiFkxV6VzkT4NZ43XIt0lu8tcc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/junhsieh/goexamples v0.0.0-20190721045834-1c67ae74caa6 h1:oi85CfIzfVPMlTf6pteDMw0S3AjZ9b6Y0OaxfsLCU3M=
|
||||
github.com/junhsieh/goexamples v0.0.0-20190721045834-1c67ae74caa6/go.mod h1:JNqB8Da6SnlJvmZusESDfgqUkJXO6+/a1by1etsVJ2M=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.9.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.6.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc/go.mod h1:6/gX3+E/IYGa0wMORlSMla999awQFdbaeQCHjSMKIzY=
|
||||
github.com/tengattack/gluasql v0.0.0-20181229041402-2e5ed630c4cf h1:7zGSyMKHHwD0A8iJk0IlP8FhSIOZco4VyzemWYHP1Ck=
|
||||
github.com/tengattack/gluasql v0.0.0-20181229041402-2e5ed630c4cf/go.mod h1:m4UsFo0sc87XS8WozZBD8HJPC2NKI/nB7w4N58HwemQ=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
layeh.com/gopher-json v0.0.0-20190114024228-97fed8db8427 h1:RZkKxMR3jbQxdCEcglq3j7wY3PRJIopAwBlx1RE71X0=
|
||||
layeh.com/gopher-json v0.0.0-20190114024228-97fed8db8427/go.mod h1:ivKkcY8Zxw5ba0jldhZCYYQfGdb2K6u9tbYK1AwMIBc=
|
||||
layeh.com/gopher-luar v1.0.7 h1:53iv6CCkRs5wyofZ+qVXcyAYQOIG52s6pt4xkqZdq7k=
|
||||
layeh.com/gopher-luar v1.0.7/go.mod h1:TPnIVCZ2RJBndm7ohXyaqfhzjlZ+OA2SZR/YwL8tECk=
|
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/fangdingjun/go-log"
|
||||
)
|
||||
|
||||
func infoLog(msg string) {
|
||||
log.Println(msg)
|
||||
}
|
||||
|
||||
func errorLog(msg string) {
|
||||
log.Errorln(msg)
|
||||
}
|
||||
|
||||
func debugLog(msg string) {
|
||||
log.Debugln(msg)
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/fangdingjun/go-log"
|
||||
luar "layeh.com/gopher-luar"
|
||||
)
|
||||
|
||||
type luaHandler struct {
|
||||
scriptFile string
|
||||
}
|
||||
|
||||
func (l *luaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
vm := luaPool.Get()
|
||||
defer luaPool.Put(vm)
|
||||
|
||||
vm.SetGlobal("request", luar.New(vm, &req{r}))
|
||||
vm.SetGlobal("response", luar.New(vm, w))
|
||||
|
||||
if err := runFile(vm, l.scriptFile); err != nil {
|
||||
log.Errorln(err)
|
||||
http.Error(w, "server error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
type req struct {
|
||||
*http.Request
|
||||
}
|
||||
|
||||
func (r1 *req) GetBody() (string, error) {
|
||||
d, err := ioutil.ReadAll(r1.Body)
|
||||
return string(d), err
|
||||
}
|
||||
|
||||
func (r1 *req) GetIP() string {
|
||||
ip := r1.Header.Get("x-real-ip")
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
ip = r1.Header.Get("x-forwarded-for")
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
host, _, _ := net.SplitHostPort(r1.RemoteAddr)
|
||||
return host
|
||||
}
|
@ -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
|
@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
gluahttp "github.com/cjoudrey/gluahttp"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
luajson "layeh.com/gopher-json"
|
||||
luar "layeh.com/gopher-luar"
|
||||
mysql "github.com/tengattack/gluasql/mysql"
|
||||
redis "github.com/fangdingjun/gopher-redis"
|
||||
)
|
||||
|
||||
// from https://github.com/yuin/gophoer-lua
|
||||
|
||||
type lStatePool struct {
|
||||
m sync.Mutex
|
||||
saved []*lua.LState
|
||||
}
|
||||
|
||||
func (pl *lStatePool) Get() *lua.LState {
|
||||
pl.m.Lock()
|
||||
defer pl.m.Unlock()
|
||||
n := len(pl.saved)
|
||||
if n == 0 {
|
||||
return pl.New()
|
||||
}
|
||||
x := pl.saved[n-1]
|
||||
pl.saved = pl.saved[0 : n-1]
|
||||
return x
|
||||
}
|
||||
|
||||
func (pl *lStatePool) New() *lua.LState {
|
||||
L := lua.NewState()
|
||||
|
||||
luajson.Preload(L)
|
||||
L.PreloadModule("http", gluahttp.NewHttpModule(&http.Client{}).Loader)
|
||||
L.PreloadModule("mysql", mysql.Loader)
|
||||
L.PreloadModule("redis", redis.Loader)
|
||||
|
||||
L.SetGlobal("infolog", luar.New(L, infoLog))
|
||||
L.SetGlobal("errorlog", luar.New(L, errorLog))
|
||||
L.SetGlobal("debuglog", luar.New(L, debugLog))
|
||||
|
||||
// setting the L up here.
|
||||
// load scripts, set global variables, share channels, etc...
|
||||
return L
|
||||
}
|
||||
|
||||
func (pl *lStatePool) Put(L *lua.LState) {
|
||||
pl.m.Lock()
|
||||
defer pl.m.Unlock()
|
||||
pl.saved = append(pl.saved, L)
|
||||
}
|
||||
|
||||
func (pl *lStatePool) Shutdown() {
|
||||
pl.m.Lock()
|
||||
defer pl.m.Unlock()
|
||||
for _, L := range pl.saved {
|
||||
L.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Global LState pool
|
||||
var luaPool = &lStatePool{
|
||||
saved: make([]*lua.LState, 0, 4),
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
//"bufio"
|
||||
//"fmt"
|
||||
"io"
|
||||
"log"
|
||||
//"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type proxy struct {
|
||||
transport http.RoundTripper
|
||||
addr string
|
||||
prefix string
|
||||
dialer *net.Dialer
|
||||
network string
|
||||
}
|
||||
|
||||
func newProxy(addr string, prefix string) *proxy {
|
||||
p := &proxy{
|
||||
addr: addr,
|
||||
prefix: prefix,
|
||||
dialer: &net.Dialer{Timeout: 2 * time.Second},
|
||||
}
|
||||
if addr[0] == '/' {
|
||||
p.network = "unix"
|
||||
} else {
|
||||
p.network = "tcp"
|
||||
}
|
||||
p.transport = &http.Transport{
|
||||
DialContext: p.dialContext,
|
||||
MaxIdleConns: 5,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *proxy) dialContext(ctx context.Context,
|
||||
network, addr string) (net.Conn, error) {
|
||||
return p.dialer.DialContext(ctx, p.network, p.addr)
|
||||
}
|
||||
|
||||
func (p *proxy) dial(network, addr string) (conn net.Conn, err error) {
|
||||
return p.dialer.Dial(p.network, p.addr)
|
||||
}
|
||||
|
||||
func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
host, _, _ := net.SplitHostPort(r.RemoteAddr)
|
||||
r.Header.Add("X-Forwarded-For", host)
|
||||
r.URL.Scheme = "http"
|
||||
r.URL.Host = r.Host
|
||||
resp, err := p.transport.RoundTrip(r)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
w.WriteHeader(http.StatusBadGateway)
|
||||
w.Write([]byte("<h1>502 Bad Gateway</h1>"))
|
||||
return
|
||||
}
|
||||
header := w.Header()
|
||||
for k, v := range resp.Header {
|
||||
for _, v1 := range v {
|
||||
header.Add(k, v1)
|
||||
}
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
io.Copy(w, resp.Body)
|
||||
resp.Body.Close()
|
||||
}
|
@ -0,0 +1 @@
|
||||
proxy_local*
|
@ -0,0 +1,9 @@
|
||||
proxy_local
|
||||
===========
|
||||
|
||||
accept http proxy request and forward to upstream proxy server via http2
|
||||
|
||||
usage
|
||||
====
|
||||
|
||||
use `./proxy_local -h` to see options
|
@ -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,161 @@
|
||||
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/fangdingjun/protolistener"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/trace"
|
||||
)
|
||||
|
||||
var logfile string
|
||||
func initServer(c *conf) error {
|
||||
|
||||
mux := mux.NewRouter()
|
||||
|
||||
for _, vh := range c.Vhosts {
|
||||
subroute := mux.Host(vh.Hostname)
|
||||
for _, rule := range vh.URLRules {
|
||||
subroute.PathPrefix(rule.Prefix).Handler(&luaHandler{rule.LuaFile})
|
||||
}
|
||||
subroute.PathPrefix("/").Handler(http.FileServer(http.Dir(vh.Docroot)))
|
||||
}
|
||||
|
||||
mux.PathPrefix("/debug/").Handler(http.DefaultServeMux)
|
||||
|
||||
if len(c.Vhosts) > 0 {
|
||||
rules := c.Vhosts[0].URLRules
|
||||
for _, rule := range rules {
|
||||
mux.PathPrefix(rule.Prefix).Handler(&luaHandler{rule.LuaFile})
|
||||
}
|
||||
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,
|
||||
events: trace.NewEventLog("http", fmt.Sprintf("%s:%d", _l.Addr, _l.Port)),
|
||||
}
|
||||
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 = protolistener.New(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)
|
||||
}
|
||||
|
||||
trace.AuthRequest = func(r *http.Request) (bool, bool) {
|
||||
return true, true
|
||||
}
|
||||
|
||||
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