ESP8266 - ESP01S with relay. Toggling the relay with http (GPIO0) and GPIO2 at t

I have an ESP8266 module with a relay like this: https://aliexpress.com/item/4000348370586.html.
I have been able to control the module, I can deactivate and activate the relay by means of an http request, with the following code.

    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>

    #ifndef STASSID
    #define STASSID "wifi_name"
    #define STAPSK  "wifi_password"
    #endif

    const char* ssid = STASSID;
    const char* password = STAPSK;

    ESP8266WebServer server(80);

    IPAddress ip(192, 168, 0, 101); //ESP static ip
    IPAddress gateway(192, 168, 0, 1);   //IP Address of your WiFi Router (Gateway)
    IPAddress subnet(255, 255, 255, 0);  //Subnet mask
    IPAddress dns(8, 8, 8, 8);  //DNS
    const char* deviceName = "ligth101";

    const int relayPin = 0;

    void handleOn() {
        digitalWrite(relayPin, LOW);
        setCrossOrigin();
        server.send(200, "text/plain", "Ligth on");
    }

    void handleOff() {
        digitalWrite(relayPin, HIGH);
        setCrossOrigin();
        server.send(200, "text/plain", "Ligth off");
    }

    void handlePing() {
        setCrossOrigin();
        server.send(200, "text/plain", "ligth");
    }

    void configPin(){
        pinMode(relayPin, OUTPUT);
        digitalWrite(relayPin, HIGH);
    }

    void configWifi(){
        WiFi.setAutoConnect(false);
        WiFi.disconnect();
        WiFi.hostname(deviceName);
        WiFi.config(ip, subnet, gateway, dns);
        WiFi.begin(ssid, password);    
        while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        }
    }

    void setCrossOrigin(){
        server.sendHeader(F("Access-Control-Allow-Origin"), F("*"));
        server.sendHeader(F("Access-Control-Max-Age"), F("600"));
        server.sendHeader(F("Access-Control-Allow-Methods"), F("PUT,POST,GET,OPTIONS"));
        server.sendHeader(F("Access-Control-Allow-Headers"), F("*"));
    }
    
    void sendCrossOriginHeader(){
        setCrossOrigin();
        server.send(204);
    }

    void configServerPaths(){
        server.on(F("/ping"), HTTP_OPTIONS, sendCrossOriginHeader);
        server.on(F("/ping"), HTTP_GET, handlePing);

        server.on(F("/on"), HTTP_OPTIONS, sendCrossOriginHeader);
        server.on(F("/on"), HTTP_GET, handleOn);

        server.on(F("/off"), HTTP_OPTIONS, sendCrossOriginHeader);
        server.on(F("/off"), HTTP_GET, handleOff);
        
        server.begin();
    }

    void setup() {
        configPin();    
        configWifi();
        configServerPaths();
    }

    void loop() {
        server.handleClient();
    }

Now, I want to use the GPIO2 pin to also turn the relay on and off. The desired behavior is to change the state of the relay regardless of whether it comes from the button or from an http request.

I have tried the following modifications to the code:

    const int buttonPin = 2;
    int buttonState = 0;
    
    void configPin(){
        ...
        digitalWrite(buttonPin, LOW);
    }
    
    void handleButton(){
        buttonState=digitalRead(buttonPin);
        if(buttonState == HIGH) {
            digitalWrite( relayPin, !digitalRead(relayPin) );
            delay(1000);
        } 
    }
    
    void loop() {
        server.handleClient();
        handleButton();
    }

With these modifications to the code, I have tested the following two modifications to the hardware:

  1. Placing a switch between ground and GPIO2. As a result of this, each time I activate the push-button, the relay remains intermittent, going from one state to the other infinitely.
  2. Placing a switch between ground and GPIO2, but adding a resistor between the switch and the GPIO2 pin, but this also does not work.

Is there a way to deactivate / activate the relay using GPIO2 with a push button and via http as well?

Thanks!