javascript - type - w3schools jquery ajax get




Come gestire una richiesta di reindirizzamento dopo una chiamata Ajax jQuery (20)

Alcuni potrebbero trovare il sotto utile:

Volevo che i client venissero reindirizzati alla pagina di login per ogni rest-action che viene inviata senza un token di autorizzazione. Poiché tutte le mie rest-action sono basate su Ajax, avevo bisogno di un buon modo generico per reindirizzare alla pagina di login invece di gestire la funzione di successo Ajax.

Questo è quello che ho fatto:

Su qualsiasi richiesta Ajax, il mio server restituirà una risposta JSON 200 "NECESSITÀ DI AUTENTICARE" (se il client deve autenticarsi).

Semplice esempio in Java (lato server):

@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class);

    public static final String COOKIE_NAME = "token_cookie"; 

    @Override
    public void filter(ContainerRequestContext context) throws IOException {        
        // Check if it has a cookie.
        try {
            Map<String, Cookie> cookies = context.getCookies();

            if (!cookies.containsKey(COOKIE_NAME)) {
                m_logger.debug("No cookie set - redirect to login page");
                throw new AuthenticationException();
            }
        }
        catch (AuthenticationException e) {
            context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build());
        }
    }
}

Nel mio Javascript ho aggiunto il seguente codice:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    var originalSuccess = options.success;

    options.success = function(data) {
        if (data == "NEED TO AUTHENTICATE") {
            window.location.replace("/login.html");
        }
        else {
            originalSuccess(data);
        }
    };      
});

E questo è tutto.

Sto usando $.post() per chiamare un servlet usando Ajax e quindi usando il frammento HTML risultante per sostituire un elemento div nella pagina corrente dell'utente. Tuttavia, se la sessione scade, il server invia una direttiva di reindirizzamento per inviare l'utente alla pagina di accesso. In questo caso, jQuery sostituisce l'elemento div con i contenuti della pagina di accesso, costringendo gli occhi dell'utente a testimoniare una scena rara.

Come posso gestire una direttiva di reindirizzamento da una chiamata Ajax con jQuery 1.2.6?


Ho letto questa domanda e ho implementato l'approccio che è stato indicato per l'impostazione del codice di stato della risposta su 278 per evitare che il browser gestisca in modo trasparente i reindirizzamenti. Anche se questo ha funzionato, ero un po 'insoddisfatto in quanto è un po' un trucco.

Dopo aver scavato di più, ho abbandonato questo approccio e ho usato JSON . In questo caso, tutte le risposte alle richieste Ajax hanno il codice di stato 200 e il corpo della risposta contiene un oggetto JSON costruito sul server. Il javascript sul client può quindi utilizzare l'oggetto JSON per decidere cosa deve fare.

Ho avuto un problema simile al tuo. Eseguo una richiesta Ajax che ha 2 possibili risposte: una che reindirizza il browser a una nuova pagina e una che sostituisce un modulo HTML esistente nella pagina corrente con una nuova. Il codice jquery per fare ciò assomiglia a qualcosa:

$.ajax({
    type: "POST",
    url: reqUrl,
    data: reqBody,
    dataType: "json",
    success: function(data, textStatus) {
        if (data.redirect) {
            // data.redirect contains the string URL to redirect to
            window.location.href = data.redirect;
        }
        else {
            // data.form contains the HTML for the replacement form
            $("#myform").replaceWith(data.form);
        }
    }
});

L'oggetto JSON "data" è costruito sul server per avere 2 membri: data.redirect e data.form. Ho trovato questo approccio molto migliore.


Ho risolto questo problema con:

  1. Aggiunta di un'intestazione personalizzata alla risposta:

    public ActionResult Index(){
        if (!HttpContext.User.Identity.IsAuthenticated)
        {
            HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
        }
        return View();
    }
    
  2. ajaxSuccess una funzione JavaScript all'evento ajaxSuccess e verifica se l'intestazione esiste:

    $(document).ajaxSuccess(function(event, request, settings) {
        if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
           window.location = '/';
        }
    });
    

Ho risolto questo problema in questo modo:

Aggiungere un middleware per elaborare la risposta, se si tratta di un reindirizzamento per una richiesta Ajax, modificare la risposta a una risposta normale con l'url di reindirizzamento.

class AjaxRedirect(object):
  def process_response(self, request, response):
    if request.is_ajax():
      if type(response) == HttpResponseRedirect:
        r = HttpResponse(json.dumps({'redirect': response['Location']}))
        return r
    return response

Quindi, in ajaxComplete, se la risposta contiene reindirizzamento, deve essere un reindirizzamento, quindi modificare la posizione del browser.

$('body').ajaxComplete(function (e, xhr, settings) {
   if (xhr.status == 200) {
       var redirect = null;
       try {
           redirect = $.parseJSON(xhr.responseText).redirect;
           if (redirect) {
               window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
           }
       } catch (e) {
           return;
       }
   }
}

La maggior parte delle soluzioni fornite utilizza una soluzione alternativa, utilizzando un'intestazione aggiuntiva o un codice HTTP inappropriato. Queste soluzioni funzioneranno molto probabilmente, ma si sentiranno un po '"hacky". Ho trovato un'altra soluzione.

Stiamo usando WIF che è configurato per il reindirizzamento (passiveRedirectEnabled = "true") su una risposta 401. Il reindirizzamento è utile quando si gestiscono le richieste normali ma non funzionerà per le richieste AJAX (poiché i browser non eseguiranno il 302 / reindirizzamento).

Usando il seguente codice nel tuo global.asax puoi disabilitare il reindirizzamento per le richieste AJAX:

    void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
    {
        string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"];

        if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase))
        {
            e.RedirectToIdentityProvider = false;
        }
    }

Ciò ti consente di restituire 401 risposte per richieste AJAX, che il tuo javascript può gestire ricaricando la pagina. Ricaricare la pagina genererà un 401 che sarà gestito da WIF (e WIF reindirizzerà l'utente alla pagina di login).

Un esempio di javascript per gestire gli errori 401:

$(document).ajaxError(function (event, jqxhr, settings, exception) {

    if (jqxhr.status == 401) { //Forbidden, go to login
        //Use a reload, WIF will redirect to Login
        location.reload(true);
    }
});

La soluzione che è stata infine implementata era quella di utilizzare un wrapper per la funzione di callback della chiamata Ajax e in questo wrapper verificare l'esistenza di un elemento specifico sul blocco HTML restituito. Se l'elemento è stato trovato, il wrapper eseguiva un reindirizzamento. In caso contrario, il wrapper ha inoltrato la chiamata alla funzione di callback effettiva.

Ad esempio, la nostra funzione wrapper era qualcosa del tipo:

function cbWrapper(data, funct){
    if($("#myForm", data).length > 0)
        top.location.href="login.htm";//redirection
    else
        funct(data);
}

Quindi, durante la chiamata Ajax, abbiamo usato qualcosa come:

$.post("myAjaxHandler", 
       {
        param1: foo,
        param2: bar
       },
       function(data){
           cbWrapper(data, myActualCB);
       }, 
       "html"
);

Questo ha funzionato per noi perché tutte le chiamate Ajax hanno sempre restituito l'HTML all'interno di un elemento DIV che usiamo per sostituire un pezzo della pagina. Inoltre, abbiamo solo bisogno di reindirizzare alla pagina di accesso.


Mettendo insieme ciò che hanno detto Vladimir Prudnikov e Thomas Hansen:

  • Cambia il tuo codice lato server per rilevare se si tratta di un XHR. Se lo è, imposta il codice di risposta del reindirizzamento su 278. In django:
   if request.is_ajax():
      response.status_code = 278

Questo fa sì che il browser tratti la risposta come un successo e la consegna al tuo Javascript.

  • Nel tuo JS, assicurati che l'invio del modulo sia tramite Ajax, controlla il codice di risposta e reindirizza se necessario:
$('#my-form').submit(function(event){ 

  event.preventDefault();   
  var options = {
    url: $(this).attr('action'),
    type: 'POST',
    complete: function(response, textStatus) {    
      if (response.status == 278) { 
        window.location = response.getResponseHeader('Location')
      }
      else { ... your code here ... } 
    },
    data: $(this).serialize(),   
  };   
  $.ajax(options); 
});

Mi piace il metodo di Timmerz con un leggero tocco di limone. Se vieni restituito contentType di text / html quando sei in attesa di JSON , molto probabilmente verrai reindirizzato. Nel mio caso, semplicemente ricarico la pagina e viene reindirizzato alla pagina di accesso. Oh, e controlla che lo stato di jqXHR sia 200, il che sembra sciocco, perché sei nella funzione di errore, giusto? In caso contrario, i casi di errore legittimi imporranno un ricaricamento iterativo (oops)

$.ajax(
   error:  function (jqXHR, timeout, message) {
    var contentType = jqXHR.getResponseHeader("Content-Type");
    if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) {
        // assume that our login has expired - reload our current page
        window.location.reload();
    }

});

Penso che un modo migliore per gestire questo è quello di sfruttare i codici di risposta del protocollo HTTP esistente, in particolare 401 Unauthorized .

Ecco come l'ho risolto:

  1. Lato server: se la sessione scade e la richiesta è ajax. inviare un'intestazione del codice di risposta 401
  2. Lato client: legatura agli eventi Ajax

    $('body').bind('ajaxSuccess',function(event,request,settings){
    if (401 == request.status){
        window.location = '/users/login';
    }
    }).bind('ajaxError',function(event,request,settings){
    if (401 == request.status){
        window.location = '/users/login';
    }
    });
    

IMO questo è più generico e non stai scrivendo qualche nuova specifica / intestazione personalizzata. Inoltre, non dovresti modificare alcuna delle tue chiamate Ajax esistenti.

Modifica: Per il commento di Rob di seguito, 401 (il codice di stato HTTP per gli errori di autenticazione) dovrebbe essere l'indicatore. Vedi 403 Forbidden vs 401 Le risposte HTTP non autorizzate per maggiori dettagli. Detto questo, alcuni framework web utilizzano il 403 per entrambi gli errori di autenticazione e autorizzazione, quindi adattati di conseguenza. Grazie Rob.


Provare

    $(document).ready(function () {
        if ($("#site").length > 0) {
            window.location = "<%= Url.Content("~") %>" + "Login/LogOn";
        }
    });

Mettilo nella pagina di accesso. Se è stato caricato in un div sulla pagina principale, verrà reindirizzato alla pagina di accesso. "#site" è un ID di un div che si trova su tutte le pagine ad eccezione della pagina di accesso.


Sebbene le risposte sembrino funzionare per le persone se si sta utilizzando Spring Security, ho trovato l'estensione di LoginUrlAuthenticationEntryPoint e l'aggiunta di codice specifico per gestire AJAX più robusto. La maggior parte degli esempi intercetta tutti i reindirizzamenti, non solo quelli di autenticazione. Questo non era auspicabile per il progetto su cui lavoro. È possibile che sia necessario estendere ExceptionTranslationFilter e sovrascrivere il metodo "sendStartAuthentication" per rimuovere il passaggio di memorizzazione nella cache se non si desidera memorizzare la richiesta AJAX memorizzata nella cache.

Esempio AjaxAwareAuthenticationEntryPoint:

public class AjaxAwareAuthenticationEntryPoint extends
    LoginUrlAuthenticationEntryPoint {

    public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
        super(loginUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        if (isAjax(request)) {
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself");
        } else {
        super.commence(request, response, authException);
        }
    }

    public static boolean isAjax(HttpServletRequest request) {
        return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
}

Fonti: 1 , 2


So che questo argomento è vecchio, ma darò un altro approccio che ho trovato e precedentemente descritto here . Fondamentalmente sto usando ASP.MVC con WIF (ma questo non è molto importante per il contesto di questo argomento - la risposta è adeguata indipendentemente dal framework utilizzato. L'indizio rimane invariato, trattando i problemi relativi agli errori di autenticazione durante l'esecuzione delle richieste Ajax ) .

L'approccio mostrato di seguito può essere applicato a tutte le richieste ajax out of the box (se non ridefiniscono ovviamente l'evento beforeSend).

$.ajaxSetup({
    beforeSend: checkPulse,
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        document.open();
        document.write(XMLHttpRequest.responseText);
        document.close();
    }
});

Prima di ogni richiesta CheckPulse viene eseguito il metodo CheckPulse (il metodo controller che può essere qualsiasi cosa più semplice):

[Authorize]
public virtual void CheckPulse() {}

Se l'utente non è autenticato (il token è scaduto) non è possibile accedere a tale metodo (protetto da attributo Authorize ). Poiché il framework gestisce l'autenticazione, mentre il token scade, inserisce lo stato http 302 nella risposta. Se non si desidera che il browser gestisca in modo trasparente la risposta 302, acquisirla in Global.asax e modificare lo stato della risposta, ad esempio 200 OK. Inoltre, aggiungi l'intestazione, che ti indica di elaborare tale risposta in modo speciale (più avanti sul lato client):

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302
        && (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
    {                
        Context.Response.StatusCode = 200;
        Context.Response.AddHeader("REQUIRES_AUTH", "1");
    }
}

Infine, dal lato client, controlla l'intestazione personalizzata. Se presente, deve essere eseguito il reindirizzamento completo alla pagina di accesso (nel mio caso window.location viene sostituito window.location dalla richiesta che viene gestito automaticamente dal mio framework).

function checkPulse(XMLHttpRequest) {
    var location = window.location.href;
    $.ajax({
        url: "/Controller/CheckPulse",
        type: 'GET',
        async: false,
        beforeSend: null,
        success:
            function (result, textStatus, xhr) {
                if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
                    XMLHttpRequest.abort(); // terminate further ajax execution
                    window.location = location;
                }
            }
    });
}

Utilizza la chiamata $.ajax() basso livello:

$.ajax({
  url: "/yourservlet",
  data: { },
  complete: function(xmlHttp) {
    // xmlHttp is a XMLHttpRquest object
    alert(xmlHttp.status);
  }
});

Prova questo per un reindirizzamento:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}

Volevo solo aggrapparmi a qualsiasi richiesta di ajax per l'intera pagina. @SuperG mi ha fatto iniziare. Ecco cosa ho finito con:

// redirect ajax requests that are redirected, not found (404), or forbidden (403.)
$('body').bind('ajaxComplete', function(event,request,settings){
        switch(request.status) {
            case 301: case 404: case 403:                    
                window.location.replace("http://mysite.tld/login");
                break;
        }
});

Volevo verificare in particolare determinati codici di stato http per basare la mia decisione su. Tuttavia, puoi semplicemente associare a ajaxError per ottenere qualcosa di diverso dal successo (solo 200 forse?) Potrei aver appena scritto:

$('body').bind('ajaxError', function(event,request,settings){
    window.location.replace("http://mysite.tld/login");
}

nel servlet dovresti inserire response.setStatus(response.SC_MOVED_PERMANENTLY); per inviare lo stato xmlHttp '301' di cui hai bisogno per un reindirizzamento ...

e nella funzione $ .ajax non dovresti usare la funzione .toString() ..., giusto

if (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }

il problema è che non è molto flessibile, non puoi decidere dove vuoi reindirizzare ..

il reindirizzamento attraverso i servlet dovrebbe essere il modo migliore. ma non riesco ancora a trovare il modo giusto per farlo.


Se vuoi anche passare i valori, puoi anche impostare le variabili di sessione e accedere ad Eg: Nel tuo jsp puoi scrivere

<% HttpSession ses = request.getSession(true);
   String temp=request.getAttribute("what_you_defined"); %>

E poi puoi memorizzare questo valore temporaneo nella tua variabile javascript e giocare


Ho ottenuto un solulion di lavoro utilizzando le risposte da @ John e @Arpad .com/a/8426947/4505142 e @RobWinch link

Io uso Spring Security 3.2.9 e jQuery 1.10.2.

Estendi la classe di Spring per causare la risposta 4XX solo dalle richieste AJAX:

public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {

    public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) {
        super(loginFormUrl);
    }

    // For AJAX requests for user that isn't logged in, need to return 403 status.
    // For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally.
    @Override
    public void commence(final HttpServletRequest request,
                         final HttpServletResponse response,
                         final AuthenticationException authException)
            throws IOException, ServletException {
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
        } else {
            super.commence(request, response, authException);
        }
    }
}

applicationContext-security.xml

  <security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" >
    <security:form-login login-page='/login.jsp' default-target-url='/index.jsp'                             
                         authentication-failure-url="/login.jsp?error=true"
                         />    
    <security:access-denied-handler error-page="/errorPage.jsp"/> 
    <security:logout logout-success-url="/login.jsp?logout" />
...
    <bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton">
        <constructor-arg value="/login.jsp" />
    </bean>
...
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    <property name="requestMatcher">
      <bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
        <constructor-arg>
          <bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher">
            <constructor-arg>
              <bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/>
            </constructor-arg>
            <constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/>
            <property name="useEquals" value="true"/>
          </bean>
        </constructor-arg>
      </bean>
    </property>
</bean>

Nei miei JSP, aggiungi un gestore di errori AJAX globale come mostrato here

  $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
      if ( jqxhr.status === 403 ) {
          window.location = "login.jsp";
      } else {
          if(thrownError != null) {
              alert(thrownError);
          } else {
              alert("error");
          }
      }
  });

Inoltre, rimuovi i gestori di errori esistenti dalle chiamate AJAX nelle pagine JSP:

        var str = $("#viewForm").serialize();
        $.ajax({
            url: "get_mongoDB_doc_versions.do",
            type: "post",
            data: str,
            cache: false,
            async: false,
            dataType: "json",
            success: function(data) { ... },
//            error: function (jqXHR, textStatus, errorStr) {
//                 if(textStatus != null)
//                     alert(textStatus);
//                 else if(errorStr != null)
//                     alert(errorStr);
//                 else
//                     alert("error");
//            }
        });

Spero che aiuti gli altri.

Update1 Ho scoperto che avevo bisogno di aggiungere l'opzione (always-use-default-target = "true") alla configurazione di login form. Ciò era necessario poiché dopo che una richiesta AJAX viene reindirizzata alla pagina di accesso (a causa della sessione scaduta), Spring ricorda la precedente richiesta AJAX e reindirizza automaticamente ad essa dopo l'accesso. Ciò fa sì che il JSON restituito venga visualizzato nella pagina del browser. Certo, non quello che voglio.

Update2 Invece di usare always-use-default-target="true", usa @RobWinch esempio di blocco delle richieste AJAX da requstCache. Ciò consente ai collegamenti normali di essere reindirizzati al loro target originale dopo il login, ma AJAX va alla home page dopo il login.


Infine, risolvo il problema aggiungendo un'abitudine HTTP Header. Appena prima della risposta per ogni richiesta sul lato server, aggiungo l'url richiesto corrente all'intestazione della risposta.

Il mio tipo di applicazione sul server è Asp.Net MVC, e ha un buon posto per farlo. in Global.asaxho implementato l' Application_EndRequestevento così:

    public class MvcApplication : System.Web.HttpApplication
    {

    //  ...
    //  ...

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            var app = (HttpApplication)sender;
            app.Context.Response.Headers.Add("CurrentUrl",app.Context. Request.CurrentExecutionFilePath);
        }

    }

Funziona perfettamente per me! Ora, in ogni risposta della JQuery $.postho la richiesta urle anche altri intestazioni di risposta, che si presenta come risultato di POSTmetodo in base allo stato 302, 303, ....

e altra cosa importante è che non è necessario modificare il codice lato server o lato client.

e la prossima è la possibilità di ottenere l'accesso alle altre informazioni di post azione come errori, messaggi e ..., In questo modo.

Ho postato questo, forse aiutare qualcuno :)


Non ho avuto alcun successo con la soluzione di intestazione - non sono mai stati rilevati nel mio metodo ajaxSuccess / ajaxComplete. Ho usato la risposta di Steg con la risposta personalizzata, ma ho modificato il lato JS. Ho impostato un metodo che chiamo in ciascuna funzione in modo da poter utilizzare standard $.gete $.postmetodi.

function handleAjaxResponse(data, callback) {
    //Try to convert and parse object
    try {
        if (jQuery.type(data) === "string") {
            data = jQuery.parseJSON(data);
        }
        if (data.error) {
            if (data.error == 'login') {
                window.location.reload();
                return;
            }
            else if (data.error.length > 0) {
                alert(data.error);
                return;
            }
        }
    }
    catch(ex) { }

    if (callback) {
        callback(data);
    }
}

Esempio in uso ...

function submitAjaxForm(form, url, action) {
    //Lock form
    form.find('.ajax-submit').hide();
    form.find('.loader').show();

    $.post(url, form.serialize(), function (d) {
        //Unlock form
        form.find('.ajax-submit').show();
        form.find('.loader').hide();

        handleAjaxResponse(d, function (data) {
            // ... more code for if auth passes ...
        });
    });
    return false;
}

Stavo avendo questo problema su un'app django con cui sto armeggiando (disclaimer: sto armeggiando per imparare, e non sono affatto un esperto). Quello che volevo fare era usare jQuery ajax per inviare una richiesta DELETE a una risorsa, cancellarla sul lato server, quindi inviare un reindirizzamento a (fondamentalmente) la homepage. Quando ho inviato HttpResponseRedirect('/the-redirect/')lo script python, il metodo ajax di jQuery stava ricevendo 200 invece di 302. Quindi, quello che ho fatto è stato inviare una risposta di 300 con:

response = HttpResponse(status='300')
response['Location'] = '/the-redirect/' 
return  response

Quindi ho inviato / gestito la richiesta sul client con jQuery.ajax in questo modo:

<button onclick="*the-jquery*">Delete</button>

where *the-jquery* =
$.ajax({ 
  type: 'DELETE', 
  url: '/resource-url/', 
  complete: function(jqxhr){ 
    window.location = jqxhr.getResponseHeader('Location'); 
  } 
});

Forse usare 300 non è "giusto", ma almeno ha funzionato esattamente come volevo.

PS: questo è stato un enorme dolore da modificare nella versione mobile di SO. Stupid ISP ha inoltrato la mia richiesta di cancellazione del servizio a destra quando ho finito con la mia risposta!





redirect