mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-23 00:44:55 +03:00
Some refacto on debug log.
This commit is contained in:
parent
96c4ca2546
commit
d4ec4b4b1a
@ -1,3 +1,3 @@
|
||||
Set-StrictMode -Version latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
hurl tests_ok/very_verbose.hurl --very-verbose --location
|
||||
hurl --very-verbose --location tests_ok/very_verbose.hurl
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
hurl tests_ok/very_verbose.hurl --very-verbose --location
|
||||
hurl --very-verbose --location tests_ok/very_verbose.hurl
|
||||
|
@ -29,6 +29,7 @@ use url::Url;
|
||||
|
||||
use crate::http::certificate::Certificate;
|
||||
use crate::http::core::*;
|
||||
use crate::http::debug::log_body;
|
||||
use crate::http::header::{
|
||||
HeaderVec, ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE, EXPECT, LOCATION, USER_AGENT,
|
||||
};
|
||||
@ -121,7 +122,7 @@ impl Client {
|
||||
}
|
||||
let redirect_url = redirect_url.unwrap();
|
||||
logger.debug("");
|
||||
logger.debug(format!("=> Redirect to {redirect_url}").as_str());
|
||||
logger.debug(&format!("=> Redirect to {redirect_url}"));
|
||||
logger.debug("");
|
||||
redirect_count += 1;
|
||||
if let Some(max_redirect) = options.max_redirect {
|
||||
@ -183,63 +184,40 @@ impl Client {
|
||||
transfer.debug_function(|info_type, data| match info_type {
|
||||
// Return all request headers (not one by one)
|
||||
easy::InfoType::HeaderOut => {
|
||||
let mut lines = split_lines(data);
|
||||
logger.debug_method_version_out(&lines[0]);
|
||||
|
||||
let lines = split_lines(data);
|
||||
// Extracts request headers from libcurl debug info.
|
||||
lines.pop().unwrap(); // Remove last empty line.
|
||||
lines.remove(0); // Remove method/path/version line.
|
||||
for line in lines {
|
||||
if let Some(header) = Header::parse(&line) {
|
||||
// First line is method/path/version line, last line is empty
|
||||
for line in &lines[1..lines.len() - 1] {
|
||||
if let Some(header) = Header::parse(line) {
|
||||
request_headers.push(header);
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't send any data, we log headers and empty body here
|
||||
// instead of relying on libcurl computing body in `easy::InfoType::DataOut`.
|
||||
// because libcurl dont call `easy::InfoType::DataOut` if there is no data
|
||||
// to send.
|
||||
if !has_body_data && verbose {
|
||||
let debug_request = Request::new(
|
||||
&method.to_string(),
|
||||
&url,
|
||||
request_headers.clone(),
|
||||
vec![],
|
||||
);
|
||||
for header in &debug_request.headers {
|
||||
// Logs method, version and request headers now.
|
||||
if verbose {
|
||||
logger.debug_method_version_out(&lines[0]);
|
||||
for header in &request_headers {
|
||||
logger.debug_header_out(&header.name, &header.value);
|
||||
}
|
||||
logger.info(">");
|
||||
}
|
||||
|
||||
if very_verbose {
|
||||
debug_request.log_body(true, logger);
|
||||
}
|
||||
// If we don't send any data, we log an empty body here instead of relying on
|
||||
// libcurl computing body in `easy::InfoType::DataOut` because libcurl doesn't
|
||||
// call `easy::InfoType::DataOut` if there is no data to send.
|
||||
if !has_body_data && very_verbose {
|
||||
logger.debug_important("Request body:");
|
||||
log_body(&[], &request_headers, true, logger);
|
||||
}
|
||||
}
|
||||
// We use this callback to get the real body bytes sent by libcurl.
|
||||
// We use this callback to get the real body bytes sent by libcurl and logs request
|
||||
// body chunks.
|
||||
easy::InfoType::DataOut => {
|
||||
// We log request headers with `easy::InfoType::DataOut` using libcurl
|
||||
// debug functions: there is no libcurl function to get the request headers.
|
||||
// As we can be called multiple times in this callback, we only log headers the
|
||||
// first time we send data (marked when the request body is empty).
|
||||
if verbose && request_body.is_empty() {
|
||||
let debug_request = Request::new(
|
||||
&method.to_string(),
|
||||
&url,
|
||||
request_headers.clone(),
|
||||
Vec::from(data),
|
||||
);
|
||||
for header in &debug_request.headers {
|
||||
logger.debug_header_out(&header.name, &header.value);
|
||||
}
|
||||
logger.info(">");
|
||||
|
||||
if very_verbose {
|
||||
debug_request.log_body(true, logger);
|
||||
}
|
||||
if very_verbose {
|
||||
logger.debug_important("Request body:");
|
||||
log_body(data, &request_headers, true, logger);
|
||||
}
|
||||
|
||||
// Extracts request body from libcurl debug info.
|
||||
// Constructs request body from libcurl debug info.
|
||||
request_body.extend(data);
|
||||
}
|
||||
// Curl debug logs
|
||||
@ -292,7 +270,7 @@ impl Client {
|
||||
match Certificate::try_from(cert_info) {
|
||||
Ok(value) => Some(value),
|
||||
Err(message) => {
|
||||
logger.error(format!("can not parse certificate - {message}").as_str());
|
||||
logger.error(&format!("can not parse certificate - {message}"));
|
||||
None
|
||||
}
|
||||
}
|
||||
@ -320,9 +298,9 @@ impl Client {
|
||||
// we have a segfault on Alpine Docker images and Rust 1.68.0, whereas it was
|
||||
// ok with Rust >= 1.67.0.
|
||||
let duration = duration.as_millis() as u64;
|
||||
logger.debug_important(
|
||||
format!("Response: (received {length} bytes in {duration} ms)").as_str(),
|
||||
);
|
||||
logger.debug_important(&format!(
|
||||
"Response: (received {length} bytes in {duration} ms)"
|
||||
));
|
||||
logger.debug("");
|
||||
|
||||
// FIXME: Explain why there may be multiple status line
|
||||
@ -336,6 +314,7 @@ impl Client {
|
||||
}
|
||||
logger.info("<");
|
||||
if very_verbose {
|
||||
logger.debug_important("Response body:");
|
||||
response.log_body(true, logger);
|
||||
logger.debug("");
|
||||
timings.log(logger);
|
||||
|
@ -15,7 +15,38 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use crate::http::{mimetype, HeaderVec};
|
||||
use crate::util::logger::Logger;
|
||||
use encoding::DecoderTrap;
|
||||
|
||||
/// Logs a buffer of bytes representing an HTTP request or response `body`.
|
||||
/// If the body is kind of text, we log all the text lines. If we can't detect that this is a text
|
||||
/// body (using Content-Type header in `headers`), we print the first 64 bytes.
|
||||
/// TODO: this function does not manage any kind of compression so we can only use for an HTTP
|
||||
/// request. For an HTTP response, see `[crate::http::Response::log_body]`.
|
||||
/// If `debug` is true, logs are printed using debug (with * prefix), otherwise logs are printed
|
||||
/// in info.
|
||||
pub fn log_body(body: &[u8], headers: &HeaderVec, debug: bool, logger: &Logger) {
|
||||
if let Some(content_type) = headers.content_type() {
|
||||
if !mimetype::is_kind_of_text(content_type) {
|
||||
log_bytes(body, 64, debug, logger);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Decode body as text:
|
||||
let encoding = match headers.character_encoding() {
|
||||
Ok(encoding) => encoding,
|
||||
Err(_) => {
|
||||
log_bytes(body, 64, debug, logger);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match encoding.decode(body, DecoderTrap::Strict) {
|
||||
Ok(text) => log_text(&text, debug, logger),
|
||||
Err(_) => log_bytes(body, 64, debug, logger),
|
||||
}
|
||||
}
|
||||
|
||||
/// Debug log text.
|
||||
pub fn log_text(text: &str, debug: bool, logger: &Logger) {
|
||||
|
@ -46,8 +46,6 @@ mod headers_helper;
|
||||
mod mimetype;
|
||||
mod options;
|
||||
mod request;
|
||||
mod request_debug;
|
||||
mod request_decoding;
|
||||
mod request_spec;
|
||||
mod request_spec_curl_args;
|
||||
mod response;
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Hurl (https://hurl.dev)
|
||||
* Copyright (C) 2023 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use crate::http::{debug, mimetype, Request};
|
||||
use crate::util::logger::Logger;
|
||||
|
||||
impl Request {
|
||||
/// Log request body.
|
||||
pub fn log_body(&self, debug: bool, logger: &Logger) {
|
||||
logger.debug_important("Request body:");
|
||||
|
||||
// We try to decode the HTTP body as text if the response has a text kind content type.
|
||||
// If it ok, we print each line of the body in debug format. Otherwise, we
|
||||
// print the body first 64 bytes.
|
||||
if let Some(content_type) = self.headers.content_type() {
|
||||
if !mimetype::is_kind_of_text(content_type) {
|
||||
debug::log_bytes(&self.body, 64, debug, logger);
|
||||
return;
|
||||
}
|
||||
}
|
||||
match self.text() {
|
||||
Ok(text) => debug::log_text(&text, debug, logger),
|
||||
Err(_) => debug::log_bytes(&self.body, 64, debug, logger),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Hurl (https://hurl.dev)
|
||||
* Copyright (C) 2023 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use encoding::DecoderTrap;
|
||||
|
||||
use crate::http::{HttpError, Request};
|
||||
|
||||
impl Request {
|
||||
/// Returns response body as text.
|
||||
pub fn text(&self) -> Result<String, HttpError> {
|
||||
let encoding = self.headers.character_encoding()?;
|
||||
match encoding.decode(&self.body, DecoderTrap::Strict) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(_) => Err(HttpError::InvalidDecoding {
|
||||
charset: encoding.name().to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
@ -24,11 +24,7 @@ use crate::util::logger::Logger;
|
||||
impl Response {
|
||||
/// Log a response body as text if possible, or a slice of body bytes.
|
||||
pub fn log_body(&self, debug: bool, logger: &Logger) {
|
||||
if debug {
|
||||
logger.debug_important("Response body:");
|
||||
}
|
||||
|
||||
// We try to decode the HTTP body as text if the request has a text kind content type.
|
||||
// We try to decode the HTTP body as text if the response has a text kind content type.
|
||||
// If it ok, we print each line of the body in debug format. Otherwise, we
|
||||
// print the body first 64 bytes.
|
||||
if let Some(content_type) = self.headers.content_type() {
|
||||
|
@ -220,7 +220,6 @@ pub fn run(
|
||||
// an error. If we want to treat it as an error, we've to add it to the current
|
||||
// `entry_result` errors, and optionally deals with retry if we can't write to the
|
||||
// specified path.
|
||||
|
||||
let authorized = if let Output::File(filename) = &output {
|
||||
if !runner_options.context_dir.is_access_allowed(filename) {
|
||||
let inner = RunnerError::UnauthorizedFileAccess {
|
||||
|
Loading…
Reference in New Issue
Block a user