mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-27 18:45:05 +08:00
⚗️ add support for data json file
This commit is contained in:
parent
75e2ca77df
commit
80258fe2d4
@ -2,6 +2,8 @@ import abc
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from http.cookiejar import Cookie, CookieJar
|
from http.cookiejar import Cookie, CookieJar
|
||||||
from typing import (
|
from typing import (
|
||||||
|
IO,
|
||||||
|
Any,
|
||||||
Dict,
|
Dict,
|
||||||
List,
|
List,
|
||||||
Tuple,
|
Tuple,
|
||||||
@ -9,7 +11,6 @@ from typing import (
|
|||||||
Mapping,
|
Mapping,
|
||||||
Iterator,
|
Iterator,
|
||||||
Optional,
|
Optional,
|
||||||
Sequence,
|
|
||||||
MutableMapping,
|
MutableMapping,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,21 +20,34 @@ from multidict import CIMultiDict
|
|||||||
RawURL = Tuple[bytes, bytes, Optional[int], bytes]
|
RawURL = Tuple[bytes, bytes, Optional[int], bytes]
|
||||||
|
|
||||||
SimpleQuery = Union[str, int, float]
|
SimpleQuery = Union[str, int, float]
|
||||||
QueryVariable = Union[SimpleQuery, Sequence[SimpleQuery]]
|
QueryVariable = Union[SimpleQuery, List[SimpleQuery]]
|
||||||
QueryTypes = Union[
|
QueryTypes = Union[
|
||||||
None, str, Mapping[str, QueryVariable], Sequence[Tuple[str, QueryVariable]]
|
None, str, Mapping[str, QueryVariable], List[Tuple[str, QueryVariable]]
|
||||||
]
|
]
|
||||||
|
|
||||||
HeaderTypes = Union[
|
HeaderTypes = Union[
|
||||||
None,
|
None,
|
||||||
CIMultiDict[str],
|
CIMultiDict[str],
|
||||||
Dict[str, str],
|
Dict[str, str],
|
||||||
Sequence[Tuple[str, str]],
|
List[Tuple[str, str]],
|
||||||
]
|
]
|
||||||
|
|
||||||
ContentTypes = Union[str, bytes, None]
|
|
||||||
CookieTypes = Union[None, "Cookies", CookieJar, Dict[str, str], List[Tuple[str, str]]]
|
CookieTypes = Union[None, "Cookies", CookieJar, Dict[str, str], List[Tuple[str, str]]]
|
||||||
|
|
||||||
|
ContentTypes = Union[str, bytes, None]
|
||||||
|
DataTypes = Union[dict, None]
|
||||||
|
FileContent = Union[IO[bytes], bytes]
|
||||||
|
FileType = Tuple[Optional[str], FileContent, Optional[str]]
|
||||||
|
FileTypes = Union[
|
||||||
|
# file (or bytes)
|
||||||
|
FileContent,
|
||||||
|
# (filename, file (or bytes))
|
||||||
|
Tuple[Optional[str], FileContent],
|
||||||
|
# (filename, file (or bytes), content_type)
|
||||||
|
FileType,
|
||||||
|
]
|
||||||
|
FilesTypes = Union[Dict[str, FileTypes], List[Tuple[str, FileTypes]], None]
|
||||||
|
|
||||||
|
|
||||||
class HTTPVersion(Enum):
|
class HTTPVersion(Enum):
|
||||||
H10 = "1.0"
|
H10 = "1.0"
|
||||||
@ -51,6 +65,9 @@ class Request:
|
|||||||
headers: HeaderTypes = None,
|
headers: HeaderTypes = None,
|
||||||
cookies: CookieTypes = None,
|
cookies: CookieTypes = None,
|
||||||
content: ContentTypes = None,
|
content: ContentTypes = None,
|
||||||
|
data: DataTypes = None,
|
||||||
|
json: Any = None,
|
||||||
|
files: FilesTypes = None,
|
||||||
version: Union[str, HTTPVersion] = HTTPVersion.H11,
|
version: Union[str, HTTPVersion] = HTTPVersion.H11,
|
||||||
timeout: Optional[float] = None,
|
timeout: Optional[float] = None,
|
||||||
):
|
):
|
||||||
@ -93,6 +110,19 @@ class Request:
|
|||||||
|
|
||||||
# body
|
# body
|
||||||
self.content: ContentTypes = content
|
self.content: ContentTypes = content
|
||||||
|
self.data: DataTypes = data
|
||||||
|
self.json: Any = json
|
||||||
|
self.files: Optional[List[Tuple[str, FileType]]] = None
|
||||||
|
if files:
|
||||||
|
self.files = []
|
||||||
|
files_ = files.items() if isinstance(files, dict) else files
|
||||||
|
for name, file_info in files_:
|
||||||
|
if not isinstance(file_info, tuple):
|
||||||
|
self.files.append((name, (None, file_info, None)))
|
||||||
|
elif len(file_info) == 2:
|
||||||
|
self.files.append((name, (file_info[0], file_info[1], None)))
|
||||||
|
else:
|
||||||
|
self.files.append((name, file_info)) # type: ignore
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
class_name = self.__class__.__name__
|
class_name = self.__class__.__name__
|
||||||
|
@ -35,11 +35,17 @@ class Mixin(ForwardMixin):
|
|||||||
raise RuntimeError(f"Unsupported HTTP version: {setup.version}")
|
raise RuntimeError(f"Unsupported HTTP version: {setup.version}")
|
||||||
|
|
||||||
timeout = aiohttp.ClientTimeout(setup.timeout)
|
timeout = aiohttp.ClientTimeout(setup.timeout)
|
||||||
|
files = None
|
||||||
|
if setup.files:
|
||||||
|
files = aiohttp.FormData()
|
||||||
|
for name, file in setup.files:
|
||||||
|
files.add_field(name, file[1], content_type=file[2], filename=file[0])
|
||||||
async with aiohttp.ClientSession(version=version) as session:
|
async with aiohttp.ClientSession(version=version) as session:
|
||||||
async with session.request(
|
async with session.request(
|
||||||
setup.method,
|
setup.method,
|
||||||
setup.url,
|
setup.url,
|
||||||
data=setup.content,
|
data=setup.content or setup.data or files,
|
||||||
|
json=setup.json,
|
||||||
headers=setup.headers,
|
headers=setup.headers,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
) as response:
|
) as response:
|
||||||
|
@ -11,17 +11,17 @@ FastAPI 驱动适配
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import List, Callable, Optional
|
from typing import Any, List, Tuple, Callable, Optional
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
from fastapi.responses import Response
|
from fastapi.responses import Response
|
||||||
from fastapi import FastAPI, Request, status
|
from fastapi import FastAPI, Request, UploadFile, status
|
||||||
from starlette.websockets import WebSocket, WebSocketState
|
from starlette.websockets import WebSocket, WebSocketState
|
||||||
|
|
||||||
|
from ._model import FileTypes
|
||||||
from nonebot.config import Env
|
from nonebot.config import Env
|
||||||
from nonebot.typing import overrides
|
from nonebot.typing import overrides
|
||||||
from nonebot.utils import escape_tag
|
|
||||||
from nonebot.config import Config as NoneBotConfig
|
from nonebot.config import Config as NoneBotConfig
|
||||||
from nonebot.drivers import Request as BaseRequest
|
from nonebot.drivers import Request as BaseRequest
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
@ -238,12 +238,36 @@ class Driver(ReverseDriver):
|
|||||||
request: Request,
|
request: Request,
|
||||||
setup: HTTPServerSetup,
|
setup: HTTPServerSetup,
|
||||||
) -> Response:
|
) -> Response:
|
||||||
|
json: Any = None
|
||||||
|
try:
|
||||||
|
json = await request.json()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
data: Optional[dict] = None
|
||||||
|
files: Optional[List[Tuple[str, FileTypes]]] = None
|
||||||
|
try:
|
||||||
|
form = await request.form()
|
||||||
|
data = {}
|
||||||
|
files = []
|
||||||
|
for key, value in form.multi_items():
|
||||||
|
if isinstance(value, UploadFile):
|
||||||
|
files.append(
|
||||||
|
(key, (value.filename, value.file, value.content_type))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
data[key] = value
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
http_request = BaseRequest(
|
http_request = BaseRequest(
|
||||||
request.method,
|
request.method,
|
||||||
str(request.url),
|
str(request.url),
|
||||||
headers=request.headers.items(),
|
headers=request.headers.items(),
|
||||||
cookies=request.cookies,
|
cookies=request.cookies,
|
||||||
content=await request.body(),
|
content=await request.body(),
|
||||||
|
data=data,
|
||||||
|
json=json,
|
||||||
|
files=files,
|
||||||
version=request.scope["http_version"],
|
version=request.scope["http_version"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ class Mixin(ForwardMixin):
|
|||||||
setup.method,
|
setup.method,
|
||||||
str(setup.url),
|
str(setup.url),
|
||||||
content=setup.content,
|
content=setup.content,
|
||||||
|
data=setup.data,
|
||||||
|
json=setup.json,
|
||||||
|
files=setup.files,
|
||||||
headers=tuple(setup.headers.items()),
|
headers=tuple(setup.headers.items()),
|
||||||
timeout=setup.timeout,
|
timeout=setup.timeout,
|
||||||
)
|
)
|
||||||
|
@ -8,15 +8,14 @@ Quart 驱动适配
|
|||||||
https://pgjones.gitlab.io/quart/index.html
|
https://pgjones.gitlab.io/quart/index.html
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import List, TypeVar, Callable, Optional, Coroutine
|
from typing import List, Tuple, TypeVar, Callable, Optional, Coroutine
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
|
|
||||||
|
from ._model import FileTypes
|
||||||
from nonebot.config import Env
|
from nonebot.config import Env
|
||||||
from nonebot.log import logger
|
|
||||||
from nonebot.typing import overrides
|
from nonebot.typing import overrides
|
||||||
from nonebot.utils import escape_tag
|
|
||||||
from nonebot.config import Config as NoneBotConfig
|
from nonebot.config import Config as NoneBotConfig
|
||||||
from nonebot.drivers import Request as BaseRequest
|
from nonebot.drivers import Request as BaseRequest
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
@ -24,9 +23,9 @@ from nonebot.drivers import ReverseDriver, HTTPServerSetup, WebSocketServerSetup
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from quart import request as _request
|
from quart import request as _request
|
||||||
import werkzeug.exceptions as exceptions
|
|
||||||
from quart import websocket as _websocket
|
from quart import websocket as _websocket
|
||||||
from quart import Quart, Request, Response
|
from quart import Quart, Request, Response
|
||||||
|
from quart.datastructures import FileStorage
|
||||||
from quart import Websocket as QuartWebSocket
|
from quart import Websocket as QuartWebSocket
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ValueError("Please install Quart by using `pip install nonebot2[quart]`")
|
raise ValueError("Please install Quart by using `pip install nonebot2[quart]`")
|
||||||
@ -213,6 +212,18 @@ class Driver(ReverseDriver):
|
|||||||
async def _handle_http(self, setup: HTTPServerSetup) -> Response:
|
async def _handle_http(self, setup: HTTPServerSetup) -> Response:
|
||||||
request: Request = _request
|
request: Request = _request
|
||||||
|
|
||||||
|
json = None
|
||||||
|
if request.is_json:
|
||||||
|
json = await request.get_json()
|
||||||
|
|
||||||
|
data = await request.form
|
||||||
|
files_dict = await request.files
|
||||||
|
files: List[Tuple[str, FileTypes]] = []
|
||||||
|
key: str
|
||||||
|
value: FileStorage
|
||||||
|
for key, value in files_dict.items():
|
||||||
|
files.append((key, (value.filename, value.stream, value.content_type)))
|
||||||
|
|
||||||
http_request = BaseRequest(
|
http_request = BaseRequest(
|
||||||
request.method,
|
request.method,
|
||||||
request.url,
|
request.url,
|
||||||
@ -221,6 +232,9 @@ class Driver(ReverseDriver):
|
|||||||
content=await request.get_data(
|
content=await request.get_data(
|
||||||
cache=False, as_text=False, parse_form_data=False
|
cache=False, as_text=False, parse_form_data=False
|
||||||
),
|
),
|
||||||
|
data=data or None,
|
||||||
|
json=json,
|
||||||
|
files=files or None,
|
||||||
version=request.http_version,
|
version=request.http_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user