We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
refactoring curl_to_request_kwargs to reduce cyclomatic complexity
<!--

Thanks for taking an interest in Scrapy!

If you have a question that starts with "How to...", please see the Scrapy Community page: https://scrapy.org/community/.
The GitHub issue tracker's purpose is to deal with bug reports and feature requests for the project itself.

Keep in mind that by filing an issue, you are expected to comply with Scrapy's Code of Conduct, including treating everyone with respect: https://github.com/scrapy/scrapy/blob/master/CODE_OF_CONDUCT.md

The following is a suggested template to structure your pull request, you can find more guidelines at https://doc.scrapy.org/en/latest/contributing.html#writing-patches and https://doc.scrapy.org/en/latest/contributing.html#submitting-patches

-->

## Summary

After some exploring with cyclomatic complexity tools (lizard), the function was found to have the second highest complexity. 

## Motivation

Low complexity allows for higher readability, testability and maintainability. 

## Solution

Refactor

## Additional context

N/A


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scrapy/utils/curl.py`
Content:
```
1 import argparse
2 import warnings
3 from shlex import split
4 from http.cookies import SimpleCookie
5 from urllib.parse import urlparse
6 
7 from w3lib.http import basic_auth_header
8 
9 
10 class CurlParser(argparse.ArgumentParser):
11     def error(self, message):
12         error_msg = f'There was an error parsing the curl command: {message}'
13         raise ValueError(error_msg)
14 
15 
16 curl_parser = CurlParser()
17 curl_parser.add_argument('url')
18 curl_parser.add_argument('-H', '--header', dest='headers', action='append')
19 curl_parser.add_argument('-X', '--request', dest='method')
20 curl_parser.add_argument('-d', '--data', '--data-raw', dest='data')
21 curl_parser.add_argument('-u', '--user', dest='auth')
22 
23 
24 safe_to_ignore_arguments = [
25     ['--compressed'],
26     # `--compressed` argument is not safe to ignore, but it's included here
27     # because the `HttpCompressionMiddleware` is enabled by default
28     ['-s', '--silent'],
29     ['-v', '--verbose'],
30     ['-#', '--progress-bar']
31 ]
32 
33 for argument in safe_to_ignore_arguments:
34     curl_parser.add_argument(*argument, action='store_true')
35 
36 
37 def curl_to_request_kwargs(curl_command, ignore_unknown_options=True):
38     """Convert a cURL command syntax to Request kwargs.
39 
40     :param str curl_command: string containing the curl command
41     :param bool ignore_unknown_options: If true, only a warning is emitted when
42                                         cURL options are unknown. Otherwise
43                                         raises an error. (default: True)
44     :return: dictionary of Request kwargs
45     """
46 
47     curl_args = split(curl_command)
48 
49     if curl_args[0] != 'curl':
50         raise ValueError('A curl command must start with "curl"')
51 
52     parsed_args, argv = curl_parser.parse_known_args(curl_args[1:])
53 
54     if argv:
55         msg = f'Unrecognized options: {", ".join(argv)}'
56         if ignore_unknown_options:
57             warnings.warn(msg)
58         else:
59             raise ValueError(msg)
60 
61     url = parsed_args.url
62 
63     # curl automatically prepends 'http' if the scheme is missing, but Request
64     # needs the scheme to work
65     parsed_url = urlparse(url)
66     if not parsed_url.scheme:
67         url = 'http://' + url
68 
69     method = parsed_args.method or 'GET'
70 
71     result = {'method': method.upper(), 'url': url}
72 
73     headers = []
74     cookies = {}
75     for header in parsed_args.headers or ():
76         name, val = header.split(':', 1)
77         name = name.strip()
78         val = val.strip()
79         if name.title() == 'Cookie':
80             for name, morsel in SimpleCookie(val).items():
81                 cookies[name] = morsel.value
82         else:
83             headers.append((name, val))
84 
85     if parsed_args.auth:
86         user, password = parsed_args.auth.split(':', 1)
87         headers.append(('Authorization', basic_auth_header(user, password)))
88 
89     if headers:
90         result['headers'] = headers
91     if cookies:
92         result['cookies'] = cookies
93     if parsed_args.data:
94         result['body'] = parsed_args.data
95         if not parsed_args.method:
96             # if the "data" is specified but the "method" is not specified,
97             # the default method is 'POST'
98             result['method'] = 'POST'
99 
100     return result
101
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scrapy/utils/curl.py b/scrapy/utils/curl.py
--- a/scrapy/utils/curl.py
+++ b/scrapy/utils/curl.py
@@ -34,6 +34,26 @@
     curl_parser.add_argument(*argument, action='store_true')
 
 
+def _parse_headers_and_cookies(parsed_args):
+    headers = []
+    cookies = {}
+    for header in parsed_args.headers or ():
+        name, val = header.split(':', 1)
+        name = name.strip()
+        val = val.strip()
+        if name.title() == 'Cookie':
+            for name, morsel in SimpleCookie(val).items():
+                cookies[name] = morsel.value
+        else:
+            headers.append((name, val))
+
+    if parsed_args.auth:
+        user, password = parsed_args.auth.split(':', 1)
+        headers.append(('Authorization', basic_auth_header(user, password)))
+
+    return headers, cookies
+
+
 def curl_to_request_kwargs(curl_command, ignore_unknown_options=True):
     """Convert a cURL command syntax to Request kwargs.
 
@@ -70,21 +90,7 @@
 
     result = {'method': method.upper(), 'url': url}
 
-    headers = []
-    cookies = {}
-    for header in parsed_args.headers or ():
-        name, val = header.split(':', 1)
-        name = name.strip()
-        val = val.strip()
-        if name.title() == 'Cookie':
-            for name, morsel in SimpleCookie(val).items():
-                cookies[name] = morsel.value
-        else:
-            headers.append((name, val))
-
-    if parsed_args.auth:
-        user, password = parsed_args.auth.split(':', 1)
-        headers.append(('Authorization', basic_auth_header(user, password)))
+    headers, cookies = _parse_headers_and_cookies(parsed_args)
 
     if headers:
         result['headers'] = headers

{"golden_diff": "diff --git a/scrapy/utils/curl.py b/scrapy/utils/curl.py\n--- a/scrapy/utils/curl.py\n+++ b/scrapy/utils/curl.py\n@@ -34,6 +34,26 @@\n     curl_parser.add_argument(*argument, action='store_true')\n \n \n+def _parse_headers_and_cookies(parsed_args):\n+    headers = []\n+    cookies = {}\n+    for header in parsed_args.headers or ():\n+        name, val = header.split(':', 1)\n+        name = name.strip()\n+        val = val.strip()\n+        if name.title() == 'Cookie':\n+            for name, morsel in SimpleCookie(val).items():\n+                cookies[name] = morsel.value\n+        else:\n+            headers.append((name, val))\n+\n+    if parsed_args.auth:\n+        user, password = parsed_args.auth.split(':', 1)\n+        headers.append(('Authorization', basic_auth_header(user, password)))\n+\n+    return headers, cookies\n+\n+\n def curl_to_request_kwargs(curl_command, ignore_unknown_options=True):\n     \"\"\"Convert a cURL command syntax to Request kwargs.\n \n@@ -70,21 +90,7 @@\n \n     result = {'method': method.upper(), 'url': url}\n \n-    headers = []\n-    cookies = {}\n-    for header in parsed_args.headers or ():\n-        name, val = header.split(':', 1)\n-        name = name.strip()\n-        val = val.strip()\n-        if name.title() == 'Cookie':\n-            for name, morsel in SimpleCookie(val).items():\n-                cookies[name] = morsel.value\n-        else:\n-            headers.append((name, val))\n-\n-    if parsed_args.auth:\n-        user, password = parsed_args.auth.split(':', 1)\n-        headers.append(('Authorization', basic_auth_header(user, password)))\n+    headers, cookies = _parse_headers_and_cookies(parsed_args)\n \n     if headers:\n         result['headers'] = headers\n", "issue": "refactoring curl_to_request_kwargs to reduce cyclomatic complexity\n<!--\r\n\r\nThanks for taking an interest in Scrapy!\r\n\r\nIf you have a question that starts with \"How to...\", please see the Scrapy Community page: https://scrapy.org/community/.\r\nThe GitHub issue tracker's purpose is to deal with bug reports and feature requests for the project itself.\r\n\r\nKeep in mind that by filing an issue, you are expected to comply with Scrapy's Code of Conduct, including treating everyone with respect: https://github.com/scrapy/scrapy/blob/master/CODE_OF_CONDUCT.md\r\n\r\nThe following is a suggested template to structure your pull request, you can find more guidelines at https://doc.scrapy.org/en/latest/contributing.html#writing-patches and https://doc.scrapy.org/en/latest/contributing.html#submitting-patches\r\n\r\n-->\r\n\r\n## Summary\r\n\r\nAfter some exploring with cyclomatic complexity tools (lizard), the function was found to have the second highest complexity. \r\n\r\n## Motivation\r\n\r\nLow complexity allows for higher readability, testability and maintainability. \r\n\r\n## Solution\r\n\r\nRefactor\r\n\r\n## Additional context\r\n\r\nN/A\r\n\n", "before_files": [{"content": "import argparse\nimport warnings\nfrom shlex import split\nfrom http.cookies import SimpleCookie\nfrom urllib.parse import urlparse\n\nfrom w3lib.http import basic_auth_header\n\n\nclass CurlParser(argparse.ArgumentParser):\n    def error(self, message):\n        error_msg = f'There was an error parsing the curl command: {message}'\n        raise ValueError(error_msg)\n\n\ncurl_parser = CurlParser()\ncurl_parser.add_argument('url')\ncurl_parser.add_argument('-H', '--header', dest='headers', action='append')\ncurl_parser.add_argument('-X', '--request', dest='method')\ncurl_parser.add_argument('-d', '--data', '--data-raw', dest='data')\ncurl_parser.add_argument('-u', '--user', dest='auth')\n\n\nsafe_to_ignore_arguments = [\n    ['--compressed'],\n    # `--compressed` argument is not safe to ignore, but it's included here\n    # because the `HttpCompressionMiddleware` is enabled by default\n    ['-s', '--silent'],\n    ['-v', '--verbose'],\n    ['-#', '--progress-bar']\n]\n\nfor argument in safe_to_ignore_arguments:\n    curl_parser.add_argument(*argument, action='store_true')\n\n\ndef curl_to_request_kwargs(curl_command, ignore_unknown_options=True):\n    \"\"\"Convert a cURL command syntax to Request kwargs.\n\n    :param str curl_command: string containing the curl command\n    :param bool ignore_unknown_options: If true, only a warning is emitted when\n                                        cURL options are unknown. Otherwise\n                                        raises an error. (default: True)\n    :return: dictionary of Request kwargs\n    \"\"\"\n\n    curl_args = split(curl_command)\n\n    if curl_args[0] != 'curl':\n        raise ValueError('A curl command must start with \"curl\"')\n\n    parsed_args, argv = curl_parser.parse_known_args(curl_args[1:])\n\n    if argv:\n        msg = f'Unrecognized options: {\", \".join(argv)}'\n        if ignore_unknown_options:\n            warnings.warn(msg)\n        else:\n            raise ValueError(msg)\n\n    url = parsed_args.url\n\n    # curl automatically prepends 'http' if the scheme is missing, but Request\n    # needs the scheme to work\n    parsed_url = urlparse(url)\n    if not parsed_url.scheme:\n        url = 'http://' + url\n\n    method = parsed_args.method or 'GET'\n\n    result = {'method': method.upper(), 'url': url}\n\n    headers = []\n    cookies = {}\n    for header in parsed_args.headers or ():\n        name, val = header.split(':', 1)\n        name = name.strip()\n        val = val.strip()\n        if name.title() == 'Cookie':\n            for name, morsel in SimpleCookie(val).items():\n                cookies[name] = morsel.value\n        else:\n            headers.append((name, val))\n\n    if parsed_args.auth:\n        user, password = parsed_args.auth.split(':', 1)\n        headers.append(('Authorization', basic_auth_header(user, password)))\n\n    if headers:\n        result['headers'] = headers\n    if cookies:\n        result['cookies'] = cookies\n    if parsed_args.data:\n        result['body'] = parsed_args.data\n        if not parsed_args.method:\n            # if the \"data\" is specified but the \"method\" is not specified,\n            # the default method is 'POST'\n            result['method'] = 'POST'\n\n    return result\n", "path": "scrapy/utils/curl.py"}], "after_files": [{"content": "import argparse\nimport warnings\nfrom shlex import split\nfrom http.cookies import SimpleCookie\nfrom urllib.parse import urlparse\n\nfrom w3lib.http import basic_auth_header\n\n\nclass CurlParser(argparse.ArgumentParser):\n    def error(self, message):\n        error_msg = f'There was an error parsing the curl command: {message}'\n        raise ValueError(error_msg)\n\n\ncurl_parser = CurlParser()\ncurl_parser.add_argument('url')\ncurl_parser.add_argument('-H', '--header', dest='headers', action='append')\ncurl_parser.add_argument('-X', '--request', dest='method')\ncurl_parser.add_argument('-d', '--data', '--data-raw', dest='data')\ncurl_parser.add_argument('-u', '--user', dest='auth')\n\n\nsafe_to_ignore_arguments = [\n    ['--compressed'],\n    # `--compressed` argument is not safe to ignore, but it's included here\n    # because the `HttpCompressionMiddleware` is enabled by default\n    ['-s', '--silent'],\n    ['-v', '--verbose'],\n    ['-#', '--progress-bar']\n]\n\nfor argument in safe_to_ignore_arguments:\n    curl_parser.add_argument(*argument, action='store_true')\n\n\ndef _parse_headers_and_cookies(parsed_args):\n    headers = []\n    cookies = {}\n    for header in parsed_args.headers or ():\n        name, val = header.split(':', 1)\n        name = name.strip()\n        val = val.strip()\n        if name.title() == 'Cookie':\n            for name, morsel in SimpleCookie(val).items():\n                cookies[name] = morsel.value\n        else:\n            headers.append((name, val))\n\n    if parsed_args.auth:\n        user, password = parsed_args.auth.split(':', 1)\n        headers.append(('Authorization', basic_auth_header(user, password)))\n\n    return headers, cookies\n\n\ndef curl_to_request_kwargs(curl_command, ignore_unknown_options=True):\n    \"\"\"Convert a cURL command syntax to Request kwargs.\n\n    :param str curl_command: string containing the curl command\n    :param bool ignore_unknown_options: If true, only a warning is emitted when\n                                        cURL options are unknown. Otherwise\n                                        raises an error. (default: True)\n    :return: dictionary of Request kwargs\n    \"\"\"\n\n    curl_args = split(curl_command)\n\n    if curl_args[0] != 'curl':\n        raise ValueError('A curl command must start with \"curl\"')\n\n    parsed_args, argv = curl_parser.parse_known_args(curl_args[1:])\n\n    if argv:\n        msg = f'Unrecognized options: {\", \".join(argv)}'\n        if ignore_unknown_options:\n            warnings.warn(msg)\n        else:\n            raise ValueError(msg)\n\n    url = parsed_args.url\n\n    # curl automatically prepends 'http' if the scheme is missing, but Request\n    # needs the scheme to work\n    parsed_url = urlparse(url)\n    if not parsed_url.scheme:\n        url = 'http://' + url\n\n    method = parsed_args.method or 'GET'\n\n    result = {'method': method.upper(), 'url': url}\n\n    headers, cookies = _parse_headers_and_cookies(parsed_args)\n\n    if headers:\n        result['headers'] = headers\n    if cookies:\n        result['cookies'] = cookies\n    if parsed_args.data:\n        result['body'] = parsed_args.data\n        if not parsed_args.method:\n            # if the \"data\" is specified but the \"method\" is not specified,\n            # the default method is 'POST'\n            result['method'] = 'POST'\n\n    return result\n", "path": "scrapy/utils/curl.py"}]}