示例#1
0
    def __init__(self,
                 path: str = '',
                 spec: Optional[specs.Specification] = None,
                 app: Optional[Starlette] = None,
                 **kwargs: Any):
        self._path = path.rstrip('/')
        self._spec = spec
        self._app = app or Starlette()
        self._dispatcher = pjrpc.server.AsyncDispatcher(**kwargs)
        self._endpoints: Dict[str, pjrpc.server.AsyncDispatcher] = {
            '': self._dispatcher
        }

        self._app.add_route(self._path,
                            async_partial(self._rpc_handle,
                                          dispatcher=self._dispatcher),
                            methods=['POST'])

        if self._spec:
            self._app.add_route(utils.join_path(self._path, self._spec.path),
                                self._generate_spec,
                                methods=['GET'])

            if self._spec.ui and self._spec.ui_path:
                ui_path = utils.join_path(self._path, self._spec.ui_path)

                self._app.add_route(utils.join_path(ui_path, '/'),
                                    self._ui_index_page)
                self._app.add_route(utils.join_path(ui_path, 'index.html'),
                                    self._ui_index_page)
                self._app.routes.append(
                    routing.Mount(ui_path,
                                  app=StaticFiles(directory=str(
                                      self._spec.ui.get_static_folder()))), )
示例#2
0
文件: aiohttp.py 项目: dapper91/pjrpc
    def add_endpoint(
        self,
        prefix: str,
        subapp: Optional[aiohttp.web.Application] = None,
        **kwargs: Any,
    ) -> pjrpc.server.Dispatcher:
        """
        Adds additional endpoint.

        :param prefix: endpoint prefix
        :param subapp: aiohttp subapp the endpoint will be served on
        :param kwargs: arguments to be passed to the dispatcher :py:class:`pjrpc.server.Dispatcher`
        :return: dispatcher
        """

        prefix = prefix.rstrip('/')
        dispatcher = pjrpc.server.AsyncDispatcher(**kwargs)
        self._endpoints[prefix] = dispatcher

        if subapp:
            subapp.router.add_post(
                '', ft.partial(self._rpc_handle, dispatcher=dispatcher))
            self._app.add_subapp(utils.join_path(self._path, prefix), subapp)
        else:
            self._app.router.add_post(
                utils.join_path(self._path, prefix),
                ft.partial(self._rpc_handle, dispatcher=dispatcher),
            )

        return dispatcher
示例#3
0
文件: aiohttp.py 项目: dapper91/pjrpc
    def __init__(self,
                 path: str = '',
                 spec: Optional[specs.Specification] = None,
                 app: Optional[web.Application] = None,
                 **kwargs: Any):
        self._path = path.rstrip('/')
        self._spec = spec
        self._app = app or web.Application()
        self._dispatcher = pjrpc.server.AsyncDispatcher(**kwargs)
        self._endpoints: Dict[str, pjrpc.server.AsyncDispatcher] = {
            '': self._dispatcher
        }

        self._app.router.add_post(
            self._path,
            ft.partial(self._rpc_handle, dispatcher=self._dispatcher))

        if self._spec:
            self._app.router.add_get(
                utils.join_path(self._path, self._spec.path),
                self._generate_spec)

            if self._spec.ui and self._spec.ui_path:
                ui_app = web.Application()
                ui_app.router.add_get('/', self._ui_index_page)
                ui_app.router.add_get('/index.html', self._ui_index_page)
                ui_app.router.add_static('/',
                                         self._spec.ui.get_static_folder())

                self._app.add_subapp(
                    utils.join_path(self._path, self._spec.ui_path), ui_app)
示例#4
0
文件: sites.py 项目: dapper91/pjrpc
    def __init__(self,
                 path: str = '',
                 spec: Optional[specs.Specification] = None,
                 **kwargs: Any):
        self._path = path
        self._spec = spec

        self._dispatcher = pjrpc.server.Dispatcher(**kwargs)
        self._urls = [
            urls.path(path, self._rpc_handle),
        ]

        if self._spec:
            self._urls.append(
                urls.path(utils.join_path(self._path, self._spec.path),
                          self._generate_spec))

            if self._spec.ui and self._spec.ui_path:
                path = utils.join_path(self._path, self._spec.ui_path)
                self._urls.extend((
                    urls.path(utils.join_path(path, '/'), self._ui_index_page),
                    urls.path(utils.join_path(path, 'index.html'),
                              self._ui_index_page),
                ))
                self._urls.extend(
                    static(path,
                           document_root=str(
                               self._spec.ui.get_static_folder())))
示例#5
0
文件: sites.py 项目: dapper91/pjrpc
    def _ui_index_page(self, request: HttpRequest) -> HttpResponse:
        app_path = request.path.rsplit(self._spec.ui_path, maxsplit=1)[0]
        spec_full_path = utils.join_path(app_path, self._spec.path)

        return HttpResponse(
            self._spec.ui.get_index_page(spec_url=spec_full_path),
            content_type='text/html')
示例#6
0
文件: flask.py 项目: dapper91/pjrpc
    def _ui_index_page(self) -> flask.Response:
        app_path = flask.request.path.rsplit(self._spec.ui_path, maxsplit=1)[0]
        spec_full_path = utils.join_path(app_path, self._spec.path)

        return current_app.response_class(
            response=self._spec.ui.get_index_page(spec_url=spec_full_path),
            content_type='text/html',
        )
示例#7
0
    async def _ui_index_page(self, request: Request) -> Response:
        app_path = request.url.path.rsplit(self._spec.ui_path, maxsplit=1)[0]
        spec_full_path = utils.join_path(app_path, self._spec.path)

        return Response(
            content=self._spec.ui.get_index_page(spec_url=spec_full_path),
            media_type='text/html',
        )
示例#8
0
文件: flask.py 项目: dapper91/pjrpc
    def init_app(self, app: Union[flask.Flask, flask.Blueprint]) -> None:
        """
        Initializes flask application with JSON-RPC extension.

        :param app: flask application instance
        """

        for prefix, dispatcher in self._endpoints.items():
            path = utils.join_path(self._path, prefix)
            blueprint = self._blueprints.get(prefix)

            (blueprint or app).add_url_rule(
                path,
                methods=['POST'],
                view_func=ft.partial(self._rpc_handle, dispatcher=dispatcher),
                endpoint=path.replace('/', '_'),
            )
            if blueprint:
                app.register_blueprint(blueprint)

        if self._spec:
            app.add_url_rule(
                utils.join_path(self._path, self._spec.path),
                methods=['GET'],
                view_func=self._generate_spec,
            )

            if self._spec.ui and self._spec.ui_path:
                path = utils.join_path(self._path, self._spec.ui_path)
                app.add_url_rule(f'{path}/',
                                 methods=['GET'],
                                 view_func=self._ui_index_page)
                app.add_url_rule(f'{path}/index.html',
                                 methods=['GET'],
                                 view_func=self._ui_index_page)
                app.add_url_rule(f'{path}/<path:filename>',
                                 methods=['GET'],
                                 view_func=self._ui_static)
示例#9
0
    def add_endpoint(self, prefix: str,
                     **kwargs: Any) -> pjrpc.server.Dispatcher:
        """
        Adds additional endpoint.

        :param prefix: endpoint prefix
        :param kwargs: arguments to be passed to the dispatcher :py:class:`pjrpc.server.Dispatcher`
        :return: dispatcher
        """

        dispatcher = pjrpc.server.AsyncDispatcher(**kwargs)
        self._endpoints[prefix] = dispatcher

        self._app.add_route(
            utils.join_path(self._path, prefix),
            async_partial(self._rpc_handle, dispatcher=self._dispatcher),
            methods=['POST'],
        )

        return dispatcher
示例#10
0
文件: openapi.py 项目: dapper91/pjrpc
    def schema(self, path: str, methods: Iterable[Method] = (), methods_map: Dict[str, Iterable[Method]] = {}) -> dict:
        methods_list: List[Tuple[str, Method]] = []
        methods_list.extend((path, method) for method in methods)
        methods_list.extend(
            (utils.join_path(path, prefix), method)
            for prefix, methods in methods_map.items()
            for method in methods
        )

        for prefix, method in methods_list:
            method_meta = utils.get_meta(method.method)
            annotated_spec = method_meta.get('openapi_spec', {})

            specs: List[Dict[str, Any]] = [
                dict(
                    params_schema=annotated_spec.get('params_schema', UNSET),
                    result_schema=annotated_spec.get('result_schema', UNSET),
                    errors_schema=annotated_spec.get('errors_schema', UNSET),
                    deprecated=annotated_spec.get('deprecated', UNSET),
                    description=annotated_spec.get('description', UNSET),
                    summary=annotated_spec.get('summary', UNSET),
                    tags=annotated_spec.get('tags', UNSET),
                    examples=annotated_spec.get('examples', UNSET),
                    error_examples=annotated_spec.get('error_examples', UNSET),
                    external_docs=annotated_spec.get('external_docs', UNSET),
                    security=annotated_spec.get('security', UNSET),
                    parameters=annotated_spec.get('parameters', UNSET),
                ),
            ]
            for schema_extractor in self._schema_extractors:
                specs.append(
                    dict(
                        params_schema=schema_extractor.extract_params_schema(method.method, exclude=[method.context]),
                        result_schema=schema_extractor.extract_result_schema(method.method),
                        errors_schema=schema_extractor.extract_errors_schema(
                            method.method, annotated_spec.get('errors') or [],
                        ),
                        deprecated=schema_extractor.extract_deprecation_status(method.method),
                        description=schema_extractor.extract_description(method.method),
                        summary=schema_extractor.extract_summary(method.method),
                        tags=schema_extractor.extract_tags(method.method),
                        examples=schema_extractor.extract_examples(method.method),
                        error_examples=schema_extractor.extract_error_examples(
                            method.method, annotated_spec.get('errors') or [],
                        ),
                    ),
                )

            method_spec = self._merge_specs(specs)
            request_schema = self._build_request_schema(method.name, method_spec)
            response_schema = self._build_response_schema(method_spec)

            request_examples = {
                example.summary or f'Example#{i}': ExampleObject(
                    summary=example.summary,
                    description=example.description,
                    value=dict(
                        jsonrpc=example.version,
                        id=1,
                        method=method.name,
                        params=example.params,
                    ),
                ) for i, example in enumerate(method_spec.get('examples') or [])
            }

            response_success_examples = {
                example.summary or f'Example#{i}': ExampleObject(
                    summary=example.summary,
                    description=example.description,
                    value=dict(
                        jsonrpc=example.version,
                        id=1,
                        result=example.result,
                    ),
                ) for i, example in enumerate(method_spec.get('examples') or [])
            }

            response_error_examples = {
                example.message or f'Error#{i}': ExampleObject(
                    summary=example.summary,
                    description=example.description,
                    value=dict(
                        jsonrpc='2.0',
                        id=1,
                        error=dict(
                            code=example.code,
                            message=example.message,
                            data=example.data,
                        ),
                    ),
                ) for i, example in enumerate(
                    utils.unique(
                        [
                            ErrorExample(code=error.code, message=error.message)
                            for error in method_spec.get('errors') or []
                        ],
                        method_spec.get('error_examples') or [],
                        key=lambda item: item.code,
                    ),
                )
            }

            self.paths[f'{prefix}#{method.name}'] = Path(
                post=Operation(
                    requestBody=RequestBody(
                        description='JSON-RPC Request',
                        content={
                            JSONRPC_MEDIATYPE: MediaType(
                                schema=request_schema,
                                examples=request_examples or UNSET,
                            ),
                        },
                        required=True,
                    ),
                    responses={
                        JSONRPC_HTTP_CODE: Response(
                            description='JSON-RPC Response',
                            content={
                                JSONRPC_MEDIATYPE: MediaType(
                                    schema=response_schema,
                                    examples={**response_success_examples, **response_error_examples} or UNSET,
                                ),
                            },
                        ),
                    },
                    tags=[tag.name for tag in method_spec.get('tags') or []],
                    summary=method_spec['summary'],
                    description=method_spec['description'],
                    deprecated=method_spec['deprecated'],
                    externalDocs=method_spec.get('external_docs', UNSET),
                    security=method_spec.get('security', UNSET),
                    parameters=method_spec.get('parameters', UNSET),
                ),
            )

        return drop_unset(dc.asdict(self))