mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-13 06:54:54 +03:00
Some refacto on output managment
This commit is contained in:
parent
20d86f5188
commit
9c7e793ba1
@ -1 +1 @@
|
||||
error: Error ~~~: ~~~ (os error ~~~)
|
||||
error: build~tmp can not be written (~~~)
|
||||
|
@ -1 +1 @@
|
||||
error: Error ~~~foo~bar~baz: ~~~ (os error ~~~)
|
||||
error: ~~~foo~bar~baz can not be written (~~~)
|
||||
|
@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use crate::runner;
|
||||
use hurl_core::error::Error as CoreError;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -24,16 +26,11 @@ impl Error {
|
||||
pub fn new(message: &str) -> Error {
|
||||
Error(message.to_string())
|
||||
}
|
||||
|
||||
pub fn from_path(error: std::io::Error, path: &str) -> Error {
|
||||
let message = format!("Error {path}: {error}");
|
||||
Error::new(&message)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Error::new(&value.to_string())
|
||||
impl From<runner::Error> for Error {
|
||||
fn from(error: runner::Error) -> Self {
|
||||
Error::new(&error.fixme())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,8 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use crate::output;
|
||||
use crate::output::error::Error;
|
||||
use crate::runner::HurlResult;
|
||||
use crate::runner::{HurlResult, Output};
|
||||
|
||||
/// Writes the `hurl_result` JSON representation to the file `filename_out`.
|
||||
///
|
||||
@ -33,5 +32,10 @@ pub fn write_json(
|
||||
let json_result = hurl_result.to_json(content, filename_in);
|
||||
let serialized = serde_json::to_string(&json_result).unwrap();
|
||||
let s = format!("{serialized}\n");
|
||||
output::write_output(&s.into_bytes(), filename_out)
|
||||
let bytes = s.into_bytes();
|
||||
match filename_out {
|
||||
Some(file) => Output::File(file.to_string()).write(&bytes)?,
|
||||
None => Output::StdOut.write(&bytes)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -24,29 +24,7 @@
|
||||
mod error;
|
||||
mod json;
|
||||
mod raw;
|
||||
mod stdout;
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
pub use self::error::Error;
|
||||
pub use self::json::write_json;
|
||||
pub use self::raw::write_body;
|
||||
|
||||
/// Writes `bytes` to the file `filename` or stdout by default.
|
||||
fn write_output(bytes: &Vec<u8>, filename: &Option<String>) -> Result<(), Error> {
|
||||
match filename {
|
||||
None => stdout::write_stdout(bytes.as_slice())?,
|
||||
Some(filename) => {
|
||||
let path = Path::new(filename.as_str());
|
||||
let mut file = match std::fs::File::create(path) {
|
||||
Ok(file) => file,
|
||||
Err(e) => return Err(Error::from_path(e, filename)),
|
||||
};
|
||||
if let Err(e) = file.write_all(bytes.as_slice()) {
|
||||
return Err(Error::from_path(e, filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -16,11 +16,11 @@
|
||||
*
|
||||
*/
|
||||
use hurl_core::ast::{Pos, SourceInfo};
|
||||
use hurl_core::error::Error;
|
||||
|
||||
use crate::runner::HurlResult;
|
||||
use crate::output::Error;
|
||||
use crate::runner;
|
||||
use crate::runner::{HurlResult, Output};
|
||||
use crate::util::logger::Logger;
|
||||
use crate::{output, runner};
|
||||
|
||||
/// Writes the `hurl_result` last body response to the file `filename_out`.
|
||||
///
|
||||
@ -33,7 +33,7 @@ pub fn write_body(
|
||||
color: bool,
|
||||
filename_out: &Option<String>,
|
||||
logger: &Logger,
|
||||
) -> Result<(), output::error::Error> {
|
||||
) -> Result<(), Error> {
|
||||
// By default, we output the body response bytes of the last entry
|
||||
if let Some(entry_result) = hurl_result.entries.last() {
|
||||
if let Some(call) = entry_result.calls.last() {
|
||||
@ -47,24 +47,27 @@ pub fn write_body(
|
||||
text.push('\n');
|
||||
output.append(&mut text.into_bytes());
|
||||
}
|
||||
let mut body = if entry_result.compressed {
|
||||
match response.uncompress_body() {
|
||||
Ok(bytes) => bytes,
|
||||
if entry_result.compressed {
|
||||
let mut bytes = match response.uncompress_body() {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
// FIXME: we convert to a runner::Error to be able to use fixme
|
||||
// method. Can we do otherwise (without creating an artificial
|
||||
// error a first character).
|
||||
// FIXME: we convert to a runner::Error to be able to use fixme!
|
||||
// We may pass a [`SourceInfo`] as a parameter of this method to make
|
||||
// a more accurate error
|
||||
let source_info = SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0));
|
||||
let error = runner::Error::new(source_info, e.into(), false);
|
||||
let message = error.fixme();
|
||||
return Err(output::error::Error::new(&message));
|
||||
return Err(error.into());
|
||||
}
|
||||
}
|
||||
};
|
||||
output.append(&mut bytes);
|
||||
} else {
|
||||
response.body.clone()
|
||||
};
|
||||
output.append(&mut body);
|
||||
output::write_output(&output, filename_out)?;
|
||||
let bytes = &response.body;
|
||||
output.extend(bytes);
|
||||
}
|
||||
match filename_out {
|
||||
Some(file) => Output::File(file.to_string()).write(&output)?,
|
||||
None => Output::StdOut.write(&output)?,
|
||||
}
|
||||
} else {
|
||||
logger.info("No response has been received");
|
||||
}
|
||||
|
@ -1,41 +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 std::io;
|
||||
#[cfg(target_family = "windows")]
|
||||
use std::io::IsTerminal;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::output::error::Error;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
pub(crate) fn write_stdout(buf: &[u8]) -> Result<(), Error> {
|
||||
let mut handle = io::stdout().lock();
|
||||
handle.write_all(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
pub(crate) fn write_stdout(buf: &[u8]) -> Result<(), Error> {
|
||||
if io::stdout().is_terminal() {
|
||||
println!("{}", String::from_utf8_lossy(buf));
|
||||
} else {
|
||||
let mut handle = io::stdout().lock();
|
||||
handle.write_all(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -190,7 +190,7 @@ impl hurl_core::error::Error for Error {
|
||||
}
|
||||
RunnerError::FileReadAccess { file } => format!("file {file} can not be read"),
|
||||
RunnerError::FileWriteAccess { file, error } => {
|
||||
format!("{file} can not be write ({error})")
|
||||
format!("{file} can not be written ({error})")
|
||||
}
|
||||
RunnerError::FilterDecode(encoding) => {
|
||||
format!("value can not be decoded with <{encoding}> encoding")
|
||||
|
@ -21,6 +21,7 @@
|
||||
pub use self::error::{Error, RunnerError};
|
||||
pub use self::hurl_file::run;
|
||||
pub use self::number::Number;
|
||||
pub use self::output::Output;
|
||||
pub use self::result::{AssertResult, CaptureResult, EntryResult, HurlResult};
|
||||
pub use self::runner_options::{RunnerOptions, RunnerOptionsBuilder};
|
||||
pub use self::value::Value;
|
||||
@ -38,6 +39,7 @@ mod multiline;
|
||||
mod multipart;
|
||||
mod number;
|
||||
mod options;
|
||||
mod output;
|
||||
mod predicate;
|
||||
mod predicate_value;
|
||||
mod query;
|
||||
@ -48,5 +50,4 @@ mod result;
|
||||
mod runner_options;
|
||||
mod template;
|
||||
mod value;
|
||||
mod write;
|
||||
mod xpath;
|
||||
|
87
packages/hurl/src/runner/output.rs
Normal file
87
packages/hurl/src/runner/output.rs
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 std::fs::File;
|
||||
use std::io;
|
||||
#[cfg(target_family = "windows")]
|
||||
use std::io::IsTerminal;
|
||||
use std::io::Write;
|
||||
|
||||
use crate::runner::{Error, RunnerError};
|
||||
use hurl_core::ast::{Pos, SourceInfo};
|
||||
|
||||
/// Represents the output of write operation: can be either a file or stdout.
|
||||
pub enum Output {
|
||||
StdOut,
|
||||
File(String),
|
||||
}
|
||||
|
||||
impl Output {
|
||||
/// Writes these `bytes` to the output.
|
||||
pub fn write(&self, bytes: &[u8]) -> Result<(), Error> {
|
||||
match self {
|
||||
Output::StdOut => match write_stdout(bytes) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(Error::new_file_write_access("stdout", &e.to_string())),
|
||||
},
|
||||
Output::File(filename) => {
|
||||
let mut file = match File::create(filename) {
|
||||
Ok(file) => file,
|
||||
Err(e) => return Err(Error::new_file_write_access(filename, &e.to_string())),
|
||||
};
|
||||
match file.write_all(bytes) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(Error::new_file_write_access(filename, &e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Creates a new file write access error.
|
||||
fn new_file_write_access(filename: &str, error: &str) -> Error {
|
||||
// TODO: improve the error with a [`SourceInfo`] passed in parameter.
|
||||
let source_info = SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0));
|
||||
Error::new(
|
||||
source_info,
|
||||
RunnerError::FileWriteAccess {
|
||||
file: filename.to_string(),
|
||||
error: error.to_string(),
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
fn write_stdout(buf: &[u8]) -> Result<(), io::Error> {
|
||||
let mut handle = io::stdout().lock();
|
||||
handle.write_all(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
fn write_stdout(buf: &[u8]) -> Result<(), io::Error> {
|
||||
if io::stdout().is_terminal() {
|
||||
println!("{}", String::from_utf8_lossy(buf));
|
||||
} else {
|
||||
let mut handle = io::stdout().lock();
|
||||
handle.write_all(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -19,8 +19,8 @@ use hurl_core::ast::{Pos, SourceInfo};
|
||||
|
||||
use crate::http::{Call, Cookie};
|
||||
use crate::runner::error::Error;
|
||||
use crate::runner::output::Output;
|
||||
use crate::runner::value::Value;
|
||||
use crate::runner::write::write_file;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct HurlResult {
|
||||
@ -123,9 +123,9 @@ impl EntryResult {
|
||||
return Err(Error::new(source_info, e.into(), false));
|
||||
}
|
||||
};
|
||||
write_file(&bytes, &filename)
|
||||
Output::File(filename).write(&bytes)
|
||||
} else {
|
||||
write_file(&response.body, &filename)
|
||||
Output::File(filename).write(&response.body)
|
||||
}
|
||||
}
|
||||
None => Ok(()),
|
||||
|
@ -1,51 +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::runner::{Error, RunnerError};
|
||||
use hurl_core::ast::{Pos, SourceInfo};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
// TODO: make functions for sdtout
|
||||
|
||||
/// Writes these `bytes` to the file `filename`.
|
||||
pub fn write_file(bytes: &[u8], filename: &str) -> Result<(), Error> {
|
||||
let mut file = match File::create(filename) {
|
||||
Ok(file) => file,
|
||||
Err(e) => return Err(Error::new_file_write_access(filename, &e.to_string())),
|
||||
};
|
||||
match file.write_all(bytes) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(Error::new_file_write_access(filename, &e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Creates a new file write access error.
|
||||
fn new_file_write_access(filename: &str, error: &str) -> Error {
|
||||
// TODO: improve the error with a [`SourcInfo`] passed in parameter.
|
||||
let source_info = SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0));
|
||||
Error::new(
|
||||
source_info,
|
||||
RunnerError::FileWriteAccess {
|
||||
file: filename.to_string(),
|
||||
error: error.to_string(),
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user