From afcd47fd01a7f376e799fc8cdaa5b5ee9e56d014 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Amiel Date: Wed, 30 Oct 2024 10:32:11 +0100 Subject: [PATCH] Support more JSON / XML "like" mimetypes with debug output --- .../error_format_long.err.pattern | 89 +++ .../hurl/tests_failed/error_format_long.hurl | 24 + .../hurl/tests_failed/error_format_long.py | 96 ++- .../error_format_long_color.err.pattern | 89 +++ packages/hurl/src/http/mimetype.rs | 648 +++++++++++++++++- 5 files changed, 932 insertions(+), 14 deletions(-) diff --git a/integration/hurl/tests_failed/error_format_long.err.pattern b/integration/hurl/tests_failed/error_format_long.err.pattern index 9b7b30505..eb59326fd 100644 --- a/integration/hurl/tests_failed/error_format_long.err.pattern +++ b/integration/hurl/tests_failed/error_format_long.err.pattern @@ -77,3 +77,92 @@ error: Assert failure | expected: string | +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: application/fhir+json +Content-Length: 902 +Server: Flask Server +Connection: close + +{"resourceType": "Practitioner", "id": "example", "text": {"status": "generated", "div": "
\n

Dr Adam Careful is a Referring Practitioner for Acme Hospital from 1-Jan 2012 to 31-Mar\n 2012

\n
"}, "identifier": [{"system": "http://www.acme.org/practitioners", "value": "23"}], "active": true, "name": [{"family": "Careful", "given": ["Adam"], "prefix": ["Dr"]}], "address": [{"use": "home", "line": ["534 Erewhon St"], "city": "PleasantVille", "state": "Vic", "postalCode": "3999"}], "qualification": [{"identifier": [{"system": "http://example.org/UniversityIdentifier", "value": "12345"}], "code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0360/2.7", "code": "BS", "display": "Bachelor of Science"}], "text": "Bachelor of Science"}, "period": {"start": "1995"}, "issuer": {"display": "Example University"}}]} + +error: Assert failure + --> tests_failed/error_format_long.hurl:34:0 + | + | GET http://localhost:8000/error-format-long/fhir + | ... +34 | jsonpath "$.id" == "foo" + | actual: string + | expected: string + | + +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: text/csv; charset=utf-8 +Content-Length: 726 +Server: Flask Server +Connection: close + +"Year","Score","Title" +1968,86,"Greetings" +1970,17,"Bloody Mama" +1970,73,"Hi, Mom!" +1971,40,"Born to Win" +1973,98,"Mean Streets" +1973,88,"Bang the Drum Slowly" +1974,97,"The Godfather, Part II" +1976,41,"The Last Tycoon" +1976,99,"Taxi Driver" +1977,47,"1900" +1977,67,"New York, New York" +1978,93,"The Deer Hunter" +1980,97,"Raging Bull" +1981,75,"True Confessions" +1983,90,"The King of Comedy" +1984,89,"Once Upon a Time in America" +1984,60,"Falling in Love" +1985,98,"Brazil" +1986,65,"The Mission" +1987,00,"Dear America: Letters Home From Vietnam" +1987,80,"The Untouchables" +1987,78,"Angel Heart" +1988,96,"Midnight Run" +1989,64,"Jacknife" +1989,47,"We're No Angels" +1990,88,"Awakenings" +1990,29,"Stanley & Iris" +1990,96,"Goodfellas" + + +error: Assert failure + --> tests_failed/error_format_long.hurl:42:0 + | + | GET http://localhost:8000/error-format-long/csv + | ... +42 | body split "\n" nth 9 split "," nth 2 == "\"Taxi\"" + | actual: string <"Taxi Driver"> + | expected: string <"Taxi"> + | + +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: application/octet-stream +Content-Length: 4 +Server: Flask Server +Connection: close + +Bytes + +error: Assert failure + --> tests_failed/error_format_long.hurl:50:0 + | + | GET http://localhost:8000/error-format-long/bytes + | ... +50 | bytes == hex,beef; + | actual: byte array + | expected: byte array + | + diff --git a/integration/hurl/tests_failed/error_format_long.hurl b/integration/hurl/tests_failed/error_format_long.hurl index 659a43d79..d756a51f0 100644 --- a/integration/hurl/tests_failed/error_format_long.hurl +++ b/integration/hurl/tests_failed/error_format_long.hurl @@ -24,3 +24,27 @@ HTTP 200 Content-Type: application/problem+json [Asserts] jsonpath "$.title" == "You have enough credit." + + +# "JSON like" mimetype are supported, like [FHIR](https://www.hl7.org/fhir/json.html) +GET http://localhost:8000/error-format-long/fhir +HTTP 200 +Content-Type: application/fhir+json +[Asserts] +jsonpath "$.id" == "foo" + + +# Text like mimetype like CSV are supported +GET http://localhost:8000/error-format-long/csv +HTTP 200 +Content-Type: text/csv; charset=utf-8 +[Asserts] +body split "\n" nth 9 split "," nth 2 == "\"Taxi\"" + + +# Bytestream are dumped as a raw bytes stream +GET http://localhost:8000/error-format-long/bytes +HTTP 200 +Content-Type: application/octet-stream +[Asserts] +bytes == hex,beef; diff --git a/integration/hurl/tests_failed/error_format_long.py b/integration/hurl/tests_failed/error_format_long.py index beef62a1e..f9b10820f 100644 --- a/integration/hurl/tests_failed/error_format_long.py +++ b/integration/hurl/tests_failed/error_format_long.py @@ -1,7 +1,8 @@ import json +from io import BytesIO from app import app -from flask import Response +from flask import Response, make_response @app.route("/error-format-long/html") @@ -37,3 +38,96 @@ def error_format_problem_json(): "accounts": ["/account/12345", "/account/67890"], } return Response(json.dumps(data), mimetype="application/problem+json") + + +@app.route("/error-format-long/fhir") +def error_format_fhir_json(): + data = { + "resourceType": "Practitioner", + "id": "example", + "text": { + "status": "generated", + "div": '
\n

Dr Adam Careful is a Referring Practitioner for Acme Hospital from 1-Jan 2012 to 31-Mar\n 2012

\n
', + }, + "identifier": [{"system": "http://www.acme.org/practitioners", "value": "23"}], + "active": True, + "name": [{"family": "Careful", "given": ["Adam"], "prefix": ["Dr"]}], + "address": [ + { + "use": "home", + "line": ["534 Erewhon St"], + "city": "PleasantVille", + "state": "Vic", + "postalCode": "3999", + } + ], + "qualification": [ + { + "identifier": [ + { + "system": "http://example.org/UniversityIdentifier", + "value": "12345", + } + ], + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0360/2.7", + "code": "BS", + "display": "Bachelor of Science", + } + ], + "text": "Bachelor of Science", + }, + "period": {"start": "1995"}, + "issuer": {"display": "Example University"}, + } + ], + } + return Response(json.dumps(data), mimetype="application/fhir+json") + + +@app.route("/error-format-long/bytes") +def error_format_bytes(): + result = BytesIO() + result.write(b"\xde\xad\xbe\xef") + data = result.getvalue() + resp = make_response(data) + resp.content_type = "application/octet-stream" + return resp + + +@app.route("/error-format-long/csv") +def error_format_csv(): + data = """\ +"Year","Score","Title" +1968,86,"Greetings" +1970,17,"Bloody Mama" +1970,73,"Hi, Mom!" +1971,40,"Born to Win" +1973,98,"Mean Streets" +1973,88,"Bang the Drum Slowly" +1974,97,"The Godfather, Part II" +1976,41,"The Last Tycoon" +1976,99,"Taxi Driver" +1977,47,"1900" +1977,67,"New York, New York" +1978,93,"The Deer Hunter" +1980,97,"Raging Bull" +1981,75,"True Confessions" +1983,90,"The King of Comedy" +1984,89,"Once Upon a Time in America" +1984,60,"Falling in Love" +1985,98,"Brazil" +1986,65,"The Mission" +1987,00,"Dear America: Letters Home From Vietnam" +1987,80,"The Untouchables" +1987,78,"Angel Heart" +1988,96,"Midnight Run" +1989,64,"Jacknife" +1989,47,"We're No Angels" +1990,88,"Awakenings" +1990,29,"Stanley & Iris" +1990,96,"Goodfellas" +""" + return Response(data, mimetype="text/csv") diff --git a/integration/hurl/tests_failed/error_format_long_color.err.pattern b/integration/hurl/tests_failed/error_format_long_color.err.pattern index ededaa2e3..b3048499a 100644 --- a/integration/hurl/tests_failed/error_format_long_color.err.pattern +++ b/integration/hurl/tests_failed/error_format_long_color.err.pattern @@ -77,3 +77,92 @@  | expected: string   | +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: application/fhir+json +Content-Length: 902 +Server: Flask Server +Connection: close + +{"resourceType": "Practitioner", "id": "example", "text": {"status": "generated", "div": "
\n

Dr Adam Careful is a Referring Practitioner for Acme Hospital from 1-Jan 2012 to 31-Mar\n 2012

\n
"}, "identifier": [{"system": "http://www.acme.org/practitioners", "value": "23"}], "active": true, "name": [{"family": "Careful", "given": ["Adam"], "prefix": ["Dr"]}], "address": [{"use": "home", "line": ["534 Erewhon St"], "city": "PleasantVille", "state": "Vic", "postalCode": "3999"}], "qualification": [{"identifier": [{"system": "http://example.org/UniversityIdentifier", "value": "12345"}], "code": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0360/2.7", "code": "BS", "display": "Bachelor of Science"}], "text": "Bachelor of Science"}, "period": {"start": "1995"}, "issuer": {"display": "Example University"}}]} + +error: Assert failure + --> tests_failed/error_format_long.hurl:34:0 + | + | GET http://localhost:8000/error-format-long/fhir + | ... +34 | jsonpath "$.id" == "foo" + | actual: string  + | expected: string  + | + +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: text/csv; charset=utf-8 +Content-Length: 726 +Server: Flask Server +Connection: close + +"Year","Score","Title" +1968,86,"Greetings" +1970,17,"Bloody Mama" +1970,73,"Hi, Mom!" +1971,40,"Born to Win" +1973,98,"Mean Streets" +1973,88,"Bang the Drum Slowly" +1974,97,"The Godfather, Part II" +1976,41,"The Last Tycoon" +1976,99,"Taxi Driver" +1977,47,"1900" +1977,67,"New York, New York" +1978,93,"The Deer Hunter" +1980,97,"Raging Bull" +1981,75,"True Confessions" +1983,90,"The King of Comedy" +1984,89,"Once Upon a Time in America" +1984,60,"Falling in Love" +1985,98,"Brazil" +1986,65,"The Mission" +1987,00,"Dear America: Letters Home From Vietnam" +1987,80,"The Untouchables" +1987,78,"Angel Heart" +1988,96,"Midnight Run" +1989,64,"Jacknife" +1989,47,"We're No Angels" +1990,88,"Awakenings" +1990,29,"Stanley & Iris" +1990,96,"Goodfellas" + + +error: Assert failure + --> tests_failed/error_format_long.hurl:42:0 + | + | GET http://localhost:8000/error-format-long/csv + | ... +42 | body split "\n" nth 9 split "," nth 2 == "\"Taxi\"" + | actual: string <"Taxi Driver"> + | expected: string <"Taxi"> + | + +HTTP/1.1 200 +Server: Werkzeug/<<<.*?>>> Python/<<<.*?>>> +Date: <<<.*?>>> +Content-Type: application/octet-stream +Content-Length: 4 +Server: Flask Server +Connection: close + +Bytes + +error: Assert failure + --> tests_failed/error_format_long.hurl:50:0 + | + | GET http://localhost:8000/error-format-long/bytes + | ... +50 | bytes == hex,beef; + | actual: byte array  + | expected: byte array  + | + diff --git a/packages/hurl/src/http/mimetype.rs b/packages/hurl/src/http/mimetype.rs index 07d7a6716..0b417f046 100644 --- a/packages/hurl/src/http/mimetype.rs +++ b/packages/hurl/src/http/mimetype.rs @@ -19,33 +19,40 @@ // TODO: maybe add a proper MimeType enum (see ) // as implementation / api example. +use regex::Regex; + /// Returns true if binary data with this `content_type` can be decoded as text. pub fn is_kind_of_text(content_type: &str) -> bool { - let content_types = [ - "text/", - "application/json", - "application/problem+json", // See https://datatracker.ietf.org/doc/html/rfc7807 - "application/xml", - "application/x-www-form-urlencoded", - ]; - - content_types.iter().any(|c| content_type.contains(c)) + let content_type = content_type.trim().to_lowercase(); + content_type.contains("text/") || is_json(&content_type) || is_xml(&content_type) } /// Returns true if this `content_type` is HTML. pub fn is_html(content_type: &str) -> bool { + let content_type = content_type.trim().to_lowercase(); content_type.starts_with("text/html") } /// Returns true if this `content_type` is HTML. pub fn is_xml(content_type: &str) -> bool { - content_type.starts_with("text/xml") || content_type.starts_with("application/xml") + let content_type = content_type.trim().to_lowercase(); + let patterns = [ + r"^text/xml", + r"^application/xml", + r"^application/[a-z0-9-_.]+[+.]xml", + ]; + patterns + .iter() + .any(|p| Regex::new(p).unwrap().is_match(&content_type)) } /// Returns true if this `content_type` is JSON. pub fn is_json(content_type: &str) -> bool { - content_type.starts_with("application/json") - || content_type.starts_with("application/problem+json") + let content_type = content_type.trim().to_lowercase(); + let patterns = [r"^application/json", r"^application/[a-z0-9-_.]+[+.-]json"]; + patterns + .iter() + .any(|p| Regex::new(p).unwrap().is_match(&content_type)) } /// Extracts charset from mime-type String @@ -65,7 +72,7 @@ pub mod tests { use super::*; #[test] - pub fn test_charset() { + fn test_charset() { assert_eq!( charset("text/plain; charset=utf-8"), Some("utf-8".to_string()) @@ -88,4 +95,619 @@ pub mod tests { Some("utf-8".to_string()) ); } + + // Dataset for mimetypes issued from + + #[test] + fn test_is_json() { + let mime_types = [ + "application/3gppHal+json", + "application/3gppHalForms+json", + "application/ace+json", + "application/activity+json", + "application/aif+json", + "application/alto-cdni+json", + "application/alto-cdnifilter+json", + "application/alto-costmap+json", + "application/alto-costmapfilter+json", + "application/alto-directory+json", + "application/alto-endpointprop+json", + "application/alto-endpointpropparams+json", + "application/alto-endpointcost+json", + "application/alto-endpointcostparams+json", + "application/alto-error+json", + "application/alto-networkmapfilter+json", + "application/alto-networkmap+json", + "application/alto-propmap+json", + "application/alto-propmapparams+json", + "application/alto-tips+json", + "application/alto-tipsparams+json", + "application/alto-updatestreamcontrol+json", + "application/alto-updatestreamparams+json", + "application/atsc-rdt+json", + "application/calendar+json", + "application/captive+json", + "application/city+json", + "application/coap-group+json", + "application/csvm+json", + "application/cwl+json", + "application/dicom+json", + "application/dns+json", + "application/elm+json", + "application/EmergencyCallData.LegacyESN+json", + "application/expect-ct-report+json", + "application/fhir+json", + "application/geo+json", + "application/geo+json-seq", + "application/geopose+json", + "application/geoxacml+json", + "application/jf2feed+json", + "application/jose+json", + "application/jrd+json", + "application/jscalendar+json", + "application/jscontact+json", + "application/json", + "application/json-patch+json", + "application/json-seq", + "application/jsonpath", + "application/jwk+json", + "application/jwk-set+json", + "application/ld+json", + "application/linkset+json", + "application/manifest+json", + "application/merge-patch+json", + "application/mud+json", + "application/ppsp-tracker+json", + "application/problem+json", + "application/prs.implied-object+json", + "application/prs.implied-object+json-seq", + "application/pvd+json", + "application/rdap+json", + "application/reputon+json", + "application/sarif-external-properties+json", + "application/sarif+json", + "application/scim+json", + "application/senml-etch+json", + "application/senml+json", + "application/sensml+json", + "application/spdx+json", + "application/stix+json", + "application/taxii+json", + "application/td+json", + "application/tlsrpt+json", + "application/tm+json", + "application/trust-chain+json", + "application/vcard+json", + "application/vnd.acm.addressxfer+json", + "application/vnd.acm.chatbot+json", + "application/vnd.amadeus+json", + "application/vnd.apache.thrift.json", + "application/vnd.api+json", + "application/vnd.aplextor.warrp+json", + "application/vnd.apothekende.reservation+json", + "application/vnd.artisan+json", + "application/vnd.avalon+json", + "application/vnd.bbf.usp.msg+json", + "application/vnd.bekitzur-stech+json", + "application/vnd.byu.uapi+json", + "application/vnd.capasystems-pg+json", + "application/vnd.cncf.helm.config.v1+json", + "application/vnd.collection.doc+json", + "application/vnd.collection+json", + "application/vnd.collection.next+json", + "application/vnd.coreos.ignition+json", + "application/vnd.cryptii.pipe+json", + "application/vnd.cyclonedx+json", + "application/vnd.datapackage+json", + "application/vnd.dataresource+json", + "application/vnd.document+json", + "application/vnd.drive+json", + "application/vnd.eclipse.ditto+json", + "application/vnd.eu.kasparian.car+json", + "application/vnd.futoin+json", + "application/vnd.gentics.grd+json", + "application/vnd.geo+json", + "application/vnd.gnu.taler.exchange+json", + "application/vnd.gnu.taler.merchant+json", + "application/vnd.hal+json", + "application/vnd.hc+json", + "application/vnd.heroku+json", + "application/vnd.hyper-item+json", + "application/vnd.hyper+json", + "application/vnd.hyperdrive+json", + "application/vnd.ims.lis.v2.result+json", + "application/vnd.ims.lti.v2.toolconsumerprofile+json", + "application/vnd.ims.lti.v2.toolproxy.id+json", + "application/vnd.ims.lti.v2.toolproxy+json", + "application/vnd.ims.lti.v2.toolsettings+json", + "application/vnd.ims.lti.v2.toolsettings.simple+json", + "application/vnd.ipld.dag-json", + "application/vnd.las.las+json", + "application/vnd.leap+json", + "application/vnd.mason+json", + "application/vnd.micro+json", + "application/vnd.miele+json", + "application/vnd.nacamar.ybrid+json", + "application/vnd.nato.bindingdataobject+json", + "application/vnd.nearst.inv+json", + "application/vnd.oai.workflows+json", + "application/vnd.oci.image.manifest.v1+json", + "application/vnd.oftn.l10n+json", + "application/vnd.oma.lwm2m+json", + "application/vnd.openvpi.dspx+json", + "application/vnd.oracle.resource+json", + "application/vnd.pagerduty+json", + "application/vnd.restful+json", + "application/vnd.seis+json", + "application/vnd.shootproof+json", + "application/vnd.shopkick+json", + "application/vnd.siren+json", + "application/vnd.syft+json", + "application/vnd.tableschema+json", + "application/vnd.think-cell.ppttc+json", + "application/vnd.uic.osdm+json", + "application/vnd.vel+json", + "application/vnd.veritone.aion+json", + "application/vnd.xacml+json", + "application/voucher-cms+json", + "application/webpush-options+json", + "application/yang-data+json", + "application/yang-patch+json", + "application/yang-sid+json", + ]; + for mime in &mime_types { + assert!(is_json(mime), "{mime} is a not a JSON mime type"); + } + } + + #[test] + fn test_is_xml() { + let mime_types = [ + "application/3gpdash-qoe-report+xml", + "application/3gpp-ims+xml", + "application/atom+xml", + "application/atomcat+xml", + "application/atomdeleted+xml", + "application/atomsvc+xml", + "application/atsc-dwd+xml", + "application/atsc-held+xml", + "application/atsc-rsat+xml", + "application/auth-policy+xml", + "application/automationml-aml+xml", + "application/beep+xml", + "application/calendar+xml", + "application/ccmp+xml", + "application/ccxml+xml", + "application/cda+xml", + "application/cea-2018+xml", + "application/cellml+xml", + "application/clue_info+xml", + "application/clue+xml", + "application/cnrp+xml", + "application/conference-info+xml", + "application/cpl+xml", + "application/csta+xml", + "application/CSTAdata+xml", + "application/dash+xml", + "application/dash-patch+xml", + "application/davmount+xml", + "application/dialog-info+xml", + "application/dicom+xml", + "application/dskpp+xml", + "application/dssc+xml", + "application/elm+xml", + "application/EmergencyCallData.cap+xml", + "application/EmergencyCallData.Comment+xml", + "application/EmergencyCallData.Control+xml", + "application/EmergencyCallData.DeviceInfo+xml", + "application/EmergencyCallData.ProviderInfo+xml", + "application/EmergencyCallData.ServiceInfo+xml", + "application/EmergencyCallData.SubscriberInfo+xml", + "application/EmergencyCallData.VEDS+xml", + "application/emma+xml", + "application/emotionml+xml", + "application/epp+xml", + "application/fdt+xml", + "application/fhir+xml", + "application/framework-attributes+xml", + "application/geoxacml+xml", + "application/gml+xml", + "application/held+xml", + "application/hl7v2+xml", + "application/ibe-key-request+xml", + "application/ibe-pkg-reply+xml", + "application/im-iscomposing+xml", + "application/inkml+xml", + "application/its+xml", + "application/kpml-request+xml", + "application/kpml-response+xml", + "application/lgr+xml", + "application/load-control+xml", + "application/lost+xml", + "application/lostsync+xml", + "application/mads+xml", + "application/marcxml+xml", + "application/mathml+xml", + "application/mathml-content+xml", + "application/mathml-presentation+xml", + "application/mbms-associated-procedure-description+xml", + "application/mbms-deregister+xml", + "application/mbms-envelope+xml", + "application/mbms-msk-response+xml", + "application/mbms-msk+xml", + "application/mbms-protection-description+xml", + "application/mbms-reception-report+xml", + "application/mbms-register-response+xml", + "application/mbms-register+xml", + "application/mbms-schedule+xml", + "application/mbms-user-service-description+xml", + "application/media_control+xml", + "application/media-policy-dataset+xml", + "application/mediaservercontrol+xml", + "application/metalink4+xml", + "application/mets+xml", + "application/mmt-aei+xml", + "application/mmt-usd+xml", + "application/mods+xml", + "application/mrb-consumer+xml", + "application/mrb-publish+xml", + "application/msc-ivr+xml", + "application/msc-mixer+xml", + "application/nlsml+xml", + "application/odm+xml", + "application/oebps-package+xml", + "application/opc-nodeset+xml", + "application/p2p-overlay+xml", + "application/patch-ops-error+xml", + "application/pidf-diff+xml", + "application/pidf+xml", + "application/pls+xml", + "application/poc-settings+xml", + "application/problem+xml", + "application/provenance+xml", + "application/prs.implied-document+xml", + "application/prs.xsf+xml", + "application/pskc+xml", + "application/rdf+xml", + "application/route-apd+xml", + "application/route-s-tsid+xml", + "application/route-usd+xml", + "application/reginfo+xml", + "application/resource-lists-diff+xml", + "application/resource-lists+xml", + "application/rfc+xml", + "application/rlmi+xml", + "application/rls-services+xml", + "application/samlassertion+xml", + "application/samlmetadata+xml", + "application/sbml+xml", + "application/scaip+xml", + "application/senml+xml", + "application/sensml+xml", + "application/sep+xml", + "application/shf+xml", + "application/simple-filter+xml", + "application/smil+xml", + "application/soap+xml", + "application/sparql-results+xml", + "application/spirits-event+xml", + "application/srgs+xml", + "application/sru+xml", + "application/ssml+xml", + "application/swid+xml", + "application/tei+xml", + "application/thraud+xml", + "application/ttml+xml", + "application/urc-grpsheet+xml", + "application/urc-ressheet+xml", + "application/urc-targetdesc+xml", + "application/urc-uisocketdesc+xml", + "application/vcard+xml", + "application/vnd.1000minds.decision-model+xml", + "application/vnd.3gpp.access-transfer-events+xml", + "application/vnd.3gpp.bsf+xml", + "application/vnd.3gpp.crs+xml", + "application/vnd.3gpp.current-location-discovery+xml", + "application/vnd.3gpp.GMOP+xml", + "application/vnd.3gpp.mcdata-affiliation-command+xml", + "application/vnd.3gpp.mcdata-info+xml", + "application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml", + "application/vnd.3gpp.mcdata-regroup+xml", + "application/vnd.3gpp.mcdata-service-config+xml", + "application/vnd.3gpp.mcdata-ue-config+xml", + "application/vnd.3gpp.mcdata-user-profile+xml", + "application/vnd.3gpp.mcptt-affiliation-command+xml", + "application/vnd.3gpp.mcptt-floor-request+xml", + "application/vnd.3gpp.mcptt-info+xml", + "application/vnd.3gpp.mcptt-location-info+xml", + "application/vnd.3gpp.mcptt-mbms-usage-info+xml", + "application/vnd.3gpp.mcptt-regroup+xml", + "application/vnd.3gpp.mcptt-service-config+xml", + "application/vnd.3gpp.mcptt-signed+xml", + "application/vnd.3gpp.mcptt-ue-config+xml", + "application/vnd.3gpp.mcptt-ue-init-config+xml", + "application/vnd.3gpp.mcptt-user-profile+xml", + "application/vnd.3gpp.mcvideo-affiliation-command+xml", + "application/vnd.3gpp.mcvideo-affiliation-info+xml", + "application/vnd.3gpp.mcvideo-info+xml", + "application/vnd.3gpp.mcvideo-location-info+xml", + "application/vnd.3gpp.mcvideo-mbms-usage-info+xml", + "application/vnd.3gpp.mcvideo-regroup+xml", + "application/vnd.3gpp.mcvideo-service-config+xml", + "application/vnd.3gpp.mcvideo-transmission-request+xml", + "application/vnd.3gpp.mcvideo-ue-config+xml", + "application/vnd.3gpp.mcvideo-user-profile+xml", + "application/vnd.3gpp.mid-call+xml", + "application/vnd.3gpp.pinapp-info+xml", + "application/vnd.3gpp-prose-pc3a+xml", + "application/vnd.3gpp-prose-pc3ach+xml", + "application/vnd.3gpp-prose-pc3ch+xml", + "application/vnd.3gpp-prose-pc8+xml", + "application/vnd.3gpp-prose+xml", + "application/vnd.3gpp.seal-group-doc+xml", + "application/vnd.3gpp.seal-info+xml", + "application/vnd.3gpp.seal-location-info+xml", + "application/vnd.3gpp.seal-mbms-usage-info+xml", + "application/vnd.3gpp.seal-network-QoS-management-info+xml", + "application/vnd.3gpp.seal-ue-config-info+xml", + "application/vnd.3gpp.seal-unicast-info+xml", + "application/vnd.3gpp.seal-user-profile-info+xml", + "application/vnd.3gpp.sms+xml", + "application/vnd.3gpp.srvcc-ext+xml", + "application/vnd.3gpp.SRVCC-info+xml", + "application/vnd.3gpp.state-and-event-info+xml", + "application/vnd.3gpp.ussd+xml", + "application/vnd.3gpp.vae-info+xml", + "application/vnd.3gpp2.bcmcsinfo+xml", + "application/vnd.adobe.xdp+xml", + "application/vnd.amundsen.maze+xml", + "application/vnd.apple.installer+xml", + "application/vnd.avistar+xml", + "application/vnd.balsamiq.bmml+xml", + "application/vnd.biopax.rdf+xml", + "application/vnd.c3voc.schedule+xml", + "application/vnd.chemdraw+xml", + "application/vnd.citationstyles.style+xml", + "application/vnd.criticaltools.wbs+xml", + "application/vnd.ctct.ws+xml", + "application/vnd.cyan.dean.root+xml", + "application/vnd.cyclonedx+xml", + "application/vnd.dece.ttml+xml", + "application/vnd.dm.delegation+xml", + "application/vnd.dvb.dvbisl+xml", + "application/vnd.dvb.notif-aggregate-root+xml", + "application/vnd.dvb.notif-container+xml", + "application/vnd.dvb.notif-generic+xml", + "application/vnd.dvb.notif-ia-msglist+xml", + "application/vnd.dvb.notif-ia-registration-request+xml", + "application/vnd.dvb.notif-ia-registration-response+xml", + "application/vnd.dvb.notif-init+xml", + "application/vnd.emclient.accessrequest+xml", + "application/vnd.eprints.data+xml", + "application/vnd.eszigno3+xml", + "application/vnd.etsi.aoc+xml", + "application/vnd.etsi.cug+xml", + "application/vnd.etsi.iptvcommand+xml", + "application/vnd.etsi.iptvdiscovery+xml", + "application/vnd.etsi.iptvprofile+xml", + "application/vnd.etsi.iptvsad-bc+xml", + "application/vnd.etsi.iptvsad-cod+xml", + "application/vnd.etsi.iptvsad-npvr+xml", + "application/vnd.etsi.iptvservice+xml", + "application/vnd.etsi.iptvsync+xml", + "application/vnd.etsi.iptvueprofile+xml", + "application/vnd.etsi.mcid+xml", + "application/vnd.etsi.overload-control-policy-dataset+xml", + "application/vnd.etsi.pstn+xml", + "application/vnd.etsi.sci+xml", + "application/vnd.etsi.simservs+xml", + "application/vnd.etsi.tsl+xml", + "application/vnd.fujifilm.fb.jfi+xml", + "application/vnd.gentoo.catmetadata+xml", + "application/vnd.gentoo.pkgmetadata+xml", + "application/vnd.geocube+xml", + "application/vnd.google-earth.kml+xml", + "application/vnd.gov.sk.e-form+xml", + "application/vnd.gov.sk.xmldatacontainer+xml", + "application/vnd.gpxsee.map+xml", + "application/vnd.hal+xml", + "application/vnd.HandHeld-Entertainment+xml", + "application/vnd.informedcontrol.rms+xml", + "application/vnd.infotech.project+xml", + "application/vnd.iptc.g2.catalogitem+xml", + "application/vnd.iptc.g2.conceptitem+xml", + "application/vnd.iptc.g2.knowledgeitem+xml", + "application/vnd.iptc.g2.newsitem+xml", + "application/vnd.iptc.g2.newsmessage+xml", + "application/vnd.iptc.g2.packageitem+xml", + "application/vnd.iptc.g2.planningitem+xml", + "application/vnd.irepository.package+xml", + "application/vnd.las.las+xml", + "application/vnd.liberty-request+xml", + "application/vnd.llamagraphics.life-balance.exchange+xml", + "application/vnd.marlin.drm.actiontoken+xml", + "application/vnd.marlin.drm.conftoken+xml", + "application/vnd.marlin.drm.license+xml", + "application/vnd.mozilla.xul+xml", + "application/vnd.ms-office.activeX+xml", + "application/vnd.ms-playready.initiator+xml", + "application/vnd.ms-PrintDeviceCapabilities+xml", + "application/vnd.ms-PrintSchemaTicket+xml", + "application/vnd.nato.bindingdataobject+xml", + "application/vnd.nokia.conml+xml", + "application/vnd.nokia.iptv.config+xml", + "application/vnd.nokia.landmark+xml", + "application/vnd.nokia.landmarkcollection+xml", + "application/vnd.nokia.n-gage.ac+xml", + "application/vnd.nokia.pcd+xml", + "application/vnd.oipf.contentaccessdownload+xml", + "application/vnd.oipf.contentaccessstreaming+xml", + "application/vnd.oipf.dae.svg+xml", + "application/vnd.oipf.dae.xhtml+xml", + "application/vnd.oipf.mippvcontrolmessage+xml", + "application/vnd.oipf.spdiscovery+xml", + "application/vnd.oipf.spdlist+xml", + "application/vnd.oipf.ueprofile+xml", + "application/vnd.oipf.userprofile+xml", + "application/vnd.oma.bcast.associated-procedure-parameter+xml", + "application/vnd.oma.bcast.drm-trigger+xml", + "application/vnd.oma.bcast.imd+xml", + "application/vnd.oma.bcast.notification+xml", + "application/vnd.oma.bcast.sgdd+xml", + "application/vnd.oma.bcast.smartcard-trigger+xml", + "application/vnd.oma.bcast.sprov+xml", + "application/vnd.oma.cab-address-book+xml", + "application/vnd.oma.cab-feature-handler+xml", + "application/vnd.oma.cab-pcc+xml", + "application/vnd.oma.cab-subs-invite+xml", + "application/vnd.oma.cab-user-prefs+xml", + "application/vnd.oma.dd2+xml", + "application/vnd.oma.drm.risd+xml", + "application/vnd.oma.group-usage-list+xml", + "application/vnd.oma.pal+xml", + "application/vnd.oma.poc.detailed-progress-report+xml", + "application/vnd.oma.poc.final-report+xml", + "application/vnd.oma.poc.groups+xml", + "application/vnd.oma.poc.invocation-descriptor+xml", + "application/vnd.oma.poc.optimized-progress-report+xml", + "application/vnd.oma.scidm.messages+xml", + "application/vnd.oma.xcap-directory+xml", + "application/vnd.omads-email+xml", + "application/vnd.omads-file+xml", + "application/vnd.omads-folder+xml", + "application/vnd.openblox.game+xml", + "application/vnd.openstreetmap.data+xml", + "application/vnd.openxmlformats-officedocument.custom-properties+xml", + "application/vnd.openxmlformats-officedocument.customXmlProperties+xml", + "application/vnd.openxmlformats-officedocument.drawing+xml", + "application/vnd.openxmlformats-officedocument.drawingml.chart+xml", + "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml", + "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml", + "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml", + "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml", + "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml", + "application/vnd.openxmlformats-officedocument.extended-properties+xml", + "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml", + "application/vnd.openxmlformats-officedocument.presentationml.comments+xml", + "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml", + "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml", + "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml", + "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml", + "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slide+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml", + "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml", + "application/vnd.openxmlformats-officedocument.presentationml.tags+xml", + "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml", + "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", + "application/vnd.openxmlformats-officedocument.theme+xml", + "application/vnd.openxmlformats-officedocument.themeOverride+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", + "application/vnd.openxmlformats-package.core-properties+xml", + "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml", + "application/vnd.openxmlformats-package.relationships+xml", + "application/vnd.otps.ct-kip+xml", + "application/vnd.paos.xml", + "application/vnd.poc.group-advertisement+xml", + "application/vnd.pwg-xhtml-print+xml", + "application/vnd.radisys.moml+xml", + "application/vnd.radisys.msml-audit-conf+xml", + "application/vnd.radisys.msml-audit-conn+xml", + "application/vnd.radisys.msml-audit-dialog+xml", + "application/vnd.radisys.msml-audit-stream+xml", + "application/vnd.radisys.msml-audit+xml", + "application/vnd.radisys.msml-conf+xml", + "application/vnd.radisys.msml-dialog-base+xml", + "application/vnd.radisys.msml-dialog-fax-detect+xml", + "application/vnd.radisys.msml-dialog-fax-sendrecv+xml", + "application/vnd.radisys.msml-dialog-group+xml", + "application/vnd.radisys.msml-dialog-speech+xml", + "application/vnd.radisys.msml-dialog-transform+xml", + "application/vnd.radisys.msml-dialog+xml", + "application/vnd.radisys.msml+xml", + "application/vnd.recordare.musicxml+xml", + "application/vnd.route66.link66+xml", + "application/vnd.software602.filler.form+xml", + "application/vnd.solent.sdkm+xml", + "application/vnd.sun.wadl+xml", + "application/vnd.sycle+xml", + "application/vnd.syncml.dmddf+xml", + "application/vnd.syncml.dmtnds+xml", + "application/vnd.syncml.dm+xml", + "application/vnd.syncml+xml", + "application/vnd.tmd.mediaflex.api+xml", + "application/vnd.uoml+xml", + "application/vnd.wv.csp+xml", + "application/vnd.wv.ssp+xml", + "application/vnd.xmi+xml", + "application/vnd.yamaha.openscoreformat.osfpvg+xml", + "application/vnd.zzazz.deck+xml", + "application/voicexml+xml", + "application/watcherinfo+xml", + "application/wsdl+xml", + "application/wspolicy+xml", + "application/xacml+xml", + "application/xcap-att+xml", + "application/xcap-caps+xml", + "application/xcap-diff+xml", + "application/xcap-el+xml", + "application/xcap-error+xml", + "application/xcap-ns+xml", + "application/xcon-conference-info-diff+xml", + "application/xcon-conference-info+xml", + "application/xenc+xml", + "application/xhtml+xml", + "application/xliff+xml", + "application/xml", + "application/xml-dtd", + "application/xml-external-parsed-entity", + "application/xml-patch+xml", + "application/xmpp+xml", + "application/xop+xml", + "application/xslt+xml", + "application/xv+xml", + "application/yang-data+xml", + "application/yang-patch+xml", + "application/yin+xml", + ]; + for mime in &mime_types { + assert!(is_xml(mime), "{mime} is a not a XML mime type"); + } + } }