diff --git a/responder/api.py b/responder/api.py index 72311ea..2cd7285 100644 --- a/responder/api.py +++ b/responder/api.py @@ -171,6 +171,11 @@ class API: if route_object.does_match(path): return route + def _prepare_cookies(self, resp): + if resp.cookies: + header = " ".join([f"{k}={v}" for k, v in resp.cookies.items()]) + resp.headers["Set-Cookie"] = header + async def _dispatch_request(self, req): # Set formats on Request object. req.formats = self.formats @@ -228,6 +233,8 @@ class API: else: self.default_response(req, resp) + self._prepare_cookies(resp) + return resp def add_route( diff --git a/responder/models.py b/responder/models.py index a1cd700..45656a5 100644 --- a/responder/models.py +++ b/responder/models.py @@ -1,17 +1,19 @@ import io import json import gzip +from http.cookies import SimpleCookie + import chardet import rfc3986 import graphene import yaml from requests.structures import CaseInsensitiveDict +from requests.cookies import RequestsCookieJar from starlette.datastructures import MutableHeaders from starlette.requests import Request as StarletteRequest from starlette.responses import Response as StarletteResponse - from urllib.parse import parse_qs from .status_codes import HTTP_200 @@ -125,6 +127,18 @@ class Request: """The parsed URL of the Request.""" return rfc3986.urlparse(self.full_url) + @property + def cookies(self): + cookies = RequestsCookieJar() + cookie_header = self.headers.get("cookie", "") + + # if cookie_header: + bc = SimpleCookie(cookie_header) + for k, v in bc.items(): + cookies[k] = v + + return cookies.get_dict() + @property def params(self): """A dictionary of the parsed query parameters used for the Request.""" @@ -211,6 +225,7 @@ class Response: "media", "headers", "formats", + "cookies", ] def __init__(self, req, *, formats): @@ -226,6 +241,7 @@ class Response: {} ) #: A Python dictionary of {Key: value}, representing the headers of the response. self.formats = formats + self.cookies = {} # req.cookies @property async def body(self): diff --git a/tests/test_responder.py b/tests/test_responder.py index 9b6a1ab..4147dff 100644 --- a/tests/test_responder.py +++ b/tests/test_responder.py @@ -369,3 +369,16 @@ def test_async_class_based_views(api, session): data = "frame" r = session.post(api.url_for(Resource), data=data) assert r.text == data + +def test_cookies(api, session): + @api.route("/") + def cookies(req, resp): + resp.media = {'cookies': req.cookies} + resp.cookies['sent'] = 'true' + + r = session.get(api.url_for(cookies), cookies={'hello': 'universe'}) + assert r.json() == {"cookies": {"hello": "universe"}} + assert 'sent' in r.cookies + + r = session.get(api.url_for(cookies)) + assert r.json() == {"cookies": {"sent": "true"}}