diff --git a/izzylib/http_server_async/misc.py b/izzylib/http_server_async/misc.py index b06e83f..6f20b32 100644 --- a/izzylib/http_server_async/misc.py +++ b/izzylib/http_server_async/misc.py @@ -47,6 +47,9 @@ class Headers(DotDict): logging.warning('Do not set the "Cookie" or "Set-Cookie" headers') return + elif key == 'Date': + value = DateItem(value) + try: self[key].append(value) @@ -54,6 +57,15 @@ class Headers(DotDict): super().__setitem__(key, HeaderItem(key, value)) + def as_dict(self): + data = {} + + for k,v in self.items(): + data[k] = str(v) + + return data + + def getone(self, key, default=None): try: return self[key].one() @@ -298,3 +310,23 @@ class HeaderItem(list): def update(self, *items): for item in items: self.append(item) + + +class DateItem(str): + _datetime = None + + def __new__(cls, date): + new_date = str.__new__(cls, date) + new_date._datetime = datetime.strptime(date, '%a, %d %b %Y %H:%M:%S GMT').replace(tzinfo=UtcTime) + return new_date + + + @property + def utc(self): + return self._datetime.astimezone(UtcTime) + + + @property + def local(self): + return self._datetime.astimezone(LocalTime) + diff --git a/izzylib/http_server_async/request.py b/izzylib/http_server_async/request.py index 1ca10d8..e04784e 100644 --- a/izzylib/http_server_async/request.py +++ b/izzylib/http_server_async/request.py @@ -14,8 +14,8 @@ LocalTime = datetime.now(UtcTime).astimezone().tzinfo class Request: __slots__ = [ - '_body', '_form', '_reader', 'app', 'address', - 'method', 'path', 'version', 'headers', 'cookies', + '_body', '_form', '_reader', '_method', 'app', 'address', + 'path', 'version', 'headers', 'cookies', 'query', 'raw_query' ] @@ -27,6 +27,7 @@ class Request: self._reader = reader self._body = b'' self._form = DotDict() + self._method = None self.headers = Headers() self.cookies = Cookies() @@ -34,7 +35,6 @@ class Request: self.app = app self.address = address - self.method = None self.path = None self.version = None self.raw_query = None @@ -50,16 +50,19 @@ class Request: def __getattr__(self, key): if key in self.__slots__: - return super().__getattr__(self, key) + return super().__getattribute__(self, key) - return self.ctx[key] + try: + return self.ctx[key] + except: + raise AttributeError(key) def __setattr__(self, key, value): - if key in self.__slots__: + try: super().__setattr__(key, value) - else: + except: self.ctx[key] = value @@ -101,6 +104,16 @@ class Request: return self.headers.getone('X-Real-Ip', self.headers.getone('X-Forwarded-For', self.address)) + @property + def method(self): + return self._method + + + @method.setter + def method(self, data): + self._method = data.upper() + + async def read(self, length=2048, timeout=None): try: return await asyncio.wait_for(self._reader.read(length), timeout or self.app.cfg.timeout) except: return @@ -118,6 +131,11 @@ class Request: async def dict(self): + logging.warning('Request.dict will be removed in a future update') + return DotDict(await self.body()) + + + async def json(self): return DotDict(await self.body())