adding support for php including clean urls and wordpress permalinks

This commit is contained in:
Thomas Hansen 2015-04-20 17:40:54 -06:00
parent 981ca72ee6
commit 96985fb3fd
2 changed files with 57 additions and 7 deletions

View File

@ -7,7 +7,9 @@ import (
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/mholt/caddy/middleware"
@ -34,12 +36,23 @@ type Handler struct {
Rules []Rule
}
func (h Handler) DoesFileExist(path string) bool {
file := h.Root + path
if _, err := os.Stat(file); err == nil {
return true
}
return false
}
// ServeHTTP satisfies the middleware.Handler interface.
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
servedFcgi := false
indexFile := "index.php"
ext := ".php"
splitText := ".php"
for _, rule := range h.Rules {
if middleware.Path(r.URL.Path).Matches(rule.Path) {
servedFcgi = true
if middleware.Path(r.URL.Path).Matches(rule.Path) && (strings.HasSuffix(r.URL.Path, "/") ||
strings.HasSuffix(r.URL.Path, ext) || !h.DoesFileExist(r.URL.Path)) {
// Get absolute file paths
absPath, err := filepath.Abs(h.Root + r.URL.Path)
@ -56,8 +69,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
// Separate remote IP and port
var ip, port string
if idx := strings.Index(r.RemoteAddr, ":"); idx > -1 {
ip = r.RemoteAddr[idx:]
port = r.RemoteAddr[:idx]
ip = r.RemoteAddr[:idx]
port = r.RemoteAddr[idx:]
} else {
ip = r.RemoteAddr
}
@ -65,6 +78,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
// TODO: Do we really have to make this map from scratch for each request?
// TODO: We have quite a few more to map, too.
env := make(map[string]string)
env["SERVER_NAME"] = "caddy"
env["SERVER_SOFTWARE"] = "caddy" // TODO: Obtain version info...
env["SERVER_PROTOCOL"] = r.Proto
env["SCRIPT_FILENAME"] = absPath
@ -72,15 +86,40 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
env["REMOTE_PORT"] = port
env["REQUEST_METHOD"] = r.Method
env["QUERY_STRING"] = r.URL.RawQuery
env["DOCUMENT_URI"] = r.URL.Path
env["SCRIPT_NAME"] = r.URL.Path
env["HTTP_HOST"] = r.Host
split := strings.Index(r.URL.Path, splitText)
if split == -1 {
//request doesn't have the extension
//send the request to the index file
env["DOCUMENT_URI"] = "/" + indexFile
env["SCRIPT_NAME"] = "/" + indexFile
env["SCRIPT_FILENAME"] = absRootPath + "/" + indexFile
env["PATH_INFO"] = r.URL.Path
} else {
env["DOCUMENT_URI"] = r.URL.Path[:split+len(splitText)]
env["PATH_INFO"] = r.URL.Path[split+len(splitText):]
}
env["REQUEST_URI"] = r.URL.RequestURI()
env["DOCUMENT_ROOT"] = absRootPath
env["HTTP_COOKIE"] = r.Header.Get("Cookie")
fcgi, err := Dial("tcp", rule.Address)
if err != nil {
return http.StatusBadGateway, err
}
resp, err := fcgi.Get(env)
var resp *http.Response
if r.Method == "GET" {
resp, err = fcgi.Get(env)
} else {
l, _ := strconv.Atoi(r.Header.Get("Content-Length"))
resp, err = fcgi.Post(env, r.Header.Get("Content-Type"), r.Body, l)
}
if err != nil && err != io.EOF {
return http.StatusBadGateway, err
}
@ -99,7 +138,9 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
w.WriteHeader(resp.StatusCode)
w.Write(body)
break
servedFcgi = true
return resp.StatusCode, nil
}
}

View File

@ -26,6 +26,7 @@ import (
"os"
"path/filepath"
"strconv"
"strings"
"sync"
)
@ -373,6 +374,14 @@ func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.
}
resp.Header = http.Header(mimeHeader)
if resp.Header.Get("Status") != "" {
statusParts := strings.SplitN(resp.Header.Get("Status"), " ", 2)
resp.StatusCode, _ = strconv.Atoi(statusParts[0])
resp.Status = statusParts[1]
} else {
resp.StatusCode = 200
}
// TODO: fixTransferEncoding ?
resp.TransferEncoding = resp.Header["Transfer-Encoding"]
resp.ContentLength, _ = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)