func (f *Filter) Request(ctx *filters.Context, req *http.Request) (*filters.Context, *http.Request, error) { if req.Method != "CONNECT" || !f.Match(req.Host) { return ctx, req, nil } hijacker, ok := ctx.GetResponseWriter().(http.Hijacker) if !ok { return ctx, nil, fmt.Errorf("%#v does not implments Hijacker", ctx.GetResponseWriter()) } conn, _, err := hijacker.Hijack() if err != nil { return ctx, nil, fmt.Errorf("http.ResponseWriter Hijack failed: %s", err) } _, err = io.WriteString(conn, "HTTP/1.1 200 OK\r\n\r\n") if err != nil { conn.Close() return ctx, nil, err } glog.Infof("%s \"STRIP %s %s %s\" - -", req.RemoteAddr, req.Method, req.Host, req.Proto) cert, err := f.issue(req.Host) if err != nil { conn.Close() return ctx, nil, err } tlsConfig := &tls.Config{ Certificates: []tls.Certificate{*cert}, ClientAuth: tls.VerifyClientCertIfGiven, } tlsConn := tls.Server(conn, tlsConfig) if err := tlsConn.Handshake(); err != nil { conn.Close() return ctx, nil, err } if ln1, ok := ctx.GetListener().(httpproxy.Listener); ok { ln1.Add(tlsConn) ctx.SetHijacked(true) return ctx, nil, nil } loConn, err := net.Dial("tcp", ctx.GetListener().Addr().String()) if err != nil { return ctx, nil, err } go httpproxy.IoCopy(loConn, tlsConn) go httpproxy.IoCopy(tlsConn, loConn) ctx.SetHijacked(true) return ctx, nil, nil }