Uso o Spring RestTemplate há algum tempo e sempre atendo em uma parede quando estou tentando depurar suas solicitações e respostas. Basicamente, estou olhando para ver as mesmas coisas que vejo quando uso o curl com a opção "detalhado" ativada. Por exemplo :
curl -v http://twitter.com/statuses/public_timeline.rss
Exibe os dados enviados e os dados recebidos (incluindo os cabeçalhos, cookies, etc.).
Eu verifiquei algumas postagens relacionadas, como: Como faço para registrar a resposta no Spring RestTemplate? mas não consegui resolver esse problema.
Uma maneira de fazer isso seria realmente alterar o código-fonte RestTemplate e adicionar algumas instruções de log extras lá, mas eu consideraria essa abordagem realmente um último recurso. Deve haver uma maneira de dizer ao Spring Web Client / RestTemplate para registrar tudo de uma maneira muito mais amigável.
Meu objetivo seria ser capaz de fazer isso com código como:
restTemplate.put("http://someurl", objectToPut, urlPathValues);
e, em seguida, para obter o mesmo tipo de informação de depuração (como recebo com curl) no arquivo de log ou no console. Acredito que isso seria extremamente útil para quem usa o Spring RestTemplate e tem problemas. Usar o curl para depurar os problemas do RestTemplate simplesmente não funciona (em alguns casos).
fonte
Respostas:
Apenas para concluir o exemplo com uma implementação completa de
ClientHttpRequestInterceptor
para rastrear solicitação e resposta:Instancie
RestTemplate
usando aeBufferingClientHttpRequestFactory
oLoggingRequestInterceptor
:Isso
BufferingClientHttpRequestFactory
é necessário, pois queremos usar o corpo da resposta no interceptador e no código de chamada inicial. A implementação padrão permite ler o corpo da resposta apenas uma vez.fonte
BufferingClientHttpResponseWrapper
significado de @sofienezaghdoudi. No entanto, ele não funciona quando usado em testes usando a estrutura mockServer do spring, poisMockRestServiceServer.createServer(restTemplate)
substitui o RequestFactory emInterceptingClientHttpRequestFactory
.no Spring Boot, você pode obter a solicitação / resposta completa, definindo-o nas propriedades (ou outro método de 12 fatores)
isso gera
e resposta
ou apenas o
logging.level.org.apache.http.wire=DEBUG
que parece conter todas as informações relevantesfonte
by default the RestTemplate relies on standard JDK facilities to establish HTTP connections. You can switch to use a different HTTP library such as Apache HttpComponents
http-outgoing-0 << "[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0]
Estendendo a resposta @hstoerr com algum código:
Crie LoggingRequestInterceptor para registrar respostas de solicitações
Configuração RestTemplate
fonte
Sua melhor aposta é adicionar
logging.level.org.springframework.web.client.RestTemplate=DEBUG
aoapplication.properties
arquivo.Outras soluções, como a configuração
log4j.logger.httpclient.wire
, nem sempre funcionam porque elas assumem o uso dolog4j
ApacheHttpClient
, o que nem sempre é verdade.Observe, no entanto, que essa sintaxe funcionará apenas nas versões mais recentes do Spring Boot.
fonte
wire
madeireira, só inclui informações essenciais, como url, código resepone, parâmetros POST etc.Nenhuma dessas respostas realmente resolve 100% do problema. O mjj1409 obtém a maior parte, mas evita convenientemente o problema de registrar a resposta, o que exige um pouco mais de trabalho. Paul Sabou fornece uma solução que parece realista, mas não fornece detalhes suficientes para realmente implementar (e não funcionou para mim). Sofiene obteve o log, mas com um problema crítico: a resposta não é mais legível porque o fluxo de entrada já foi consumido!
Eu recomendo usar um BufferingClientHttpResponseWrapper para agrupar o objeto de resposta para permitir a leitura do corpo da resposta várias vezes:
Isso não consumirá o InputStream porque o corpo da resposta é carregado na memória e pode ser lido várias vezes. Se você não possui o BufferingClientHttpResponseWrapper em seu caminho de classe, poderá encontrar a implementação simples aqui:
https://github.com/spring-projects/spring-android/blob/master/spring-android-rest-template/src/main/java/org/springframework/http/client/BufferingClientHttpResponseWrapper.java
Para configurar o RestTemplate:
fonte
status==200
antesresponseCopy.getBody()
asyncRestTemplate
? Seria necessário retornar umListenableFuture
quando você o interceptar, o que não é possível alterarBufferingClientHttpResponseWrapper
em um retorno de chamada.A solução dada pelo xenoterracida para usar
é bom, mas o problema é que, por padrão, o Apache HttpComponents não é usado.
Para usar o Apache HttpComponents, adicione ao seu pom.xml
e configure
RestTemplate
com:fonte
Você pode usar o spring-rest-template-logger para registrar o
RestTemplate
tráfego HTTP.Adicione uma dependência ao seu projeto Maven:
Em seguida, personalize o seu da
RestTemplate
seguinte maneira:Verifique se o log de depuração está ativado em
application.properties
:Agora todo o tráfego HTTP RestTemplate será registrado
org.hobsoft.spring.resttemplatelogger.LoggingCustomizer
no nível de depuração.AVISO LEGAL: Eu escrevi esta biblioteca.
fonte
Finalmente encontrei uma maneira de fazer isso da maneira certa. A maior parte da solução vem de Como eu configuro o Spring e o SLF4J para que eu possa obter o log?
Parece que há duas coisas que precisam ser feitas:
log4j.logger.httpclient.wire=DEBUG
A segunda questão ocorre principalmente em ambientes de primavera em que o slf4j é usado (como foi o meu caso). Assim, quando slf4j é usado, verifique se as duas coisas a seguir acontecem:
Não existe uma biblioteca de registro comum em seu caminho de classe: isso pode ser feito adicionando os descritores de exclusão em seu pom:
O arquivo log4j.properties é armazenado em algum lugar do caminho de classe onde o Spring pode encontrá-lo / vê-lo. Se você tiver problemas com isso, uma solução de último recurso seria colocar o arquivo log4j.properties no pacote padrão (não é uma boa prática, mas apenas para ver se as coisas funcionam conforme o esperado)
fonte
httpclient.wire
é realmente da biblioteca Apache HttpComponents HttpClient (consulte hc.apache.org/httpcomponents-client-ga/logging.html ). Essa técnica funcionará apenas se você tiverRestTemplate
configurado para usar oHttpComponentsClientHttpRequestFactory
Log RestTemplate
Opção 1. Abra o log de depuração.
Configurar RestTemplate
Por padrão, o RestTemplate conta com os recursos padrão do JDK para estabelecer conexões HTTP. Você pode alternar para usar uma biblioteca HTTP diferente, como Apache HttpComponents
@Bean public RestTemplate restTemplate (construtor RestTemplateBuilder) {RestTemplate restTemplate = builder.build (); return restTemplate; }
Configurar log
application.yml
log: level: org.springframework.web.client.RestTemplate: DEBUG
Opção 2. Usando o Interceptor
Resposta do Wrapper
Implementar o Interceptor
Configurar RestTemplate
Configurar log
Verifique o pacote do LoggingRestTemplate, por exemplo em
application.yml
:log: nível: com.example.logging: DEBUG
Opção 3. Usando httpcomponent
Importar dependência de httpcomponent
Configurar RestTemplate
Configurar log
Verifique o pacote do LoggingRestTemplate, por exemplo em
application.yml
:log: level: org.apache.http: DEBUG
fonte
TestRestTemplate
, configureRestTemplateBuilder
: @Bean public RestTemplateBuilder restTemplateBuilder () {retorne novo RestTemplateBuilder (). AdditionalInterceptors (Collections.singletonList (new LoggingRestTemplate ())); }---- julho de 2019 ----
(usando o Spring Boot)
Fiquei surpreso que o Spring Boot, com toda a mágica de Configuração Zero, não fornece uma maneira fácil de inspecionar ou registrar um corpo de resposta JSON simples com o RestTemplate. Examinei as várias respostas e comentários fornecidos aqui e estou compartilhando minha própria versão destilada do que (ainda) funciona e me parece uma solução razoável, dadas as opções atuais (estou usando o Spring Boot 2.1.6 com Gradle 4.4 )
1. Usando o Fiddler como proxy http
Essa é, na verdade, uma solução bastante elegante, pois ignora todos os esforços pesados de criar seu próprio interceptor ou alterar o cliente http subjacente para apache (veja abaixo).
e depois
2. Usando o Apache HttpClient
Adicione o Apache HttpClient às suas dependências do Maven ou Gradle.
Use
HttpComponentsClientHttpRequestFactory
como RequestFactory para RestTemplate. A maneira mais simples de fazer isso seria:Ative DEBUG no seu
application.properties
arquivo (se você estiver usando o Spring Boot)Se você estiver usando o Spring Boot, precisará ter uma estrutura de registro configurada, por exemplo, usando uma dependência do spring-boot-starter que inclua
spring-boot-starter-logging
.3. Use um interceptador
Vou deixar você ler as propostas, contrapropostas e dicas nas outras respostas e comentários e decidir por si mesmo se deseja seguir esse caminho.
4. URL do log e status da resposta sem corpo
Embora isso não atenda aos requisitos estabelecidos para registrar o corpo, é uma maneira rápida e simples de começar a registrar suas chamadas REST. Ele exibe o URL completo e o status da resposta.
Basta adicionar a seguinte linha ao seu
application.properties
arquivo (supondo que você esteja usando o Spring Boot e supondo que você esteja usando uma dependência do iniciador do boot que incluaspring-boot-starter-logging
)A saída será mais ou menos assim:
fonte
Além do log do HttpClient descrito na outra resposta , você também pode introduzir um ClientHttpRequestInterceptor que lê o corpo da solicitação e a resposta e a registra. Você pode fazer isso se outras coisas também usarem o HttpClient ou se desejar um formato de log personalizado. Cuidado: você deseja fornecer ao RestTemplate um BufferingClientHttpRequestFactory, para poder ler a resposta duas vezes.
fonte
Conforme indicado nas outras respostas, o corpo da resposta precisa de tratamento especial para que possa ser lido repetidamente (por padrão, seu conteúdo é consumido na primeira leitura).
Em vez de usar
BufferingClientHttpRequestFactory
ao configurar a solicitação, o próprio interceptador pode agrupar a resposta e garantir que o conteúdo seja retido e possa ser lido repetidamente (pelo criador de logs e pelo consumidor da resposta):Meu interceptador, que
Código:
Configuração:
Exemplo de saída de log:
fonte
application.properties
application.yml
fonte
Pode não ser a maneira correta de fazer isso, mas acho que essa é a abordagem mais simples para imprimir solicitações e respostas sem preencher muito os logs.
Adicionando abaixo de 2 linhas, application.properties registra todas as solicitações e respostas 1ª linha para registrar as solicitações e 2ª linha para registrar as respostas.
fonte
Supondo que
RestTemplate
esteja configurado para usar o HttpClient 4.x, você pode ler a documentação de log do HttpClient aqui . Os registradores são diferentes dos especificados nas outras respostas.A configuração de log do HttpClient 3.x está disponível aqui .
fonte
Tantas respostas aqui exigem alterações de codificação e classes personalizadas e isso realmente não é necessário. Gte um proxy de depuração como o violinista e defina seu ambiente java para usá-lo na linha de comando (-Dhttp.proxyHost e -Dhttp.proxyPort) e execute o violinista e você poderá ver as solicitações e respostas na íntegra. Também possui muitas vantagens auxiliares, como a capacidade de mexer nos resultados e nas respostas antes e depois de serem enviadas para executar experimentos antes de se comprometer com a modificação do servidor.
O último problema que pode surgir é que se você deve usar HTTPS, precisará exportar o certificado SSL do violinista e importá-lo para a dica java keystore (cacerts): a senha padrão do keystore java é geralmente "changeit".
fonte
-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888
.Para fazer logon no Logback com a ajuda do Apache HttpClient:
Você precisa do Apache HttpClient no caminho de classe:
Configure o seu
RestTemplate
para usar HttpClient:Para registrar solicitações e respostas, adicione ao arquivo de configuração do Logback:
Ou para registrar ainda mais:
fonte
org.apache.http.wire=DEBUG
seuapplication.properties
agoraO truque de configurar o seu
RestTemplate
com aBufferingClientHttpRequestFactory
não funciona se você estiver usando algumClientHttpRequestInterceptor
, o que você fará se estiver tentando registrar através de interceptadores. Isto é devido à maneira queInterceptingHttpAccessor
(queRestTemplate
subclasses) funciona.Para encurtar a história ... basta usar esta classe no lugar de
RestTemplate
(observe que ela usa a API de log do SLF4J, edite conforme necessário):Concordo que é bobagem que é preciso muito trabalho apenas para fazer isso.
fonte
Adicionando à discussão acima, isso representa apenas cenários felizes. provavelmente você não poderá registrar a resposta se ocorrer um erro .
Nesse caso, além de todos os casos acima, você deve substituir DefaultResponseErrorHandler e configurá-lo como abaixo
fonte
Estranhamente, nenhuma dessas soluções funciona, pois o RestTemplate parece não retornar a resposta em alguns erros 500x do cliente e do servidor. Nesse caso, você também os registrará implementando ResponseErrorHandler da seguinte maneira. Aqui está um rascunho do código, mas você entendeu:
Você pode definir o mesmo interceptador que o manipulador de erros:
E a interceptação implementa as duas interfaces:
fonte
Como o @MilacH apontou, há um erro na implementação. Se um statusCode> 400 for retornado, uma IOException será lançada, pois o errorHandler não é chamado, dos interceptadores. A exceção pode ser ignorada e, em seguida, capturada novamente no método manipulador.
fonte
Melhor solução agora, basta adicionar dependência:
Ele contém uma classe LoggingRequestInterceptor que você pode adicionar dessa maneira ao seu RestTemplate:
integre esse utilitário adicionando-o como interceptador a um RestTemplate de mola, da seguinte maneira:
e adicione uma implementação slf4j à sua estrutura, como log4j.
ou use diretamente "Zg2proRestTemplate" . A "melhor resposta" de @PaulSabou parece assim, pois o httpclient e todas as bibliotecas apache.http não são necessariamente carregadas ao usar um RestTemplate de primavera.
fonte
log("Headers: {}", request.headers)
inLoggingRequestInterceptor:traceRequest
elog("Headers: {}", response.headers)
inLoggingRequestInterceptor:logResponse
. Você pode pensar em adicionar alguns sinalizadores para registrar cabeçalhos e corpo. Além disso - convém verificar o tipo de conteúdo do corpo para registro (por exemplo, log only application / json *). Isso também deve ser configurável. Em suma, com esses pequenos ajustes, você terá uma boa biblioteca para espalhar. bom trabalho :)Queria adicionar minha implementação disso também. Peço desculpas por todos os pontos e vírgulas que faltam, isso está escrito em Groovy.
Eu precisava de algo mais configurável do que a resposta aceita fornecida. Aqui está um bean de modelo de descanso que é muito ágil e registrará tudo o que o OP está procurando.
Classe de interceptador de log personalizado:
Definição de Bean de modelo de descanso:
Implementação:
fonte
Consulte o Q / A para registrar a solicitação e a resposta do modelo restante, ativando as várias leituras no HttpInputStream
Por que meu ClientHttpRequestInterceptor personalizado com resposta vazia
fonte
org.apache.http.wire fornece logs muito ilegíveis, então eu uso o logbook para registrar o aplicativo Servlet e RestTemplate req / resp para registrar
build.gradle
application.properties
RestTemplate
fonte
Em relação à resposta usando o ClientHttpInterceptor, encontrei uma maneira de manter toda a resposta sem as fábricas de buffer. Apenas armazene o fluxo de entrada do corpo da resposta na matriz de bytes usando algum método utils que copiará essa matriz do corpo, mas importante, envolva esse método com try catch, pois ele será interrompido se a resposta estiver vazia (que é a causa da Exceção de Acesso ao Recurso) e em catch, crie apenas uma matriz de bytes vazia e, em seguida, crie uma classe interna anônima de ClientHttpResponse usando essa matriz e outros parâmetros da resposta original. Depois, você pode retornar o novo objeto ClientHttpResponse para a cadeia de execução do modelo restante e registrar a resposta usando a matriz de bytes do corpo que foi armazenada anteriormente. Dessa forma, você evitará consumir InputStream na resposta real e poderá usar a resposta Rest Template como ela é. Nota,
fonte
minha configuração do logger usou xml
então você terá algo como abaixo:
através de HttpMessageConverterExtractor.java:92, você precisa continuar depurando e, no meu caso, obtive o seguinte:
e isto:
outputMessage.getBody () contém a mensagem que o http (tipo de postagem) envia
fonte