mirror of
https://code.rocketnine.space/tslocum/twins.git
synced 2024-11-27 11:28:14 +01:00
4f0c9f2c39
Resolves !2.
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
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)
|
|
}
|
|
}
|