package main import ( "bytes" "crypto/sha1" "crypto/tls" "fmt" "io" "io/ioutil" "log" "net/http" "net/url" "path/filepath" "strings" "github.com/yookoala/gofast" ) type fakeResponseWriter struct { io.WriteCloser header http.Header } func newFakeResponseWriter(out io.WriteCloser) *fakeResponseWriter { return &fakeResponseWriter{ WriteCloser: out, header: make(http.Header), } } func (w *fakeResponseWriter) Header() http.Header { return w.header } func (w *fakeResponseWriter) WriteHeader(statusCode int) { // Do nothing } func serveFastCGI(c *tls.Conn, connFactory gofast.ConnFactory, u *url.URL, filePath string) { header := map[string][]string{ "Accept": {"*/*"}, "Host": {u.Hostname()}, } r := &http.Request{ Method: "GET", URL: u, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: header, Body: ioutil.NopCloser(bytes.NewReader(nil)), Host: u.Host, RemoteAddr: c.RemoteAddr().String(), } req := gofast.NewRequest(r) req.Params["CONTENT_TYPE"] = r.Header.Get("Content-Type") req.Params["CONTENT_LENGTH"] = r.Header.Get("Content-Length") req.Params["HTTP_HOST"] = r.Host req.Params["HTTPS"] = "on" req.Params["GATEWAY_INTERFACE"] = "CGI/1.1" req.Params["REMOTE_ADDR"] = strings.SplitN(c.RemoteAddr().String(), ":", 2)[0] req.Params["REMOTE_PORT"] = "1965" req.Params["SERVER_PORT"] = "1965" req.Params["SERVER_NAME"] = r.Host req.Params["SERVER_PROTOCOL"] = r.Proto req.Params["SERVER_SOFTWARE"] = "twins" req.Params["REDIRECT_STATUS"] = "200" req.Params["REQUEST_METHOD"] = r.Method req.Params["REQUEST_URI"] = r.RequestURI req.Params["QUERY_STRING"] = r.URL.RawQuery req.Params["DOCUMENT_ROOT"] = filepath.Dir(filePath) req.Params["DOCUMENT_URI"] = r.URL.Path req.Params["SCRIPT_FILENAME"] = filePath req.Params["SCRIPT_NAME"] = filepath.Base(filePath) certLabel := 'A' clientCerts := c.ConnectionState().PeerCertificates for i := 0; i < len(clientCerts) && i < 26; i++ { req.Params["CLIENT_CERT_"+string(certLabel+rune(i))] = fmt.Sprintf("%x", sha1.Sum(clientCerts[i].Raw)) } w := newFakeResponseWriter(c) client, err := gofast.SimpleClientFactory(connFactory)() if err != nil { log.Printf("FastCGI Error: %s", err) http.Error(w, "Failed to connect to FastCGI server", http.StatusInternalServerError) return } resp, err := client.Do(req) if err != nil { log.Printf("FastCGI Error: %s", err) http.Error(w, "Failed to connect to FastCGI server", http.StatusInternalServerError) return } errBuffer := new(bytes.Buffer) err = resp.WriteTo(w, errBuffer) if err != nil { log.Printf("FastCGI Error: %s", err) http.Error(w, "Failed to connect to FastCGI server", http.StatusInternalServerError) return } else if errBuffer.Len() > 0 { log.Printf("FastCGI Error: %s", errBuffer.String()) http.Error(w, "Failed to connect to FastCGI server", http.StatusInternalServerError) } }