mirror of
https://github.com/nushell/nushell.git
synced 2025-02-16 10:32:29 +01:00
Fallback to extension-based content type detection when parsing Content-Type
header fails (#13610)
# Description Previously when nushell failed to parse the content type header, it would emit an error instead of returning the response. Now it will fall back to `text/plain` (which, in turn, will trigger type detection based on file extension). May fix (potentially) nushell/nushell#11927 Refs: https://discord.com/channels/601130461678272522/614593951969574961/1272895236489613366 Supercedes: #13609 # User-Facing Changes It's now possible to fetch content even if the server returns an invalid content type header. Users may need to parse the response manually, but it's still better than not getting the response at all. # Tests + Formatting Added a test for the new behaviour. # After Submitting
This commit is contained in:
parent
e841fce0f9
commit
e690e7aac0
@ -4,7 +4,6 @@ use base64::{
|
||||
engine::{general_purpose::PAD, GeneralPurpose},
|
||||
Engine,
|
||||
};
|
||||
use fancy_regex::Regex;
|
||||
use multipart_rs::MultipartWriter;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::{ByteStream, LabeledError, Signals};
|
||||
@ -561,14 +560,12 @@ fn transform_response_using_content_type(
|
||||
resp: Response,
|
||||
content_type: &str,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let regex = Regex::new("\"").expect("Failed to create regex");
|
||||
let content_type_trim = regex.replace_all(content_type, "").to_string();
|
||||
|
||||
let content_type = mime::Mime::from_str(&content_type_trim).map_err(|err| {
|
||||
LabeledError::new(err.to_string())
|
||||
.with_help("given unknown MIME type, or error parsing MIME type")
|
||||
.with_label(format!("MIME type unknown: {content_type_trim}"), span)
|
||||
})?;
|
||||
let content_type = mime::Mime::from_str(content_type)
|
||||
// there are invalid content types in the wild, so we try to recover
|
||||
// Example: `Content-Type: "text/plain"; charset="utf8"` (note the quotes)
|
||||
.or_else(|_| mime::Mime::from_str(&content_type.replace('"', "")))
|
||||
.or_else(|_| mime::Mime::from_str("text/plain"))
|
||||
.expect("Failed to parse content type, and failed to default to text/plain");
|
||||
|
||||
let ext = match (content_type.type_(), content_type.subtype()) {
|
||||
(mime::TEXT, mime::PLAIN) => {
|
||||
|
@ -273,3 +273,46 @@ fn http_get_self_signed_override() {
|
||||
let actual = nu!("http get --insecure https://self-signed.badssl.com/");
|
||||
assert!(actual.out.contains("<html>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_get_with_invalid_mime_type() {
|
||||
let mut server = Server::new();
|
||||
|
||||
let _mock = server
|
||||
.mock("GET", "/foo.nuon")
|
||||
.with_status(200)
|
||||
// `what&ever` is not a parseable MIME type
|
||||
.with_header("content-type", "what&ever")
|
||||
.with_body("[1 2 3]")
|
||||
.create();
|
||||
|
||||
// but `from nuon` is a known command in nu, so we take `foo.{ext}` and pass it to `from {ext}`
|
||||
let actual = nu!(pipeline(
|
||||
format!(
|
||||
r#"http get {url}/foo.nuon | to json --raw"#,
|
||||
url = server.url()
|
||||
)
|
||||
.as_str()
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[1,2,3]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_get_with_unknown_mime_type() {
|
||||
let mut server = Server::new();
|
||||
let _mock = server
|
||||
.mock("GET", "/foo")
|
||||
.with_status(200)
|
||||
// `application/nuon` is not an IANA-registered MIME type
|
||||
.with_header("content-type", "application/nuon")
|
||||
.with_body("[1 2 3]")
|
||||
.create();
|
||||
|
||||
// but `from nuon` is a known command in nu, so we take `{garbage}/{whatever}` and pass it to `from {whatever}`
|
||||
let actual = nu!(pipeline(
|
||||
format!(r#"http get {url}/foo | to json --raw"#, url = server.url()).as_str()
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "[1,2,3]");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user