--- /dev/null
+package cfg
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "path"
+ "strconv"
+ "strings"
+ "time"
+
+ fcgiclient "github.com/alash3al/go-fastcgi-client"
+ "go.stargrave.org/godlighty"
+)
+
+func ServeFCGI(
+ w http.ResponseWriter,
+ r *http.Request,
+ host, docRoot, scriptName, sockProto, sockPath string,
+ timeout time.Duration,
+) {
+ defer r.Body.Close()
+ serverHost, serverPort, err := net.SplitHostPort(godlighty.BindAddr)
+ if err != nil {
+ panic(err)
+ }
+ remoteAddr, remotePort, _ := net.SplitHostPort(r.RemoteAddr)
+ params := map[string]string{
+ "GATEWAY_INTERFACE": "CGI/1.1",
+
+ "PATH_INFO": r.URL.Path,
+ "QUERY_STRING": r.URL.RawQuery,
+
+ "REMOTE_ADDR": remoteAddr,
+ "REMOTE_PORT": remotePort,
+
+ "SERVER_NAME": serverHost,
+ "SERVER_PORT": serverPort,
+ "SERVER_PROTOCOL": r.Proto,
+ "SERVER_SOFTWARE": godlighty.Version,
+
+ "REQUEST_METHOD": r.Method,
+ "DOCUMENT_ROOT": docRoot,
+ "SCRIPT_NAME": scriptName,
+ "SCRIPT_FILENAME": path.Join(docRoot, scriptName),
+ }
+ for k, vs := range r.Header {
+ if len(vs) < 1 {
+ continue
+ }
+ k = "HTTP_" + strings.ToUpper(strings.Replace(k, "-", "_", -1))
+ params[k] = strings.Join(vs, ";")
+ }
+ c, err := fcgiclient.Dial(sockProto, sockPath)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ log.Println("can not FCGI:", err)
+ return
+ }
+ defer c.Close()
+ c.SetReadTimeout(timeout)
+ c.SetSendTimeout(timeout)
+ resp, err := c.Request(params, r.Body)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ log.Println("can not FCGI:", err)
+ return
+ }
+ defer resp.Body.Close()
+ for k, vs := range resp.Header {
+ for _, v := range vs {
+ w.Header().Add(k, v)
+ }
+ }
+ if resp.ContentLength > 0 {
+ w.Header().Set("Content-Length", strconv.FormatInt(resp.ContentLength, 10))
+ }
+ w.WriteHeader(resp.StatusCode)
+ written, err := io.Copy(w, resp.Body)
+ if err != nil {
+ stderr := c.Stderr()
+ log.Println("can not copy FCGI:", string(stderr.Bytes()))
+ return
+ }
+ fmt.Printf("%s %s \"%s %+q %s\" %d %d \"%s\"\n",
+ r.RemoteAddr, host, r.Method, godlighty.PathWithQuery(r.URL), r.Proto,
+ resp.StatusCode, written,
+ r.Header.Get("User-Agent"),
+ )
+}