Repository: louislam/uptime-kuma
File: src/pages/EditMonitor.vue (Vue)

Code before:

            // Validate MQTT WebSocket Path pattern if present
            if (this.monitor.type === "mqtt" && this.monitor.mqttWebsocketPath) {
                const pattern = /^\/[A-Za-z0-9-_&()*+]*$/;
                if (!pattern.test(this.monitor.mqttWebsocketPath)) {
                    toast.error(this.$t("mqttWebsocketPathInvalid"));
                    return false;
                }
            }

            // Validate the DNS Monitor hostname input
            if (this.monitor.type === "dns" && this.monitor.hostname) {
                let hostname = this.monitor.hostname.trim();

                if (isIP(hostname)) {
                    toast.error("Hostname cannot be an IP address");
                    return false;
                }

                if (!isFQDN(hostname, {
                    allow_wildcard: true,
                    require_tld: false,
                    allow_underscores: true,
                    allow_trailing_dot: true,
                })) {
                    toast.error("Invalid hostname");
                    return false;
                }
            }

            // Validate URL field input
            if ((this.monitor.type === "http" || this.monitor.type === "keyword" || this.monitor.type === "json-query" || this.monitor.type === "websocket-upgrade" || this.monitor.type === "real-browser") && this.monitor.url) {
                try {
                    const url = new URL(this.monitor.url);
                    if (url.hostname.includes("*")) {
                        toast.error("Wildcard hostnames are only supported for DNS monitors.");
                        return false;
                    }
                    if (!isFQDN(url.hostname, {
                        require_tld: false,
                        allow_underscores: true,
                        allow_trailing_dot: true,
                    }) && !isIP(url.hostname)) {
                        toast.error("Invalid hostname");
                        return false;
                    }
                } catch (err) {
                    toast.error("Invalid URL");
                    return false;
                }
            }

Review comment (suggestion):
We can be more specific here

```suggestion
                    toast.error("Invalid hostname. Must be a FQDN, wildcard, underscore, or end with a dot.");
```

Code after:
                const pattern = /^\/[A-Za-z0-9-_&()*+]*$/;
                if (!pattern.test(this.monitor.mqttWebsocketPath)) {
                    toast.error(this.$t("mqttWebsocketPathInvalid"));
                    return false;
                }
            }

            // Validate hostname field input for various monitors
            if ([ "mqtt", "dns", "port", "ping", "steam", "gamedig", "radius", "tailscale-ping", "smtp", "snmp" ].includes(this.monitor.type) && this.monitor.hostname) {
                let hostname = this.monitor.hostname.trim();

                if (this.monitor.type === "mqtt") {
                    hostname = hostname.replace(/^(mqtt|ws)s?:\/\//, "");
                }

                if (this.monitor.type === "dns" && isIP(hostname)) {
                    toast.error(this.$t("hostnameCannotBeIP"));
                    return false;
                }

                // Wildcard is allowed only for DNS
                if (!isFQDN(hostname, {
                    allow_wildcard: this.monitor.type === "dns",
                    require_tld: false,
                    allow_underscores: true,
                    allow_trailing_dot: true,
                }) && !isIP(hostname)) {
                    if (this.monitor.type === "dns") {
                        toast.error(this.$t("invalidDNSHostname"));
                    } else {
                        toast.error(this.$t("invalidHostnameOrIP"));
                    }
                    return false;
                }
            }

            // Validate URL field input for various monitors
            if ([ "http", "keyword", "json-query", "websocket-upgrade", "real-browser" ].includes(this.monitor.type) && this.monitor.url) {
                try {
                    const url = new URL(this.monitor.url);
                    // Browser can encode *.hostname.com to %2A.hostname.com
                    if (url.hostname.includes("*") || url.hostname.includes("%2A")) {
                        toast.error(this.$t("wildcardOnlyForDNS"));
                        return false;
                    }
                    if (!isFQDN(url.hostname, {
                        require_tld: false,
                        allow_underscores: true,
                        allow_trailing_dot: true,
                    }) && !isIP(url.hostname)) {
                        toast.error(this.$t("invalidHostnameOrIP"));