| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | package http | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-02-15 22:51:01 +01:00
										 |  |  | 	"bufio" | 
					
						
							| 
									
										
										
										
											2017-01-15 00:57:06 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2017-10-28 14:25:22 +02:00
										 |  |  | 	"encoding/base64" | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2015-12-14 16:26:29 +00:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2015-12-15 00:53:40 +01:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2015-12-14 16:26:29 +00:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2017-01-31 12:42:05 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 20:55:45 +02:00
										 |  |  | 	"v2ray.com/core/app" | 
					
						
							|  |  |  | 	"v2ray.com/core/app/dispatcher" | 
					
						
							| 
									
										
										
										
											2017-02-03 22:35:09 +01:00
										 |  |  | 	"v2ray.com/core/app/log" | 
					
						
							| 
									
										
										
										
											2016-08-20 20:55:45 +02:00
										 |  |  | 	"v2ray.com/core/common" | 
					
						
							| 
									
										
										
										
											2016-12-09 13:17:34 +01:00
										 |  |  | 	"v2ray.com/core/common/buf" | 
					
						
							| 
									
										
										
										
											2016-12-04 09:10:47 +01:00
										 |  |  | 	"v2ray.com/core/common/errors" | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 	"v2ray.com/core/common/net" | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	"v2ray.com/core/common/signal" | 
					
						
							| 
									
										
										
										
											2016-08-20 20:55:45 +02:00
										 |  |  | 	"v2ray.com/core/transport/internet" | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 16:46:31 +02:00
										 |  |  | // Server is a HTTP proxy server. | 
					
						
							|  |  |  | type Server struct { | 
					
						
							| 
									
										
										
										
											2017-02-03 22:35:09 +01:00
										 |  |  | 	config *ServerConfig | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-22 13:54:11 +01:00
										 |  |  | // NewServer creates a new HTTP inbound handler. | 
					
						
							| 
									
										
										
										
											2017-01-13 00:56:21 +01:00
										 |  |  | func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { | 
					
						
							|  |  |  | 	space := app.SpaceFromContext(ctx) | 
					
						
							|  |  |  | 	if space == nil { | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 		return nil, newError("no space in context.") | 
					
						
							| 
									
										
										
										
											2017-01-13 00:56:21 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-06 15:32:36 +01:00
										 |  |  | 	s := &Server{ | 
					
						
							|  |  |  | 		config: config, | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-13 00:56:21 +01:00
										 |  |  | 	return s, nil | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | func (*Server) Network() net.NetworkList { | 
					
						
							|  |  |  | 	return net.NetworkList{ | 
					
						
							|  |  |  | 		Network: []net.Network{net.Network_TCP}, | 
					
						
							| 
									
										
										
										
											2017-01-15 00:57:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | func parseHost(rawHost string, defaultPort net.Port) (net.Destination, error) { | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 	port := defaultPort | 
					
						
							| 
									
										
										
										
											2015-12-15 00:53:40 +01:00
										 |  |  | 	host, rawPort, err := net.SplitHostPort(rawHost) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if addrError, ok := err.(*net.AddrError); ok && strings.Contains(addrError.Err, "missing port") { | 
					
						
							|  |  |  | 			host = rawHost | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 			return net.Destination{}, err | 
					
						
							| 
									
										
										
										
											2015-12-15 00:53:40 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-03 13:03:51 +01:00
										 |  |  | 	} else if len(rawPort) > 0 { | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 		intPort, err := strconv.Atoi(rawPort) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 			return net.Destination{}, err | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 		port = net.Port(intPort) | 
					
						
							| 
									
										
										
										
											2015-12-14 16:26:29 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 	return net.TCPDestination(net.ParseAddress(host), port), nil | 
					
						
							| 
									
										
										
										
											2015-12-14 16:26:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-12 00:21:46 +02:00
										 |  |  | func isTimeout(err error) bool { | 
					
						
							| 
									
										
										
										
											2017-11-16 12:01:42 +01:00
										 |  |  | 	nerr, ok := errors.Cause(err).(net.Error) | 
					
						
							| 
									
										
										
										
											2017-04-12 00:21:46 +02:00
										 |  |  | 	return ok && nerr.Timeout() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-28 14:25:22 +02:00
										 |  |  | func parseBasicAuth(auth string) (username, password string, ok bool) { | 
					
						
							|  |  |  | 	const prefix = "Basic " | 
					
						
							|  |  |  | 	if !strings.HasPrefix(auth, prefix) { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cs := string(c) | 
					
						
							|  |  |  | 	s := strings.IndexByte(cs, ':') | 
					
						
							|  |  |  | 	if s < 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cs[:s], cs[s+1:], true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 	reader := bufio.NewReaderSize(conn, buf.Size) | 
					
						
							| 
									
										
										
										
											2017-11-17 02:56:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | Start: | 
					
						
							| 
									
										
										
										
											2017-11-17 02:56:24 +00:00
										 |  |  | 	conn.SetReadDeadline(time.Now().Add(time.Second * 16)) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	request, err := http.ReadRequest(reader) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		trace := newError("failed to read http request").Base(err) | 
					
						
							| 
									
										
										
										
											2017-04-12 00:21:46 +02:00
										 |  |  | 		if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) { | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 			trace.AtWarning() | 
					
						
							| 
									
										
										
										
											2016-06-03 20:21:46 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		return trace | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-26 21:44:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(s.config.Accounts) > 0 { | 
					
						
							| 
									
										
										
										
											2017-10-28 14:25:22 +02:00
										 |  |  | 		user, pass, ok := parseBasicAuth(request.Header.Get("Proxy-Authorization")) | 
					
						
							| 
									
										
										
										
											2017-11-18 19:40:53 +01:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			_, err := conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\n\r\n")) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !s.config.HasAccount(user, pass) { | 
					
						
							| 
									
										
										
										
											2017-10-26 21:44:13 +02:00
										 |  |  | 			_, err := conn.Write([]byte("HTTP/1.1 401 UNAUTHORIZED\r\n\r\n")) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 	log.Trace(newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]")) | 
					
						
							| 
									
										
										
										
											2017-11-17 02:56:24 +00:00
										 |  |  | 	conn.SetReadDeadline(time.Time{}) | 
					
						
							| 
									
										
										
										
											2017-01-31 16:49:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 	defaultPort := net.Port(80) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	if strings.ToLower(request.URL.Scheme) == "https" { | 
					
						
							| 
									
										
										
										
											2017-08-29 12:56:57 +02:00
										 |  |  | 		defaultPort = net.Port(443) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	host := request.Host | 
					
						
							|  |  |  | 	if len(host) == 0 { | 
					
						
							|  |  |  | 		host = request.URL.Host | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dest, err := parseHost(host, defaultPort) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 		return newError("malformed proxy host: ", host).AtWarning().Base(err) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-05 15:02:15 +02:00
										 |  |  | 	log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") | 
					
						
							| 
									
										
										
										
											2017-02-03 22:35:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	if strings.ToUpper(request.Method) == "CONNECT" { | 
					
						
							| 
									
										
										
										
											2017-11-17 02:56:24 +00:00
										 |  |  | 		return s.handleConnect(ctx, request, reader, conn, dest, dispatcher) | 
					
						
							| 
									
										
										
										
											2015-12-16 15:52:40 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	keepAlive := (strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 	err = s.handlePlainHTTP(ctx, request, conn, dest, dispatcher) | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 	if err == errWaitAnother { | 
					
						
							|  |  |  | 		if keepAlive { | 
					
						
							|  |  |  | 			goto Start | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		err = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2015-12-16 15:52:40 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-15 22:13:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher dispatcher.Interface) error { | 
					
						
							|  |  |  | 	_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) | 
					
						
							| 
									
										
										
										
											2017-04-18 13:30:26 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 		return newError("failed to write back OK response").Base(err) | 
					
						
							| 
									
										
										
										
											2016-12-22 13:54:11 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-31 16:49:59 +01:00
										 |  |  | 	timeout := time.Second * time.Duration(s.config.Timeout) | 
					
						
							|  |  |  | 	if timeout == 0 { | 
					
						
							| 
									
										
										
										
											2017-09-27 21:09:13 +02:00
										 |  |  | 		timeout = time.Minute * 5 | 
					
						
							| 
									
										
										
										
											2017-01-31 16:49:59 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-15 00:36:14 +01:00
										 |  |  | 	ctx, cancel := context.WithCancel(ctx) | 
					
						
							|  |  |  | 	timer := signal.CancelAfterInactivity(ctx, cancel, timeout) | 
					
						
							| 
									
										
										
										
											2017-02-03 22:35:09 +01:00
										 |  |  | 	ray, err := dispatcher.Dispatch(ctx, dest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 	if reader.Buffered() > 0 { | 
					
						
							|  |  |  | 		payload := buf.New() | 
					
						
							|  |  |  | 		common.Must(payload.Reset(func(b []byte) (int, error) { | 
					
						
							|  |  |  | 			return reader.Read(b[:reader.Buffered()]) | 
					
						
							|  |  |  | 		})) | 
					
						
							|  |  |  | 		if err := ray.InboundInput().WriteMultiBuffer(buf.NewMultiBufferValue(payload)); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-17 20:58:46 +01:00
										 |  |  | 		reader = nil | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	requestDone := signal.ExecuteAsync(func() error { | 
					
						
							|  |  |  | 		defer ray.InboundInput().Close() | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 		v2reader := buf.NewReader(conn) | 
					
						
							| 
									
										
										
										
											2017-11-17 21:02:32 +01:00
										 |  |  | 		return buf.Copy(v2reader, ray.InboundInput(), buf.UpdateActivity(timer)) | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	responseDone := signal.ExecuteAsync(func() error { | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | 		v2writer := buf.NewWriter(conn) | 
					
						
							| 
									
										
										
										
											2017-04-27 22:30:48 +02:00
										 |  |  | 		if err := buf.Copy(ray.InboundOutput(), v2writer, buf.UpdateActivity(timer)); err != nil { | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2016-11-22 00:17:49 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-27 15:29:00 +02:00
										 |  |  | 		timer.SetTimeout(time.Second * 2) | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-28 21:24:46 +01:00
										 |  |  | 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-10 14:22:42 +01:00
										 |  |  | 		ray.InboundInput().CloseError() | 
					
						
							|  |  |  | 		ray.InboundOutput().CloseError() | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 		return newError("connection ends").Base(err) | 
					
						
							| 
									
										
										
										
											2017-01-10 14:22:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-26 20:46:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-15 16:00:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 23:27:06 +01:00
										 |  |  | // @VisibleForTesting | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | func StripHopByHopHeaders(header http.Header) { | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	// Strip hop-by-hop header basaed on RFC: | 
					
						
							|  |  |  | 	// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 | 
					
						
							|  |  |  | 	// https://www.mnot.net/blog/2011/07/11/what_proxies_must_do | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 	header.Del("Proxy-Connection") | 
					
						
							|  |  |  | 	header.Del("Proxy-Authenticate") | 
					
						
							|  |  |  | 	header.Del("Proxy-Authorization") | 
					
						
							|  |  |  | 	header.Del("TE") | 
					
						
							|  |  |  | 	header.Del("Trailers") | 
					
						
							|  |  |  | 	header.Del("Transfer-Encoding") | 
					
						
							|  |  |  | 	header.Del("Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	connections := header.Get("Connection") | 
					
						
							| 
									
										
										
										
											2017-04-12 00:21:46 +02:00
										 |  |  | 	header.Del("Connection") | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	if len(connections) == 0 { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, h := range strings.Split(connections, ",") { | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		header.Del(strings.TrimSpace(h)) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-05 19:24:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Prevent UA from being set to golang's default ones | 
					
						
							|  |  |  | 	if len(header.Get("User-Agent")) == 0 { | 
					
						
							|  |  |  | 		header.Set("User-Agent", "") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | var errWaitAnother = newError("keep alive") | 
					
						
							| 
									
										
										
										
											2016-06-02 00:57:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 20:54:24 +01:00
										 |  |  | func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { | 
					
						
							| 
									
										
										
										
											2017-11-05 22:13:15 +01:00
										 |  |  | 	if !s.config.AllowTransparent && len(request.URL.Host) <= 0 { | 
					
						
							|  |  |  | 		// RFC 2068 (HTTP/1.1) requires URL to be absolute URL in HTTP proxy. | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		response := &http.Response{ | 
					
						
							|  |  |  | 			Status:        "Bad Request", | 
					
						
							|  |  |  | 			StatusCode:    400, | 
					
						
							|  |  |  | 			Proto:         "HTTP/1.1", | 
					
						
							|  |  |  | 			ProtoMajor:    1, | 
					
						
							|  |  |  | 			ProtoMinor:    1, | 
					
						
							|  |  |  | 			Header:        http.Header(make(map[string][]string)), | 
					
						
							|  |  |  | 			Body:          nil, | 
					
						
							|  |  |  | 			ContentLength: 0, | 
					
						
							|  |  |  | 			Close:         true, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		response.Header.Set("Proxy-Connection", "close") | 
					
						
							|  |  |  | 		response.Header.Set("Connection", "close") | 
					
						
							| 
									
										
										
										
											2017-01-26 20:46:44 +01:00
										 |  |  | 		return response.Write(writer) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-05 22:13:15 +01:00
										 |  |  | 	if len(request.URL.Host) > 0 { | 
					
						
							|  |  |  | 		request.Host = request.URL.Host | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 	StripHopByHopHeaders(request.Header) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 22:35:09 +01:00
										 |  |  | 	ray, err := dispatcher.Dispatch(ctx, dest) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-30 00:51:39 +01:00
										 |  |  | 	input := ray.InboundInput() | 
					
						
							|  |  |  | 	output := ray.InboundOutput() | 
					
						
							| 
									
										
										
										
											2017-01-28 23:34:55 +01:00
										 |  |  | 	defer input.Close() | 
					
						
							| 
									
										
										
										
											2016-12-30 00:51:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 14:18:09 +02:00
										 |  |  | 	var result error = errWaitAnother | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	requestDone := signal.ExecuteAsync(func() error { | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		request.Header.Set("Connection", "close") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 22:33:15 +01:00
										 |  |  | 		requestWriter := buf.NewBufferedWriter(ray.InboundInput()) | 
					
						
							| 
									
										
										
										
											2017-11-15 11:23:25 +01:00
										 |  |  | 		common.Must(requestWriter.SetBuffered(false)) | 
					
						
							|  |  |  | 		return request.Write(requestWriter) | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	responseDone := signal.ExecuteAsync(func() error { | 
					
						
							| 
									
										
										
										
											2017-11-09 22:33:15 +01:00
										 |  |  | 		responseReader := bufio.NewReaderSize(buf.NewBufferedReader(ray.InboundOutput()), 2048) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 		response, err := http.ReadResponse(responseReader, request) | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			StripHopByHopHeaders(response.Header) | 
					
						
							| 
									
										
										
										
											2017-04-18 13:39:34 +02:00
										 |  |  | 			if response.ContentLength >= 0 { | 
					
						
							|  |  |  | 				response.Header.Set("Proxy-Connection", "keep-alive") | 
					
						
							|  |  |  | 				response.Header.Set("Connection", "keep-alive") | 
					
						
							|  |  |  | 				response.Header.Set("Keep-Alive", "timeout=4") | 
					
						
							|  |  |  | 				response.Close = false | 
					
						
							| 
									
										
										
										
											2017-04-18 14:18:09 +02:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				response.Close = true | 
					
						
							|  |  |  | 				result = nil | 
					
						
							| 
									
										
										
										
											2017-04-18 13:39:34 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-04-18 00:14:42 +02:00
										 |  |  | 			log.Trace(newError("failed to read response from ", request.Host).Base(err).AtWarning()) | 
					
						
							| 
									
										
										
										
											2017-04-11 14:59:58 +02:00
										 |  |  | 			response = &http.Response{ | 
					
						
							|  |  |  | 				Status:        "Service Unavailable", | 
					
						
							|  |  |  | 				StatusCode:    503, | 
					
						
							|  |  |  | 				Proto:         "HTTP/1.1", | 
					
						
							|  |  |  | 				ProtoMajor:    1, | 
					
						
							|  |  |  | 				ProtoMinor:    1, | 
					
						
							|  |  |  | 				Header:        http.Header(make(map[string][]string)), | 
					
						
							|  |  |  | 				Body:          nil, | 
					
						
							|  |  |  | 				ContentLength: 0, | 
					
						
							|  |  |  | 				Close:         true, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			response.Header.Set("Connection", "close") | 
					
						
							|  |  |  | 			response.Header.Set("Proxy-Connection", "close") | 
					
						
							| 
									
										
										
										
											2016-05-25 09:32:26 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-17 22:35:20 +02:00
										 |  |  | 		if err := response.Write(writer); err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-18 00:14:42 +02:00
										 |  |  | 			return newError("failed to write response").Base(err) | 
					
						
							| 
									
										
										
										
											2015-12-31 23:34:08 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-28 21:24:46 +01:00
										 |  |  | 	if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-10 14:22:42 +01:00
										 |  |  | 		input.CloseError() | 
					
						
							|  |  |  | 		output.CloseError() | 
					
						
							| 
									
										
										
										
											2017-04-09 01:43:25 +02:00
										 |  |  | 		return newError("connection ends").Base(err) | 
					
						
							| 
									
										
										
										
											2016-12-30 00:32:20 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-26 20:46:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 14:18:09 +02:00
										 |  |  | 	return result | 
					
						
							| 
									
										
										
										
											2015-10-28 12:13:27 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-07 14:08:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2017-01-13 00:56:21 +01:00
										 |  |  | 	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { | 
					
						
							|  |  |  | 		return NewServer(ctx, config.(*ServerConfig)) | 
					
						
							|  |  |  | 	})) | 
					
						
							| 
									
										
										
										
											2016-05-07 14:08:27 +02:00
										 |  |  | } |