Metadata-Version: 2.4
Name: parse-http-header-line
Version: 0.1.0
Summary: Parse HTTP header field lines into their names and values, and split `type; name=value` parameter lists.
Author-email: Jifeng Wu <jifengwu2k@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/jifengwu2k/parse-http-header-line
Project-URL: Bug Tracker, https://github.com/jifengwu2k/parse-http-header-line/issues
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=2
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: enum34; python_version < "3.4"
Requires-Dist: typing; python_version < "3.5"
Dynamic: license-file

# parse-http-header-line

Parse HTTP header field lines into their names and values, and split
`type; name=value` parameter lists.

## Installation

```bash
pip install parse-http-header-line
```

## Quick start

```python
from parse_http_header_line import parse_name_value, parse_parameters

parse_name_value(u"Content-Type: text/html\r\n")
# ("content-type", "text/html")

parse_name_value(u"Host: example.com")
# ("host", "example.com")

parse_parameters(u"multipart/form-data; boundary=abc=def")
# ("multipart/form-data", [("boundary", "abc=def")])

parse_parameters(u'form-data; name="file"; filename="hello.txt"')
# ("form-data", [("name", "file"), ("filename", "hello.txt")])
```

## API

### `parse_name_value(line)`

Parses one header field line and returns a `(name, value)` tuple.

| Return | Description |
| ------ | ----------- |
| `name` | Field name, lowercased. |
| `value` | Field value with leading/trailing spaces and tabs removed. |

- `line` is Latin-1 text, with or without a trailing CRLF.
- On Python 3, `line` is `str`; on Python 2, it is `unicode`.
- Bytes are rejected with `TypeError`.

```python
parse_name_value(u"Host: example.com")
# ("host", "example.com")

parse_name_value(u"Host: example.com:8080\r\n")
# ("host", "example.com:8080")

parse_name_value(u"X-Empty:\r\n")
# ("x-empty", "")

parse_name_value(u"X: caf\xe9\r\n")       # obs-text is allowed
# ("x", "café")
```

Names are lowercased and surrounding whitespace is trimmed from the value:

```python
parse_name_value(u"CONTENT-TYPE:\t text/html \t\r\n")
# ("content-type", "text/html")
```

The value is returned exactly as written (minus surrounding whitespace); no
value grammar is applied. To interpret a value, parse the line first and then
choose a semantic parser based on the name:

```python
name, value = parse_name_value(
    u'Content-Disposition: form-data; name="file"; filename="hello.txt"\r\n'
)
if name == "content-disposition":
    type_text, parameters = parse_parameters(value)
    # type_text  == "form-data"
    # parameters == [("name", "file"), ("filename", "hello.txt")]
```

### `parse_parameters(value)`

Splits a `type; name=value; ...` value into a `(type_text, parameters)` tuple.

- `type_text` is the leading type (a token or `type/subtype`), lowercased.
- `parameters` is an ordered list of `(name, value)` pairs. Order and
  duplicate names are preserved. Parameter names are lowercased.

```python
parse_parameters(u"multipart/form-data; boundary=abc=def")
# ("multipart/form-data", [("boundary", "abc=def")])

parse_parameters(u'x; v="a;b"')
# ("x", [("v", "a;b")])

parse_parameters(u'form-data; name="a\\"b"')
# ("form-data", [("name", 'a"b')])
```

Quoted values are unquoted, and a backslash escapes the next character.
Unquoted values extend to the next `;`, preserving `=` and other characters in
boundary values.

Do **not** use `parse_parameters` for every field that contains a semicolon.
Fields such as `Set-Cookie`, `Link`, `Accept`, and authentication headers have
their own grammars.

## Scanner helpers

Two position-based helpers are exported for use with the module's state
machines:

- `skip_ows(text, position)` — returns the first position after spaces and tabs.
- `consume_token(text, position)` — returns the first position after RFC 7230
  token characters.

## Errors

`parse_name_value` raises `MalformedHeaderLineError` for invalid field-line
syntax:

```python
parse_name_value(u"\r\n")                 # empty line
parse_name_value(u" folded\r\n")          # obsolete folded line
parse_name_value(u"no-colon\r\n")         # missing ':'
parse_name_value(u": value\r\n")          # empty field name
parse_name_value(u"bad name: v\r\n")      # space in field name
parse_name_value(u"X: bad\x7fvalue\r\n")  # DEL in field value
```

`parse_parameters` raises `MalformedParameterListError` when its argument is
not a well-formed parameterized value:

```python
parse_parameters(u"form-data; name")  # parameter has no '='
```

## Testing

```bash
python -m unittest discover -s tests
```

## License

This project is licensed under the [MIT License](LICENSE).
