Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions httptools/parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .protocol import HTTPProtocol
from .parser import * # NoQA
from .errors import * # NoQA
from .url_parser import * # NoQA
Expand Down
58 changes: 58 additions & 0 deletions httptools/parser/parser.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from typing import Union, Any
from array import array
from .protocol import HTTPProtocol



class HttpParser:
def __init__(self, protocol:Union[HTTPProtocol, Any]) -> None:
"""
protocol -- a Python object with the following methods
(all optional):

- on_message_begin()
- on_url(url: bytes)
- on_header(name: bytes, value: bytes)
- on_headers_complete()
- on_body(body: bytes)
- on_message_complete()
- on_chunk_header()
- on_chunk_complete()
- on_status(status: bytes)
"""

def get_http_version(self) -> str:
"""Return an HTTP protocol version."""
...
def should_keep_alive(self) -> bool:
"""Return ``True`` if keep-alive mode is preferred."""
...
def should_upgrade(self) -> bool:
"""Return ``True`` if the parsed request is a valid Upgrade request.
The method exposes a flag set just before on_headers_complete.
Calling this method earlier will only yield `False`."""
...
def feed_data(self, data:Union[bytes, bytearray, memoryview, array]) -> None:
"""Feed data to the parser.

Will eventually trigger callbacks on the ``protocol``
object.

On HTTP upgrade, this method will raise an
``HttpParserUpgrade`` exception, with its sole argument
set to the offset of the non-HTTP data in ``data``.
"""


class HttpRequestParser(HttpParser):
"""Used for parsing http requests from the server's side"""

def get_method(self) -> bytes:
"""Return HTTP request method (GET, HEAD, etc)"""


class HttpResponseParser(HttpParser):
"""Used for parsing http requests from the client's side"""

def get_status_code(self) -> int:
"""Return the status code of the HTTP response"""
15 changes: 15 additions & 0 deletions httptools/parser/protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Protocol

class HTTPProtocol(Protocol):
"""Used for providing static type-checking when parsing through the http protocol"""

def on_message_begin() -> None:...
def on_url(url: bytes) -> None:...
def on_header(name: bytes, value: bytes) -> None:...
def on_headers_complete() -> None:...
def on_body(body: bytes) -> None:...
def on_message_complete() -> None:...
def on_chunk_header() -> None:...
def on_chunk_complete() -> None:...
def on_status(status: bytes) -> None:...

29 changes: 29 additions & 0 deletions httptools/parser/url_parser.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import Union
from array import array

class URL:
schema:bytes
host:bytes
port:int
path:bytes
query:bytes
fragment:bytes
userinfo:bytes

def parse_url(url:Union[bytes, bytearray, memoryview, array]) -> URL:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should add spaces after colons for type annotations

"""Parse URL strings into a structured Python object.

Returns an instance of ``httptools.URL`` class with the
following attributes:

- schema: bytes
- host: bytes
- port: int
- path: bytes
- query: bytes
- fragment: bytes
- userinfo: bytes
"""
...