// Handles a new http connection from the public internet func httpHandler(tcpConn net.Conn, proto string) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // Make sure we detect dead connections while we decide how to multiplex conn.SetDeadline(time.Now().Add(connReadTimeout)) // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid %s request: %v", proto, err) conn.Write([]byte(BadRequest)) return } // read out the Host header from the request host := strings.ToLower(req.Host) conn.Debug("Found hostname %s in request", host) // multiplex to find the right backend host tunnel := tunnelRegistry.Get(fmt.Sprintf("%s://%s", proto, host)) if tunnel == nil { conn.Info("No tunnel found for hostname %s", host) conn.Write([]byte(fmt.Sprintf(NotFound, len(host)+18, host))) return } // If the client specified http auth and it doesn't match this request's auth // then fail the request with 401 Not Authorized and request the client reissue the // request with basic authdeny the request if tunnel.req.HttpAuth != "" && req.Header.Get("Authorization") != tunnel.req.HttpAuth { conn.Info("Authentication failed: %s", req.Header.Get("Authorization")) conn.Write([]byte(NotAuthorized)) return } // dead connections will now be handled by tunnel heartbeating and the client conn.SetDeadline(time.Time{}) // let the tunnel handle the connection now tunnel.HandlePublicConnection(conn) }
/** * Handles a new http connection from the public internet */ func httpHandler(tcpConn net.Conn) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid http request: %v", err) conn.Write([]byte(BadRequest)) return } // read out the Host header from the request host := strings.ToLower(req.Host) conn.Debug("Found hostname %s in request", host) // multiplex to find the right backend host tunnel := tunnels.Get("http://" + host) if tunnel == nil { conn.Info("No tunnel found for hostname %s", host) conn.Write([]byte(fmt.Sprintf(NotFound, len(host)+18, host))) return } // If the client specified http auth and it doesn't match this request's auth // then fail the request with 401 Not Authorized and request the client reissue the // request with basic authdeny the request if tunnel.regMsg.HttpAuth != "" && req.Header.Get("Authorization") != tunnel.regMsg.HttpAuth { conn.Info("Authentication failed: %s", req.Header.Get("Authorization")) conn.Write([]byte(NotAuthorized)) return } tunnel.HandlePublicConnection(conn) }
/** * Handles a new http connection from the public internet */ func httpHandler(tcpConn net.Conn) { // wrap up the connection for logging conn := conn.NewHttp(tcpConn, "pub") defer conn.Close() defer func() { // recover from failures if r := recover(); r != nil { conn.Warn("httpHandler failed with error %v", r) } }() // read out the http request req, err := conn.ReadRequest() if err != nil { conn.Warn("Failed to read valid http request: %v", err) conn.Write([]byte(BadRequest)) return } // multiplex to find the right backend host conn.Debug("Found hostname %s in request", req.Host) tunnel := tunnels.Get("http://" + req.Host) if tunnel == nil { conn.Info("No tunnel found for hostname %s", req.Host) conn.Write([]byte(fmt.Sprintf(NotFound, len(req.Host)+18, req.Host))) return } // satisfy auth, if necessary conn.Debug("From client: %s", req.Header.Get("Authorization")) conn.Debug("To match: %s", tunnel.regMsg.HttpAuth) if req.Header.Get("Authorization") != tunnel.regMsg.HttpAuth { conn.Info("Authentication failed") conn.Write([]byte(NotAuthorized)) return } tunnel.HandlePublicConnection(conn) }