Desativar todos os conteúdos resposta de erro HTTP padrão no Tomcat
-
16-09-2019 - |
Pergunta
Por padrão, Tomcat envia alguns de volta o conteúdo HTML para o cliente se ele encontrar algo como um HTTP 404. Eu sei que via web.xml
um <error-page>
pode ser configurado para personalizar este conteúdo.
No entanto, eu gostaria apenas para Tomcat para não enviar qualquer coisa em termos de conteúdo de resposta (eu ainda como o código de status, é claro). Existe alguma maneira de configurar facilmente isso?
Eu estou tentando evitar A) enviando explicitamente conteúdo vazio no fluxo de resposta de minha Servlet, e B) configurar páginas de erro personalizadas para um grupo inteiro de HTTP status de erro na minha web.xml
.
Para alguns fundo, eu estou desenvolvendo uma API HTTP e estou controlando minha própria conteúdo da resposta. Assim, para um HTTP 500, por exemplo, estou preencher algum conteúdo XML na resposta contendo informações de erro. Para situações como um HTTP 404, o status de resposta HTTP é suficiente para os clientes, eo conteúdo tomcat está enviando é desnecessário. Se há uma abordagem diferente, estou aberto a ouvi-lo.
Editar: Após investigação continuada, eu ainda não consigo encontrar muito na forma de uma solução. Se alguém pode dizer definitivamente isso não é possível, ou fornecer um recurso com evidências de que ele não vai funcionar, eu vou aceitar isso como uma resposta e tentar trabalhar em torno dele.
Solução
Se você não quer tomcat mostrar uma página de erro, então não use sendError (...). Em vez disso use setStatus (...).
por exemplo. Se você quer dar uma resposta 405, então você faz
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.getWriter().println("The method " + request.getMethod() +
" is not supported by this service.");
Lembre-se também para não jogar qualquer exceção de seu servlet. Em vez capturar a exceção e, novamente, defina o statusCode seu self.
i.
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);
}
}
é claro, se você não quer qualquer conteúdo, em seguida, basta fazer qualquer coisa que não escrever para o escritor, basta definir o status.
Outras dicas
Embora este não responde exatamente a declaração "não enviar qualquer coisa" sobre a questão, e sobre a onda de Clive Evans' responder , eu descobri que no tomcat você pode fazer os demais detalhado textos ir longe de páginas de erro sem criar um ErrorReportValve personalizado.
Você pode fazer a esta personalização ErrorReportValve através das 2 params "ShowReport" e "showServerInfo" no seu "server.xml":
<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />
Link para a documentação oficial.
trabalhou para mim em tomcat 7.0.55, não funcionou para mim no tomcat 7.0.47 (acho que por causa de algo relatado no link a seguir http://www.mail-archive.com/users@tomcat.apache.org/msg113856.html )
A rápida, um pouco sujo, mas fácil maneira de parar Tomcat de enviar qualquer corpo de erro é chamar setErrorReportValveClass contra o hospedeiro tomcat, com uma válvula de relatório de erro personalizada que substitui denunciar para não fazer nada. ou seja:
public class SecureErrorReportValve extends ErrorReportValve {
@Override
protected void report(Request request,Response response,Throwable throwable) {
}
}
e configurá-lo com:
((StandardHost) tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);
Se você quiser enviar sua mensagem, e só pensar Tomcat não deve mexer com ele, você quer algo ao longo das linhas de:
@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) {
}
}
}
Como Heikki disse, colocando o estado em vez de sendError()
faz com que o Tomcat não tocar a entidade resposta / corpo / carga útil.
Se você só quer enviar os cabeçalhos de resposta, sem qualquer entidade, como no meu caso,
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
faz o truque. Com Content-Length: 0
, o print()
não terá nenhum efeito, mesmo se usado, como:
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");
o cliente recebe algo como:
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
Se você quiser enviar alguma mensagem de erro, use o setContentLength()
com comprimento de mensagem (diferente de zero) ou você pode deixá-lo para o servidor
Embora compatível com a sua Servlet spec, por razões de segurança eu não quero tomcat ou qualquer outro recipiente Servlet para enviar os detalhes do erro. Lutei com isso também um pouco. Depois de pesquisar e experimentar, a solução pode ser resumida como:
- Como os outros mencionados, não use
sendError()
, usosetStatus()
vez - frameworks como por exemplo Spring Security uso
sendError()
embora ... -
Filter
que
uma. redireciona as chamadas parasendError()
parasetStatus()
b. esvazia a resposta no final para impedir que o recipiente de modificar ainda mais a resposta ??li>
Um pequeno exemplo filtro de servlet fazer isso podem ser encontrados aqui .
Porque não basta configurar o elemento <error-page>
com uma página HTML vazio?
Embora esta pergunta é um pouco velho, eu corri para este problema também. Primeiro de tudo, o comportamento do Tomcat é absolutamente correto. Este é por Servlet Spec. Não se deve alterar o comportamento do Tomcat contra o spec. Como Heikki Vesalainen e mrCoder mencionado, setStatus
uso e setStatus
somente.
Para quem possa interessar, eu levantei um href="https://issues.apache.org/bugzilla/show_bug.cgi?id=54198" rel="nofollow"> bilhete sendError.
Configurar <error-page>
Elements em web.xml
Editar $CATALINA_HOME/conf/web.xml
, adicione no final o seguinte <error-page>
, salvar e reiniciar tomcat
<web-app>
...
...
...
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.html</location>
</error-page>
<error-page>
<error-code>400</error-code>
<location>/400.html</location>
</error-page>
</web-app>
- Ele funciona muito bem como eu esperava, embora eu realmente não criou um rotas válidas para esses valores
location
específicos (por exemplo/400.html
)
antes
depois