use gofast implement to handle php script

master
Dingjun 8 years ago
parent fee0a0bf02
commit dd6cbd7f81

1
.gitignore vendored

@ -1,3 +1,4 @@
*~ *~
fileserver* fileserver*
gserver* gserver*
*swp

@ -1,115 +0,0 @@
package main
import (
"fmt"
"github.com/fangdingjun/gofast"
"log"
"net"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
)
// FastCGI is a fastcgi client connection
type FastCGI struct {
Network string
Addr string
DocRoot string
URLPrefix string
//client gofast.Client
}
// NewFastCGI creates a new FastCGI struct
func NewFastCGI(network, addr, docroot, urlPrefix string) (*FastCGI, error) {
u := strings.TrimRight(urlPrefix, "/")
return &FastCGI{network, addr, docroot, u}, nil
}
var fcgiPathInfo = regexp.MustCompile(`^(.*?\.php)(.*)$`)
// ServeHTTP implements http.Handler interface
func (f *FastCGI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
f.FastCGIPass(w, r)
}
// FastCGIPass pass the request to fastcgi socket
func (f *FastCGI) FastCGIPass(w http.ResponseWriter, r *http.Request) {
// make sure server not access the file out of document root
p1 := filepath.Clean(filepath.Join(f.DocRoot, r.URL.Path))
p2 := filepath.Clean(f.DocRoot)
if !strings.HasPrefix(p1, p2) {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "invalid url")
return
}
var scriptName, pathInfo, scriptFileName string
conn, err := net.Dial(f.Network, f.Addr)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusBadGateway)
return
}
defer conn.Close()
client := gofast.NewClient(f.DocRoot, conn, 20)
urlPath := r.URL.Path
if f.URLPrefix != "" {
urlPath = strings.Replace(r.URL.Path, f.URLPrefix, "", 1)
}
p := fcgiPathInfo.FindStringSubmatch(urlPath)
if len(p) < 2 {
if strings.HasSuffix(r.URL.Path, "/") {
// redirect to index.php
scriptName = filepath.Join(r.URL.Path, "index.php")
pathInfo = ""
scriptFileName = filepath.Join(f.DocRoot, urlPath, "index.php")
} else {
// serve static file in php directory
fn := filepath.Join(f.DocRoot, urlPath)
http.ServeFile(w, r, fn)
return
}
} else {
scriptName = p[1]
pathInfo = p[2]
scriptFileName = filepath.Join(f.DocRoot, scriptName)
}
req := client.NewRequest(r)
// set ourself path, prefix stripped
// req.Params["DOCUMENT_URI"] = scriptName
req.Params["SCRIPT_NAME"] = scriptName
req.Params["PHP_SELF"] = scriptName
req.Params["PATH_INFO"] = pathInfo
req.Params["SCRIPT_FILENAME"] = scriptFileName
scheme := "http"
if r.TLS != nil {
scheme = "https"
}
req.Params["REQUEST_SCHEME"] = scheme
resp, err := client.Do(req)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusBadGateway)
return
}
err = resp.WriteTo(w, os.Stderr)
if err != nil {
log.Println(err)
}
resp.Close()
}

@ -3,6 +3,7 @@ package main
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/fangdingjun/gofast"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"log" "log"
"net" "net"
@ -155,22 +156,24 @@ func registerUwsgiHandler(r rule, router *mux.Router) {
} }
func registerFastCGIHandler(r rule, docroot string, router *mux.Router) { func registerFastCGIHandler(r rule, docroot string, router *mux.Router) {
var p string var n, p string
switch r.Target.Type { switch r.Target.Type {
case "unix": case "unix":
n = "unix"
p = r.Target.Path p = r.Target.Path
case "tcp": case "tcp":
n = "tcp"
p = fmt.Sprintf("%s:%d", r.Target.Host, r.Target.Port) p = fmt.Sprintf("%s:%d", r.Target.Host, r.Target.Port)
default: default:
fmt.Printf("invalid scheme: %s, only support unix, tcp", r.Target.Type) fmt.Printf("invalid scheme: %s, only support unix, tcp", r.Target.Type)
os.Exit(-1) os.Exit(-1)
} }
u := gofast.NewHandler(gofast.NewPHPFS(docroot), n, p)
if r.IsRegex { if r.IsRegex {
m1 := myURLMatch{regexp.MustCompile(r.URLPrefix)} m1 := myURLMatch{regexp.MustCompile(r.URLPrefix)}
u, _ := NewFastCGI(r.Target.Type, p, docroot, "")
router.MatcherFunc(m1.match).Handler(u) router.MatcherFunc(m1.match).Handler(u)
} else { } else {
u, _ := NewFastCGI(r.Target.Type, p, docroot, r.URLPrefix)
router.PathPrefix(r.URLPrefix).Handler(u) router.PathPrefix(r.URLPrefix).Handler(u)
} }
} }

Loading…
Cancel
Save