add lua support
parent
c39fc8c107
commit
350ec51345
@ -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,31 +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/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
||||
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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc h1:lNOt1SMsgHXTdpuGw+RpnJtzUcCb/oRKZP65pBy9pr8=
|
||||
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 h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g=
|
||||
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 h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
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/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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
|
||||
}
|
@ -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),
|
||||
}
|
Loading…
Reference in New Issue