Jak rozwiązać błąd HTTP 414 „Za długi identyfikator URI żądania”?

103

Stworzyłem aplikację internetową w języku PHP. Daję użytkownikowi możliwość aktualizacji wielu problemów za jednym razem. Robiąc to, czasami użytkownik napotyka ten błąd. Czy istnieje sposób na zwiększenie długości adresu URL w Apache?

JPro
źródło
Jeśli widzisz ten błąd na serwerze Windows i / lub w aplikacji IIS / ASP.NET, zobacz pytanie: stackoverflow.com/q/23237538/12484
Jon Schneider

Odpowiedzi:

166

Pod Apache, limit jest wartością konfigurowalny LimitRequestLine. Zmień tę wartość na większą niż domyślna 8190, jeśli chcesz obsługiwać dłuższy identyfikator URI żądania. Wartość znajduje się w /etc/apache2/apache2.conf . Jeśli nie, dodaj nową linię ( LimitRequestLine 10000) pod AccessFileName .htaccess.

Pamiętaj jednak, że jeśli faktycznie osiągasz ten limit, prawdopodobnie GETna początku nadużywasz . Powinieneś używać POSTdo przesyłania tego rodzaju danych - zwłaszcza, że ​​nawet przyznajesz, że używasz ich do aktualizowania wartości. Jeśli zaznaczysz powyższy link, zauważysz, że Apache mówi nawet „W normalnych warunkach wartość nie powinna być zmieniana z domyślnej”.

John Feminella
źródło
Na początku próbowałem użyć POST, ale jest to operacja aktualizacji bazy danych i odświeżam oryginalną stronę przy użyciu wartości, które zostały pierwotnie opublikowane na tej stronie.
JPro
8
JPro: Aktualizacja bazy danych jest mniej więcej dokładnym powodem, dla którego byś użył POST. Nic w używaniu POST nie wyklucza wypełnienia tego samego formularza polami, które właśnie zostały wysłane, więc nie jestem pewien, co przez to rozumiesz.
John Feminella
1
@JPro: Zwykłą techniką w tym przypadku jest POST na tej samej stronie. Procedura obsługi strony (która może być tym samym kodem zarówno dla GET, jak i POST) najpierw sprawdza parametry POST, obsługuje je, jeśli je znajdzie, a następnie zwraca stronę z wypełnionymi odpowiednimi wartościami, które będą albo zaktualizowanymi wartościami ( jeśli POST i aktualizacja powiedzie się) lub oryginalne wartości (jeśli GET lub POST i aktualizacja się nie powiedzie). Jeśli aktualizacja się nie powiedzie, możesz nawet wyświetlić komunikaty o błędach dla poszczególnych pól opisujące awarię.
Mike DeSimone
5
Zrozumiałem to dość późno, więc chciałbym się tym podzielić. Jeśli nie możesz znaleźć tego słowa LimitRequestLinew swoim pliku httpd.conf, po prostu dodaj tę linię w dowolnym miejscu. Na przykład:LimitRequestLine 100000
Jules Colle
dzięki za odpowiedź i wyjaśnienie, uratowałeś mi dzień. :)
saghira
16

Na podstawie odpowiedzi Johna zmieniłem żądanie GET na żądanie POST. Działa bez konieczności zmiany konfiguracji serwera. Zacząłem więc szukać, jak to zaimplementować. Pomocne były następujące strony:

Przykład jQuery Ajax POST z PHP (zwróć uwagę na uwagę dotyczącą czyszczenia opublikowanych danych) i

http://www.openjs.com/articles/ajax_xmlhttp_using_post.php

Zasadniczo różnica polega na tym, że żądanie GET ma adres URL i parametry w jednym ciągu, a następnie wysyła wartość null:

http.open("GET", url+"?"+params, true);
http.send(null);

podczas gdy żądanie POST wysyła adres URL i parametry w oddzielnych poleceniach:

http.open("POST", url, true);
http.send(params);

Oto działający przykład:

ajaxPOST.html:

<html>
<head>
<script type="text/javascript">
    function ajaxPOSTTest() {
        try {
            // Opera 8.0+, Firefox, Safari
            ajaxPOSTTestRequest = new XMLHttpRequest();
        } catch (e) {
            // Internet Explorer Browsers
            try {
                ajaxPOSTTestRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    ajaxPOSTTestRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
                    // Something went wrong
                    alert("Your browser broke!");
                    return false;
                }
            }
        }

        ajaxPOSTTestRequest.onreadystatechange = ajaxCalled_POSTTest;
        var url = "ajaxPOST.php";
        var params = "lorem=ipsum&name=binny";
        ajaxPOSTTestRequest.open("POST", url, true);
        ajaxPOSTTestRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        ajaxPOSTTestRequest.send(params);
    }

    //Create a function that will receive data sent from the server
    function ajaxCalled_POSTTest() {
        if (ajaxPOSTTestRequest.readyState == 4) {
            document.getElementById("output").innerHTML = ajaxPOSTTestRequest.responseText;
        }
    }
</script>

</head>
<body>
    <button onclick="ajaxPOSTTest()">ajax POST Test</button>
    <div id="output"></div>
</body>
</html>

ajaxPOST.php:

<?php

$lorem=$_POST['lorem'];
print $lorem.'<br>';

?>

Właśnie wysłałem ponad 12 000 znaków bez żadnych problemów.

atmelino
źródło
4

Mam proste obejście.

Załóżmy, że Twój identyfikator URI zawiera stringdatazbyt długi ciąg . Możesz po prostu podzielić go na kilka części w zależności od ograniczeń serwera. Następnie prześlij pierwszy, w moim przypadku do napisania pliku. Następnie prześlij kolejne, aby dołączyć do wcześniej dodanych danych.

Shrey Gupta
źródło
Czy możesz podać przykład? Widzę, jak dzielisz ciąg, gdy jest on wygenerowany przez użytkownika ...
endyourif
4
Bardzo tanie obejście. Lepiej przemyśleć problem domeny!
Muhammad Hewedy
13
To nie zasługuje na tak wiele głosów przeciw. Z pewnością istnieją sytuacje, w których przesłanie wielu wniosków może być akceptowalnym obejściem. To prawda, że ​​jakość odpowiedzi jest nieco niska, ale można się tego spodziewać po zupełnie nowym użytkowniku SO. Okażmy trochę miłości i podzielmy się opiniami, zamiast po prostu odrzucać głosy nowo przybyłych, którzy jeszcze nie dostali TAK!
rinogo
1
Zgadzam się, wygląda to na wykonalne
Felipe Valdes
3

Otrzymałem ten błąd po użyciu $ .getJSON () z JQuery. Właśnie zmieniłem post:

data = getDataObjectByForm(form);
var jqxhr = $.post(url, data, function(){}, 'json')
    .done(function (response) {
        if (response instanceof Object)
            var json = response;
        else
            var json = $.parseJSON(response);
        // console.log(response);
        // console.log(json);
        jsonToDom(json);
        if (json.reload != undefined && json.reload)
            location.reload();
        $("body").delay(1000).css("cursor", "default");
    })
    .fail(function (jqxhr, textStatus, error) {
        var err = textStatus + ", " + error;
        console.log("Request Failed: " + err);
        alert("Fehler!");
    });
Oprogramowanie Fusca
źródło
2
czy to jest odpowiedź czy pytanie?
Takarii
To dobre szybkie rozwiązanie. Zmiana z get na post pozwala na długi URL bez jakiejkolwiek zmiany konfiguracji serwera.
mt025
1

Fragment dokumentu RFC 2616: Hypertext Transfer Protocol - HTTP / 1.1 :

Metoda POST służy do żądania, aby serwer pochodzenia zaakceptował jednostkę zawartą w żądaniu jako nowego podwładnego zasobu określonego przez identyfikator żądania w wierszu żądania. POST został zaprojektowany, aby umożliwić jednolitą metodę obejmującą następujące funkcje:

  • Opis istniejących zasobów;
  • Wysyłanie wiadomości do tablicy ogłoszeń, grupy dyskusyjnej, listy mailingowej lub podobnej grupy artykułów;
  • Udostępnienie bloku danych, np. Wynikającego z przesłania formularza, do procesu obsługi danych ;
  • Rozszerzanie bazy danych poprzez operację dołączania.
Twój zdrowy rozsądek
źródło
8
Nie widząc, jak to odpowiada na pytanie…?
kwiecień
Oryginalny plakat informował, że zapisy są aktualizowane. W przypadku aktualizacji dobrą praktyką jest użycie POST lub PUT, a nie GET. Ale oczywiście może się zdarzyć, że maksymalny limit adresu URL zostanie przekroczony podczas pobierania rekordów do wyświetlenia przed aktualizacją, a następnie metoda GET jest odpowiednia, ale może się nie powieść z powodu tego limitu. Oryginalny plakat nie wspomniał, na jakim etapie pojawia się problem, więc można przypuszczać, że był on podczas samej aktualizacji, ale nie mamy pewności ...
JustAMartin