Skip to content

Commit 0d80886

Browse files
authored
fix: parse URL response Content-Type according to RFC 9110 (#2950)
Currently, `file_and_type_from_url()` does not correctly handle the `Content-Type` header. Specifically, it assumes that the header contains only the mime-type (e.g. `text/html`), however, [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110#field.content-type) allows for additional directives — specifically the `charset` — to be returned in the header. This leads to a `ValueError` when loading a URL with a response Content-Type header such as `text/html; charset=UTF-8`. To reproduce the issue: ```python from unstructured.partition.auto import partition url = "https://arstechnica.com/space/2024/04/nasa-still-doesnt-understand-root-cause-of-orion-heat-shield-issue/" partition(url=url) ``` Which will result in the following exception: ```python { "name": "ValueError", "message": "Invalid file. The FileType.UNK file type is not supported in partition.", "stack": "--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[1], line 4 1 from unstructured.partition.auto import partition 3 url = \"https://arstechnica.com/space/2024/04/nasa-still-doesnt-understand-root-cause-of-orion-heat-shield-issue/\" ----> 4 partition(url=url) File ~/miniconda3/envs/ai-tasks/lib/python3.11/site-packages/unstructured/partition/auto.py:541, in partition(filename, content_type, file, file_filename, url, include_page_breaks, strategy, encoding, paragraph_grouper, headers, skip_infer_table_types, ssl_verify, ocr_languages, languages, detect_language_per_element, pdf_infer_table_structure, extract_images_in_pdf, extract_image_block_types, extract_image_block_output_dir, extract_image_block_to_payload, xml_keep_tags, data_source_metadata, metadata_filename, request_timeout, hi_res_model_name, model_name, date_from_file_object, starting_page_number, **kwargs) 539 else: 540 msg = \"Invalid file\" if not filename else f\"Invalid file {filename}\" --> 541 raise ValueError(f\"{msg}. The {filetype} file type is not supported in partition.\") 543 for element in elements: 544 element.metadata.url = url ValueError: Invalid file. The FileType.UNK file type is not supported in partition." } ``` This PR fixes the issue by parsing the mime-type out of the `Content-Type` header string. Closes #2257
1 parent 7720e72 commit 0d80886

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

Diff for: CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 0.13.6
2+
3+
### Enhancements
4+
5+
### Features
6+
7+
### Fixes
8+
9+
- **ValueError: Invalid file (FileType.UNK) when parsing Content-Type header with charset directive** URL response Content-Type headers are now parsed according to RFC 9110.
10+
111
## 0.13.5
212

313
### Enhancements

Diff for: test_unstructured/partition/test_auto.py

+16
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,22 @@ def test_auto_partition_from_url():
609609
assert elements[0].metadata.url == url
610610

611611

612+
def test_auto_partition_from_url_with_rfc9110_content_type():
613+
url = "https://raw.githubusercontent.com/Unstructured-IO/unstructured/main/LICENSE.md"
614+
elements = partition(
615+
url=url, content_type="text/plain; charset=utf-8", strategy=PartitionStrategy.HI_RES
616+
)
617+
assert elements[0] == Title("Apache License")
618+
assert elements[0].metadata.url == url
619+
620+
621+
def test_auto_partition_from_url_without_providing_content_type():
622+
url = "https://raw.githubusercontent.com/Unstructured-IO/unstructured/main/LICENSE.md"
623+
elements = partition(url=url, strategy=PartitionStrategy.HI_RES)
624+
assert elements[0] == Title("Apache License")
625+
assert elements[0].metadata.url == url
626+
627+
612628
def test_partition_md_works_with_embedded_html():
613629
url = "https://raw.githubusercontent.com/Unstructured-IO/unstructured/main/README.md"
614630
elements = partition(url=url, content_type="text/markdown", strategy=PartitionStrategy.HI_RES)

Diff for: unstructured/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.13.5" # pragma: no cover
1+
__version__ = "0.13.6" # pragma: no cover

Diff for: unstructured/partition/auto.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,9 @@ def file_and_type_from_url(
564564
response = requests.get(url, headers=headers, verify=ssl_verify, timeout=request_timeout)
565565
file = io.BytesIO(response.content)
566566

567-
content_type = content_type or response.headers.get("Content-Type")
567+
content_type = (
568+
content_type or response.headers.get("Content-Type", "").split(";")[0].strip().lower()
569+
)
568570
encoding = response.headers.get("Content-Encoding", "utf-8")
569571

570572
filetype = detect_filetype(file=file, content_type=content_type, encoding=encoding)

0 commit comments

Comments
 (0)