Commit 96985fb3 authored by Thomas Hansen's avatar Thomas Hansen

adding support for php including clean urls and wordpress permalinks

parent 981ca72e
...@@ -7,7 +7,9 @@ import ( ...@@ -7,7 +7,9 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
...@@ -34,12 +36,23 @@ type Handler struct { ...@@ -34,12 +36,23 @@ type Handler struct {
Rules []Rule 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. // ServeHTTP satisfies the middleware.Handler interface.
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
servedFcgi := false servedFcgi := false
indexFile := "index.php"
ext := ".php"
splitText := ".php"
for _, rule := range h.Rules { for _, rule := range h.Rules {
if middleware.Path(r.URL.Path).Matches(rule.Path) { if middleware.Path(r.URL.Path).Matches(rule.Path) && (strings.HasSuffix(r.URL.Path, "/") ||
servedFcgi = true strings.HasSuffix(r.URL.Path, ext) || !h.DoesFileExist(r.URL.Path)) {
// Get absolute file paths // Get absolute file paths
absPath, err := filepath.Abs(h.Root + r.URL.Path) 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) ...@@ -56,8 +69,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
// Separate remote IP and port // Separate remote IP and port
var ip, port string var ip, port string
if idx := strings.Index(r.RemoteAddr, ":"); idx > -1 { if idx := strings.Index(r.RemoteAddr, ":"); idx > -1 {
ip = r.RemoteAddr[idx:] ip = r.RemoteAddr[:idx]
port = r.RemoteAddr[:idx] port = r.RemoteAddr[idx:]
} else { } else {
ip = r.RemoteAddr ip = r.RemoteAddr
} }
...@@ -65,6 +78,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) ...@@ -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: Do we really have to make this map from scratch for each request?
// TODO: We have quite a few more to map, too. // TODO: We have quite a few more to map, too.
env := make(map[string]string) env := make(map[string]string)
env["SERVER_NAME"] = "caddy"
env["SERVER_SOFTWARE"] = "caddy" // TODO: Obtain version info... env["SERVER_SOFTWARE"] = "caddy" // TODO: Obtain version info...
env["SERVER_PROTOCOL"] = r.Proto env["SERVER_PROTOCOL"] = r.Proto
env["SCRIPT_FILENAME"] = absPath env["SCRIPT_FILENAME"] = absPath
...@@ -72,15 +86,40 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) ...@@ -72,15 +86,40 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
env["REMOTE_PORT"] = port env["REMOTE_PORT"] = port
env["REQUEST_METHOD"] = r.Method env["REQUEST_METHOD"] = r.Method
env["QUERY_STRING"] = r.URL.RawQuery 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["DOCUMENT_ROOT"] = absRootPath
env["HTTP_COOKIE"] = r.Header.Get("Cookie")
fcgi, err := Dial("tcp", rule.Address) fcgi, err := Dial("tcp", rule.Address)
if err != nil { if err != nil {
return http.StatusBadGateway, err 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 { if err != nil && err != io.EOF {
return http.StatusBadGateway, err return http.StatusBadGateway, err
} }
...@@ -99,7 +138,9 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) ...@@ -99,7 +138,9 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
w.WriteHeader(resp.StatusCode) w.WriteHeader(resp.StatusCode)
w.Write(body) w.Write(body)
break servedFcgi = true
return resp.StatusCode, nil
} }
} }
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"sync" "sync"
) )
...@@ -373,6 +374,14 @@ func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http. ...@@ -373,6 +374,14 @@ func (this *FCGIClient) Request(p map[string]string, req io.Reader) (resp *http.
} }
resp.Header = http.Header(mimeHeader) 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 ? // TODO: fixTransferEncoding ?
resp.TransferEncoding = resp.Header["Transfer-Encoding"] resp.TransferEncoding = resp.Header["Transfer-Encoding"]
resp.ContentLength, _ = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64) resp.ContentLength, _ = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment