diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e841dd..8ec80d0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,12 +4,12 @@ - Python - `pip` -- `componentize-py` 0.16.0 +- `componentize-py` 0.17.2 Once you have `pip` installed, you can install `componentize-py` using: ```bash -pip install componentize-py==0.16.0 +pip install componentize-py==0.17.2 ``` ### Generating the bindings @@ -22,9 +22,11 @@ componentize-py \ -d src/spin_sdk/wit \ -w spin-all \ --import-interface-name fermyon:spin/postgres@2.0.0=postgres \ + --import-interface-name spin:postgres/postgres@3.0.0=spin_postgres_postgres \ + --import-interface-name fermyon:spin/sqlite@2.0.0=sqlite \ + --world-module spin_sdk.wit \ bindings \ - bindings \ - --world-module spin_sdk.wit + bindings rm -r src/spin_sdk/wit/imports src/spin_sdk/wit/exports mv bindings/spin_sdk/wit/* src/spin_sdk/wit/ rm -r bindings diff --git a/README.md b/README.md index f3da2e1..f202c6e 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ enter a virtual environment and then install the desired packages ```shell python -m venv .venv source .venv/bin/activate -pip install componentize-py==0.16.0 spin-sdk==3.3.1 mypy==1.8.0 +pip install componentize-py==0.17.2 spin-sdk==3.4.1 mypy==1.8.0 ``` ### Hello, World diff --git a/docs/v3/http/index.html b/docs/v3/http/index.html index 3db7af2..50f5070 100644 --- a/docs/v3/http/index.html +++ b/docs/v3/http/index.html @@ -3,19 +3,30 @@ - + spin_sdk.http API documentation - + @@ -45,18 +56,136 @@

Functions

def send(request: Request) ‑> Response
+
+ +Expand source code + +
def send(request: Request) -> Response:
+    """Send an HTTP request and return a response or raise an error"""
+    loop = PollLoop()
+    asyncio.set_event_loop(loop)
+    return loop.run_until_complete(send_async(request))
+

Send an HTTP request and return a response or raise an error

async def send_and_close(sink: Sink,
data: bytes)
+
+ +Expand source code + +
async def send_and_close(sink: Sink, data: bytes):
+    await sink.send(data)
+    sink.close()
+
async def send_async(request: Request) ‑> Response
+
+ +Expand source code + +
async def send_async(request: Request) -> Response:
+    match request.method:
+        case "GET":
+            method: Method = Method_Get()
+        case "HEAD":
+            method = Method_Head()
+        case "POST":
+            method = Method_Post()
+        case "PUT":
+            method = Method_Put()
+        case "DELETE":
+            method = Method_Delete()
+        case "CONNECT":
+            method = Method_Connect()
+        case "OPTIONS":
+            method = Method_Options()
+        case "TRACE":
+            method = Method_Trace()
+        case "PATCH":
+            method = Method_Patch()
+        case _:
+            method = Method_Other(request.method)
+    
+    url_parsed = parse.urlparse(request.uri)
+
+    match url_parsed.scheme:
+        case "http":
+            scheme: Scheme = Scheme_Http()
+        case "https":
+            scheme = Scheme_Https()
+        case "":
+            scheme = Scheme_Http()
+        case _:
+            scheme = Scheme_Other(url_parsed.scheme)
+
+    headers_dict = request.headers
+
+    # Add a `content-length` header if the caller didn't include one, but did
+    # specify a body:
+    if headers_dict.get('content-length') is None:
+        content_length = len(request.body) if request.body is not None else 0
+        # Make a copy rather than mutate in place, since the caller might not
+        # expect us to mutate it:
+        headers_dict = headers_dict.copy()
+        headers_dict['content-length'] = str(content_length)
+
+    headers = list(map(
+        lambda pair: (pair[0], bytes(pair[1], "utf-8")),
+        headers_dict.items()
+    ))
+
+    outgoing_request = OutgoingRequest(Fields.from_list(headers))
+    outgoing_request.set_method(method)
+    outgoing_request.set_scheme(scheme)
+    if url_parsed.netloc == '':
+        if scheme == "http":
+            authority = ":80"
+        else:
+            authority = ":443"
+    else:
+        authority = url_parsed.netloc
+
+    outgoing_request.set_authority(authority)
+
+    path_and_query = url_parsed.path
+    if url_parsed.query:
+        path_and_query += '?' + url_parsed.query
+    outgoing_request.set_path_with_query(path_and_query)
+
+    outgoing_body = request.body if request.body is not None else bytearray()
+    sink = Sink(outgoing_request.body())
+    incoming_response: IncomingResponse = (await asyncio.gather(
+        poll_loop.send(outgoing_request),
+        send_and_close(sink, outgoing_body)
+    ))[0]
+
+    response_body = Stream(incoming_response.consume())
+    body = bytearray()
+    while True:
+        chunk = await response_body.next()
+        if chunk is None:
+            headers = incoming_response.headers()
+            simple_response = Response(
+                incoming_response.status(),
+                dict(map(
+                    lambda pair: (pair[0], str(pair[1], "utf-8")),
+                    headers.entries()
+                )),
+                bytes(body)
+            )
+            headers.__exit__(None, None, None)
+            incoming_response.__exit__(None, None, None)
+            return simple_response
+        else:
+            body += chunk
+
@@ -69,18 +198,17 @@

Classes

(*args, **kwargs)
-

Simplified handler for incoming HTTP requests using blocking, buffered I/O.

Expand source code -
class IncomingHandler(exports.IncomingHandler):
+
class IncomingHandler(Base):
     """Simplified handler for incoming HTTP requests using blocking, buffered I/O."""
-    
+
     def handle_request(self, request: Request) -> Response:
         """Handle an incoming HTTP request and return a response or raise an error"""
         raise NotImplementedError
-    
+
     def handle(self, request: IncomingRequest, response_out: ResponseOutparam):
         method = request.method()
 
@@ -164,6 +292,7 @@ 

Classes

response_stream.__exit__(None, None, None) OutgoingBody.finish(response_body, None)
+

Simplified handler for incoming HTTP requests using blocking, buffered I/O.

Ancestors