Wyłącz całą domyślną zawartość odpowiedzi na błędy HTTP w programie Tomcat

Domyślnie Tomcat wysyła część zawartości HTML z powrotem do Klienta, jeśli napotka coś w rodzaju HTTP 404. Wiem, że via web.xml an <error-page> można skonfigurować , aby dostosować tę zawartość.

Jednak po prostu chciałbym, aby Tomcat nie wysyłał niczego pod względem treści odpowiedzi(oczywiście nadal chciałbym kod statusu). Czy jest jakiś sposób, aby łatwo to skonfigurować?

Staram się uniknąć a) jawnego wysyłania pustej treści w strumieniu odpowiedzi z mojego Servlet, oraz B) konfigurowanie własnych stron błędów dla całej gamy statusów błędów HTTP w moim web.xml.

Dla jakiegoś tła, rozwijam HTTP API i kontroluję własną treść odpowiedzi. Tak więc dla HTTP 500, na przykład, wypełniam pewną zawartość XML w odpowiedzi zawierającej informacje o błędzie. W sytuacjach takich jak HTTP 404, status odpowiedzi HTTP jest wystarczający dla klientów, a wysyłana przez tomcat zawartość jest niepotrzebna. Jeśli jest inne podejście, jestem otwarty na słysząc to.

Edit: Po dalszym śledztwie nadal nie mogę znaleźć wiele na drodze do rozwiązania. Jeśli ktoś może definitywnie powiedzieć, że nie jest to możliwe, lub dostarczyć zasób z dowodami, że to nie zadziała, zaakceptuję to jako odpowiedź i spróbuję obejść to.

Author: Rob Hruska, 2009-04-27

7 answers

Jeśli nie chcesz, aby tomcat wyświetlał stronę błędu, nie używaj sendError(...). Zamiast tego użyj setStatus(...).

Np. jeśli chcesz dać odpowiedź 405, to zrób

response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);      
response.getWriter().println("The method " + request.getMethod() + 
   " is not supported by this service.");

Pamiętaj również, aby nie wyrzucać żadnych WYJĄTKÓW z twojego servletu. Zamiast tego Złap wyjątek i ponownie ustaw statusCode your self.

Tzn.

protected void service(HttpServletRequest request,
      HttpServletResponse response) throws IOException {
  try {

    // servlet code here, e.g. super.service(request, response);

  } catch (Exception e) {
    // log the error with a timestamp, show the timestamp to the user
    long now = System.currentTimeMillis();
    log("Exception " + now, e);
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    response.getWriter().println("Guru meditation: " + now);
  }
}

Oczywiście, jeśli nie chcesz żadnej treści, to po prostu nie pisz nic do pisarza, po prostu ustaw status.

 42
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-20 14:06:41

Chociaż to nie odpowiada dokładnie na stwierdzenie "nie wysyłaj niczego" na pytanie, a na fali odpowiedzi Clive ' a Evansa , dowiedziałem się, że w tomcat możesz sprawić, że te zbyt obszerne teksty znikną ze stron błędów bez tworzenia niestandardowego ErrorReportValve.

Możesz wykonać ten dostosowujący ErrorReportValve poprzez param 2 "showReport" i " showServerInfo "na twoim serwerze.xml": {]}

<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />

Link do oficjalnego dokumentacja .

Pracował dla mnie na tomcat 7.0.55, nie pracował dla mnie na tomcat 7.0.47 (myślę, że z powodu czegoś zgłoszonego na poniższym linku http://www.mail-archive.com/[email protected]/msg113856.html )

 34
Author: reallynice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:29

Szybkim, nieco brudnym, ale łatwym sposobem powstrzymania Tomcat przed wysyłaniem jakichkolwiek błędów jest wywołanie setErrorReportValveClass przeciwko hostowi tomcat, z niestandardowym zaworem raportowania błędów, który nadpisuje raport, aby nic nie robić. ie:

public class SecureErrorReportValve extends ErrorReportValve {

@Override
protected void report(Request request,Response response,Throwable throwable) {
}

}

I ustaw go za pomocą:

  ((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);

Jeśli chcesz wysłać swoją wiadomość i uważasz, że Tomcat nie powinien jej zadzierać, chcesz coś w stylu:

@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
    String message = response.getMessage();
    if (message != null) {
        try {
            response.getWriter().print(message);
            response.finishResponse();
        } catch (IOException e) {
        }
    }
}
 10
Author: Clive Evans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-16 23:56:43

Jak powiedział Heikki, ustawienie statusu zamiast sendError() powoduje, że Tomcat nie dotyka jednostki odpowiedzi/ciała/ładunku.

Jeśli chcesz wysyłać tylko nagłówki odpowiedzi bez żadnych encji, jak w moim przypadku,

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);

Robi sztuczkę. Z Content-Length: 0, print() nie będzie miało żadnego efektu, nawet jeśli zostanie użyte, jak:

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");

Klient otrzymuje coś w rodzaju:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Wed, 28 Sep 2011 08:59:49 GMT

Jeśli chcesz wysłać jakiś komunikat o błędzie, użyj {[6] } o długości wiadomości (innej niż zero) lub możesz zostawić go Serwer

 9
Author: manikanta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 16:13:41

Mimo że jest zgodny z Servlet spec, ze względów bezpieczeństwa nie chcę, aby tomcat lub jakikolwiek inny kontener Servlet wysyłał szczegóły błędu. Z tym też trochę się zmagałem. Po wyszukaniu i wypróbowaniu rozwiązanie można podsumować jako:

  1. jak inni wspomnieli, nie używaj sendError(), używaj setStatus() zamiast
  2. frameworki jak np. Spring Security use sendError()...
  3. napisz a Filter że
    a. przekierowuje wywołania do sendError() do setStatus()
    b. spłukuje odpowiedź na końcu, aby zapobiec dalszej modyfikacji odpowiedzi przez pojemnik

Mały przykład filtra serwletów można znaleźć tutaj .

 5
Author: Erich Eichinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-16 13:15:19

Dlaczego po prostu nie skonfigurować elementu <error-page> z pustą stroną HTML?

 2
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 17:51:03

Choć to pytanie jest trochę stare, też napotkałem ten problem. Po pierwsze, zachowanie Tomcat jest absolutnie poprawne. Jest to zgodne ze specyfikacją Servlet. Nie należy zmieniać zachowania Tomcat wobec spec. Jak wspomnieli Heikki Vesalainen i mrCoder, używaj tylko setStatus i setStatus.

Do kogo to może dotyczyć, podałem bilet z Tomcat, aby poprawić dokumenty sendError.

 1
Author: Michael-O,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-10 08:11:11