code: func wsHandshakeValidator(allowedOrigins []string) func(*websocket.Config, *http.Request) error {
  	origins := mapset.NewSet()
  	allowAllOrigins := false
  
  	for _, origin := range allowedOrigins {
  		if origin == "*" {
  			allowAllOrigins = true
  		}
  		if origin != "" {
  			origins.Add(strings.ToLower(origin))
  		}
  	}
  
  	// allow localhost if no allowedOrigins are specified.
  	if len(origins.ToSlice()) == 0 {
  		origins.Add("http://localhost")
  		if hostname, err := os.Hostname(); err == nil {
  			origins.Add("http://" + strings.ToLower(hostname))
  		}
  	}
  
  	log.Debug(fmt.Sprintf("Allowed origin(s) for WS RPC interface %v", origins.ToSlice()))
  
  	f := func(cfg *websocket.Config, req *http.Request) error {
  		// Skip origin verification if no Origin header is present. The origin check
  		// is supposed to protect against browser based attacks. Browsers always set
  		// Origin. Non-browser software can put anything in origin and checking it doesn't
  		// provide additional security.
  		if _, ok := req.Header["Origin"]; !ok {
  			return nil
  		}
  		// Verify origin against whitelist.
  		origin := strings.ToLower(req.Header.Get("Origin"))
  		if allowAllOrigins || origins.Contains(origin) {
  			return nil
  		}
  		log.Warn("Rejected WebSocket connection", "origin", origin)
  		return errors.New("origin not allowed")
  	}
  
  	return f
  }
docs: // wsHandshakeValidator returns a handler that verifies the origin during the
  // websocket upgrade process. When a '*' is specified as an allowed origins all
  // connections are accepted.