ch-remote: Show response body from error

If the server returns an error then print out the response body if there
is one present.

Fixes: #1262

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-06-08 15:25:37 +01:00 committed by Sebastien Boeuf
parent e436bbf3bb
commit 90e7accf8b

View File

@ -9,6 +9,7 @@ extern crate serde_json;
extern crate vmm; extern crate vmm;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use std::fmt;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::process; use std::process;
@ -19,7 +20,7 @@ enum Error {
StatusCodeParsing(std::num::ParseIntError), StatusCodeParsing(std::num::ParseIntError),
MissingProtocol, MissingProtocol,
ContentLengthParsing(std::num::ParseIntError), ContentLengthParsing(std::num::ParseIntError),
ServerResponse(StatusCode), ServerResponse(StatusCode, Option<String>),
InvalidCPUCount(std::num::ParseIntError), InvalidCPUCount(std::num::ParseIntError),
InvalidMemorySize(std::num::ParseIntError), InvalidMemorySize(std::num::ParseIntError),
AddDeviceConfig(vmm::config::Error), AddDeviceConfig(vmm::config::Error),
@ -31,6 +32,34 @@ enum Error {
Restore(vmm::config::Error), Restore(vmm::config::Error),
} }
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match self {
Socket(e) => write!(f, "Error writing to HTTP socket: {}", e),
StatusCodeParsing(e) => write!(f, "Error parsing HTTP status code: {}", e),
MissingProtocol => write!(f, "HTTP output is missing protocol statement"),
ContentLengthParsing(e) => write!(f, "Error parsing HTTP Content-Length field: {}", e),
ServerResponse(s, o) => {
if let Some(o) = o {
write!(f, "Server responded with an error: {:?}: {}", s, o)
} else {
write!(f, "Server responded with an error: {:?}", s)
}
}
InvalidCPUCount(e) => write!(f, "Error parsing CPU count: {}", e),
InvalidMemorySize(e) => write!(f, "Error parsing memory size: {}", e),
AddDeviceConfig(e) => write!(f, "Error parsing device syntax: {}", e),
AddDiskConfig(e) => write!(f, "Error parsing disk syntax: {}", e),
AddFsConfig(e) => write!(f, "Error parsing filesystem syntax: {}", e),
AddPmemConfig(e) => write!(f, "Error parsing persistent memory syntax: {}", e),
AddNetConfig(e) => write!(f, "Error parsing network syntax: {}", e),
AddVsockConfig(e) => write!(f, "Error parsing vsock syntax: {}", e),
Restore(e) => write!(f, "Error parsing restore syntax: {}", e),
}
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum StatusCode { pub enum StatusCode {
Continue, Continue,
@ -63,10 +92,10 @@ impl StatusCode {
)) ))
} }
fn check(self) -> Result<(), Error> { fn is_server_error(self) -> bool {
match self { match self {
StatusCode::OK | StatusCode::Continue | StatusCode::NoContent => Ok(()), StatusCode::OK | StatusCode::Continue | StatusCode::NoContent => false,
_ => Err(Error::ServerResponse(self)), _ => true,
} }
} }
} }
@ -123,10 +152,14 @@ fn parse_http_response(socket: &mut UnixStream) -> Result<Option<String>, Error>
} }
} }
} }
let body_string = content_length.and(Some(String::from(&res[body_offset.unwrap()..])));
let status_code = get_status_code(&res)?;
get_status_code(&res)?.check()?; if status_code.is_server_error() {
Err(Error::ServerResponse(status_code, body_string))
Ok(content_length.and(Some(String::from(&res[body_offset.unwrap()..])))) } else {
Ok(body_string)
}
} }
fn simple_api_command( fn simple_api_command(
@ -509,7 +542,7 @@ fn main() {
let matches = app.get_matches(); let matches = app.get_matches();
if let Err(e) = do_command(&matches) { if let Err(e) = do_command(&matches) {
eprintln!("Error running command: {:?}", e); eprintln!("Error running command: {}", e);
process::exit(1) process::exit(1)
}; };
} }