cliapi


Namecliapi JSON
Version 1.0.4 PyPI version JSON
download
home_pageNone
SummaryCliapi 是一个专为 Python 初学者设计的 WEB 包,目的是让学者能够以非常简单的方式搭建一个 WEB 服务,进而提高对 Python 的兴趣,步入 Python 世界。
upload_time2024-07-31 02:54:47
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseNone
keywords tornado flask fastapi django cliapi
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 项目描述

Cliapi 是一个专为 Python 初学者设计的 WEB 包,目的是让学者能够以非常简单的方式搭建一个 WEB 服务,进而提高对 Python 的兴趣,步入 Python 世界。

# 作者

江南雨上

[主页](https://lcctoor.com/index.html) \| [Github](https://github.com/lcctoor) \| [PyPi](https://pypi.org/user/lcctoor) \| [微信](https://lcctoor.com/cdn/WeChatQRC.jpg) \| [邮箱](mailto:lcctoor@outlook.com) \| [捐赠](https://lcctoor.com/cdn/DonationQRC-0rmb.jpg)

# Bug提交、功能提议

你可以通过 [Github-Issues](https://github.com/lcctoor/arts/issues)、[微信](https://lcctoor.com/cdn/WeChatQRC.jpg) 与我联系。

# 安装

在命令行执行:

```
pip install cliapi
```

# 教程

## 运行一个服务

```python
import asyncio
from cliapi import server, Request


async def get_1(request: Request):
    return 'Hi, Cliapi GET request successful!'  # get_1函数返回什么,客户端就会接收到什么


async def main():
    app1 = server(get=get_1, port=8887)  # port填多少,即代表让服务监听哪个端口
    await asyncio.Event().wait()

asyncio.run(main())
```

此时,你可以在浏览器中访问 [http://localhost:8887/](http://localhost:8887/) ,并看到页面上显示【Hi, Cliapi GET request successful!】。

说明:对于初学者,只需要理解:1、`get_1` 函数返回什么,客户端就会接收到什么。2、`port` 填多少,即代表让服务监听哪个端口。而并不需要明白其余的代码为什么要这样写,把它们视为固定用法即可。

### 参数说明

`request` 参数的常用属性及其描述:

| 方法和属性             | 描述                                                | 备注               |
| ---------------------- | --------------------------------------------------- | ------------------ |
| request.full_url()     | 完整的请求URL,包括协议、主机名和查询字符串         |                    |
| request.uri            | 请求的URI路径,包含查询字符串                       |                    |
| request.path.asstr()   | 请求的路径部分,不包括查询字符串                    | 下文的实战中需用到 |
| request.arguments      | 查询字符串参数的字典,键是参数名,值是参数值的列表  |                    |
| request.body           | 请求体的原始字节数据                                |                    |
| request.body_arguments | 请求体中的参数字典,键是参数名,值是参数值的列表    |                    |
| request.cookies        | 请求中的所有 cookie,键是 cookie 名,值是 cookie 值 |                    |
| request.headers        | 请求头的字典,键是头的名称,值是头的值              |                    |
| request.host           | 请求的主机名和端口                                  |                    |
| request.host_name      | 请求的主机名,不包含端口                            |                    |
| request.files          | 上传的文件字典,键是文件名,值是文件对象的列表      |                    |

`request.handler` 参数的常用属性及其描述:

| 方法和属性                        | 描述                          | 备注 |
| --------------------------------- | ----------------------------- | ---- |
| request.handler                   | 与该 request 对应的 handler |      |
| request.handler.redirect          | 重定向请求到指定的 URL        |      |
| request.handler.set_cookie        | 设置一个新的 cookie           |      |
| request.handler.clear_cookie      | 清除指定名称的 cookie         |      |
| request.handler.clear_all_cookies | 清除所有的 cookies            |      |
| request.handler.cookies           | 以字典形式获取所有的 cookies  |      |
| request.handler.set_header        | 设置一个 HTTP 响应头          |      |
| request.handler.add_header        | 添加一个 HTTP 响应头          |      |
| request.handler.clear_header      | 清除指定的 HTTP 响应头        |      |
| request.handler.set_status        | 设置 HTTP 响应状态码          |      |

## 完成《在线阅读四大名著》网站

当学者能够正确部署一个服务后,可以让他尝试做一个《在线阅读四大名著》网站。在此计划中,学者须要重新设计 `get_1` 函数的内容,并完成以下事项:

* 掌握 if 条件判断的语法。
* 收集四大名著(西游记、三国演义、水浒传、红楼梦)每部小说的前 2 章。
* 学会使用 pathlib.Path(Python标准库中的模块) 读取本地文本。
* 学会使用 request.path.asstr() 获取客户端(比如浏览器)请求的路径。
* 利用任何有效的语法(比如 if 结构),使服务按照 `/{book}/pages/{n}` 的路径返回各小说的章节,例如:当访问 [http://localhost:8887/xiyouji/pages/1](http://localhost:8887/xiyouji/pages/1) 时,返回《西游记》的第一章。然后在浏览器上体验该网站。
* (可选)注册一个域名,购买一个云服务器,将服务部署在云端,然后在本地设备上体验云网站。

## 在浏览器上显示一张图片

我们已经知道了要返回一段文本的方式为:

```python
async def get_1(request: Request):
    return 'Hi, Cliapi GET request successful!'
```

那么如何返回一张 jpeg 图片呢?可能有学者【猜想】可以使用下面这种方式:

```python
from pathlib import Path

async def get_1(request: Request):
    return Path('_ig_.jpeg').read_bytes()
```

那么,这种方式究竟是否可行呢?

答案是:这种方式可行的概率非常低,因为浏览器一般不会自动根据内容推断类型(但具体情况取决于浏览器的特性,不排除极少数浏览器具备了根据内容推断类型的特性),我们需要告诉浏览器【该数据是一张图片】。

为了告诉浏览器【该数据是一张图片】,可以采取以下两种方式中的任意一种:

### 方式一

将 URL 的后缀设置为 `.jpeg` ,比如,设定当访问 [http://localhost:8887/xiyouji/cover.jpeg](http://localhost:8887/xiyouji/cover.jpeg) 时,返回一张图片。代码示例:

```python
from pathlib import Path

async def get_1(request: Request):
    if request.path.asstr() == '/xiyouji/cover.jpeg':
        return Path('_ig_1.jpeg').read_bytes()
  
    if request.path.asstr() == '/shuihuzhuan/cover.jpeg':
        return Path('_ig_2.jpeg').read_bytes()
  
    return 'Hi, Cliapi GET request successful!'
```

### 方式二

`return` 时,返回两个值,其中第二个值将被用来告诉浏览器数据类型,代码示例:

```python
from pathlib import Path

async def get_1(request: Request):
    if request.path.asstr() == '/xiyouji/cover':
        return Path('_ig_1.jpeg').read_bytes(), 'jpeg'
  
    if request.path.asstr() == '/shuihuzhuan/cover':
        return Path('_ig_2.jpeg').read_bytes(), 'jpeg'
  
    return 'Hi, Cliapi GET request successful!'
```

### 说明

1、以上两种方式适用于任何 MIME 数据类型,比如:jpeg、jpg、png、mp3、flac、mp4、avi、txt、html、js、css、json、zip、rar。

2、由于浏览器主要是用来处理 html 的,因此当你未指定数据类型时,大多数情况下浏览器会将数据视为 html 处理。由于这个原因,以下两种写法对于浏览器是等价的:

```python
async def get_1(request: Request):
    return 'Hi, Cliapi GET request successful!'
```

```python
async def get_1(request: Request):
    return 'Hi, Cliapi GET request successful!', 'html'
```

3、当指定数据类型为 `bytes` 时,浏览器会把该文件下载到本地。

## 为《在线阅读四大名著》网站添加含封面的目录

在此计划中,学者须要完成以下事项:

* 学会使用 pathlib.Path 读取本地二进制文件,用来读取图片。
* 理解:在 html 中超链接的写法是 `<a href="{url}" target="_blank">{desc}</a>` ,例如 `<a href="http://localhost:8887/xiyouji/pages/1" target="_blank">西游记·第一章</a>` 。
* 理解:在 html 中图片的写法是 `<img src="{url}" style="width: 25rem;">` ,例如 `<img src="http://localhost:8887/xiyouji/cover.jpeg" style="width: 25rem;">` 。
* 学会 `'\n'.join(['a', 'b'])` 形式的字符串拼接方法,并将图片标签与章节超链接标签拼接成一个文本。
* 根据 request.path.asstr() 的值判断客户端想请求的是哪个资源。
* 使服务按照 /{book}/ 的路径返回各小说的目录,例如:当访问 [http://localhost:8887/xiyouji/](http://localhost:8887/xiyouji/) 时,返回《西游记》的目录。

## POST 方法示例

```python
import asyncio
from cliapi import server, Request


async def get_1(request: Request):
    return 'Hi, Cliapi GET request successful!'

async def post_1(request: Request):
    return 'Hi, Cliapi POST request successful!'


async def main():
    app1 = server(get=get_1, post=post_1, port=8887)
    await asyncio.Event().wait()

asyncio.run(main())
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "cliapi",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "tornado, flask, fastapi, django, cliapi",
    "author": null,
    "author_email": "\u6c5f\u5357\u96e8\u4e0a <lcctoor@outlook.com>",
    "download_url": "https://files.pythonhosted.org/packages/93/e3/c21e8fab4f393844f1a6e816a4ccf59d779e6ebc817d1ff6940da359ea56/cliapi-1.0.4.tar.gz",
    "platform": null,
    "description": "# \u9879\u76ee\u63cf\u8ff0\n\nCliapi \u662f\u4e00\u4e2a\u4e13\u4e3a Python \u521d\u5b66\u8005\u8bbe\u8ba1\u7684 WEB \u5305\uff0c\u76ee\u7684\u662f\u8ba9\u5b66\u8005\u80fd\u591f\u4ee5\u975e\u5e38\u7b80\u5355\u7684\u65b9\u5f0f\u642d\u5efa\u4e00\u4e2a WEB \u670d\u52a1\uff0c\u8fdb\u800c\u63d0\u9ad8\u5bf9 Python \u7684\u5174\u8da3\uff0c\u6b65\u5165 Python \u4e16\u754c\u3002\n\n# \u4f5c\u8005\n\n\u6c5f\u5357\u96e8\u4e0a\n\n[\u4e3b\u9875](https://lcctoor.com/index.html) \\| [Github](https://github.com/lcctoor) \\| [PyPi](https://pypi.org/user/lcctoor) \\| [\u5fae\u4fe1](https://lcctoor.com/cdn/WeChatQRC.jpg) \\| [\u90ae\u7bb1](mailto:lcctoor@outlook.com) \\| [\u6350\u8d60](https://lcctoor.com/cdn/DonationQRC-0rmb.jpg)\n\n# Bug\u63d0\u4ea4\u3001\u529f\u80fd\u63d0\u8bae\n\n\u4f60\u53ef\u4ee5\u901a\u8fc7 [Github-Issues](https://github.com/lcctoor/arts/issues)\u3001[\u5fae\u4fe1](https://lcctoor.com/cdn/WeChatQRC.jpg) \u4e0e\u6211\u8054\u7cfb\u3002\n\n# \u5b89\u88c5\n\n\u5728\u547d\u4ee4\u884c\u6267\u884c\uff1a\n\n```\npip install cliapi\n```\n\n# \u6559\u7a0b\n\n## \u8fd0\u884c\u4e00\u4e2a\u670d\u52a1\n\n```python\nimport asyncio\nfrom cliapi import server, Request\n\n\nasync def get_1(request: Request):\n    return 'Hi, Cliapi GET request successful!'  # get_1\u51fd\u6570\u8fd4\u56de\u4ec0\u4e48\uff0c\u5ba2\u6237\u7aef\u5c31\u4f1a\u63a5\u6536\u5230\u4ec0\u4e48\n\n\nasync def main():\n    app1 = server(get=get_1, port=8887)  # port\u586b\u591a\u5c11\uff0c\u5373\u4ee3\u8868\u8ba9\u670d\u52a1\u76d1\u542c\u54ea\u4e2a\u7aef\u53e3\n    await asyncio.Event().wait()\n\nasyncio.run(main())\n```\n\n\u6b64\u65f6\uff0c\u4f60\u53ef\u4ee5\u5728\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee [http://localhost:8887/](http://localhost:8887/) \uff0c\u5e76\u770b\u5230\u9875\u9762\u4e0a\u663e\u793a\u3010Hi, Cliapi GET request successful!\u3011\u3002\n\n\u8bf4\u660e\uff1a\u5bf9\u4e8e\u521d\u5b66\u8005\uff0c\u53ea\u9700\u8981\u7406\u89e3\uff1a1\u3001`get_1` \u51fd\u6570\u8fd4\u56de\u4ec0\u4e48\uff0c\u5ba2\u6237\u7aef\u5c31\u4f1a\u63a5\u6536\u5230\u4ec0\u4e48\u30022\u3001`port` \u586b\u591a\u5c11\uff0c\u5373\u4ee3\u8868\u8ba9\u670d\u52a1\u76d1\u542c\u54ea\u4e2a\u7aef\u53e3\u3002\u800c\u5e76\u4e0d\u9700\u8981\u660e\u767d\u5176\u4f59\u7684\u4ee3\u7801\u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u5199\uff0c\u628a\u5b83\u4eec\u89c6\u4e3a\u56fa\u5b9a\u7528\u6cd5\u5373\u53ef\u3002\n\n### \u53c2\u6570\u8bf4\u660e\n\n`request` \u53c2\u6570\u7684\u5e38\u7528\u5c5e\u6027\u53ca\u5176\u63cf\u8ff0\uff1a\n\n| \u65b9\u6cd5\u548c\u5c5e\u6027             | \u63cf\u8ff0                                                | \u5907\u6ce8               |\n| ---------------------- | --------------------------------------------------- | ------------------ |\n| request.full_url()     | \u5b8c\u6574\u7684\u8bf7\u6c42URL\uff0c\u5305\u62ec\u534f\u8bae\u3001\u4e3b\u673a\u540d\u548c\u67e5\u8be2\u5b57\u7b26\u4e32         |                    |\n| request.uri            | \u8bf7\u6c42\u7684URI\u8def\u5f84\uff0c\u5305\u542b\u67e5\u8be2\u5b57\u7b26\u4e32                       |                    |\n| request.path.asstr()   | \u8bf7\u6c42\u7684\u8def\u5f84\u90e8\u5206\uff0c\u4e0d\u5305\u62ec\u67e5\u8be2\u5b57\u7b26\u4e32                    | \u4e0b\u6587\u7684\u5b9e\u6218\u4e2d\u9700\u7528\u5230 |\n| request.arguments      | \u67e5\u8be2\u5b57\u7b26\u4e32\u53c2\u6570\u7684\u5b57\u5178\uff0c\u952e\u662f\u53c2\u6570\u540d\uff0c\u503c\u662f\u53c2\u6570\u503c\u7684\u5217\u8868  |                    |\n| request.body           | \u8bf7\u6c42\u4f53\u7684\u539f\u59cb\u5b57\u8282\u6570\u636e                                |                    |\n| request.body_arguments | \u8bf7\u6c42\u4f53\u4e2d\u7684\u53c2\u6570\u5b57\u5178\uff0c\u952e\u662f\u53c2\u6570\u540d\uff0c\u503c\u662f\u53c2\u6570\u503c\u7684\u5217\u8868    |                    |\n| request.cookies        | \u8bf7\u6c42\u4e2d\u7684\u6240\u6709 cookie\uff0c\u952e\u662f cookie \u540d\uff0c\u503c\u662f cookie \u503c |                    |\n| request.headers        | \u8bf7\u6c42\u5934\u7684\u5b57\u5178\uff0c\u952e\u662f\u5934\u7684\u540d\u79f0\uff0c\u503c\u662f\u5934\u7684\u503c              |                    |\n| request.host           | \u8bf7\u6c42\u7684\u4e3b\u673a\u540d\u548c\u7aef\u53e3                                  |                    |\n| request.host_name      | \u8bf7\u6c42\u7684\u4e3b\u673a\u540d\uff0c\u4e0d\u5305\u542b\u7aef\u53e3                            |                    |\n| request.files          | \u4e0a\u4f20\u7684\u6587\u4ef6\u5b57\u5178\uff0c\u952e\u662f\u6587\u4ef6\u540d\uff0c\u503c\u662f\u6587\u4ef6\u5bf9\u8c61\u7684\u5217\u8868      |                    |\n\n`request.handler` \u53c2\u6570\u7684\u5e38\u7528\u5c5e\u6027\u53ca\u5176\u63cf\u8ff0\uff1a\n\n| \u65b9\u6cd5\u548c\u5c5e\u6027                        | \u63cf\u8ff0                          | \u5907\u6ce8 |\n| --------------------------------- | ----------------------------- | ---- |\n| request.handler                   | \u4e0e\u8be5\u00a0request \u5bf9\u5e94\u7684\u00a0handler |      |\n| request.handler.redirect          | \u91cd\u5b9a\u5411\u8bf7\u6c42\u5230\u6307\u5b9a\u7684 URL        |      |\n| request.handler.set_cookie        | \u8bbe\u7f6e\u4e00\u4e2a\u65b0\u7684 cookie           |      |\n| request.handler.clear_cookie      | \u6e05\u9664\u6307\u5b9a\u540d\u79f0\u7684 cookie         |      |\n| request.handler.clear_all_cookies | \u6e05\u9664\u6240\u6709\u7684 cookies            |      |\n| request.handler.cookies           | \u4ee5\u5b57\u5178\u5f62\u5f0f\u83b7\u53d6\u6240\u6709\u7684 cookies  |      |\n| request.handler.set_header        | \u8bbe\u7f6e\u4e00\u4e2a HTTP \u54cd\u5e94\u5934          |      |\n| request.handler.add_header        | \u6dfb\u52a0\u4e00\u4e2a HTTP \u54cd\u5e94\u5934          |      |\n| request.handler.clear_header      | \u6e05\u9664\u6307\u5b9a\u7684 HTTP \u54cd\u5e94\u5934        |      |\n| request.handler.set_status        | \u8bbe\u7f6e HTTP \u54cd\u5e94\u72b6\u6001\u7801          |      |\n\n## \u5b8c\u6210\u300a\u5728\u7ebf\u9605\u8bfb\u56db\u5927\u540d\u8457\u300b\u7f51\u7ad9\n\n\u5f53\u5b66\u8005\u80fd\u591f\u6b63\u786e\u90e8\u7f72\u4e00\u4e2a\u670d\u52a1\u540e\uff0c\u53ef\u4ee5\u8ba9\u4ed6\u5c1d\u8bd5\u505a\u4e00\u4e2a\u300a\u5728\u7ebf\u9605\u8bfb\u56db\u5927\u540d\u8457\u300b\u7f51\u7ad9\u3002\u5728\u6b64\u8ba1\u5212\u4e2d\uff0c\u5b66\u8005\u987b\u8981\u91cd\u65b0\u8bbe\u8ba1 `get_1` \u51fd\u6570\u7684\u5185\u5bb9\uff0c\u5e76\u5b8c\u6210\u4ee5\u4e0b\u4e8b\u9879\uff1a\n\n* \u638c\u63e1 if \u6761\u4ef6\u5224\u65ad\u7684\u8bed\u6cd5\u3002\n* \u6536\u96c6\u56db\u5927\u540d\u8457\uff08\u897f\u6e38\u8bb0\u3001\u4e09\u56fd\u6f14\u4e49\u3001\u6c34\u6d52\u4f20\u3001\u7ea2\u697c\u68a6\uff09\u6bcf\u90e8\u5c0f\u8bf4\u7684\u524d 2 \u7ae0\u3002\n* \u5b66\u4f1a\u4f7f\u7528 pathlib.Path\uff08Python\u6807\u51c6\u5e93\u4e2d\u7684\u6a21\u5757\uff09 \u8bfb\u53d6\u672c\u5730\u6587\u672c\u3002\n* \u5b66\u4f1a\u4f7f\u7528 request.path.asstr() \u83b7\u53d6\u5ba2\u6237\u7aef\uff08\u6bd4\u5982\u6d4f\u89c8\u5668\uff09\u8bf7\u6c42\u7684\u8def\u5f84\u3002\n* \u5229\u7528\u4efb\u4f55\u6709\u6548\u7684\u8bed\u6cd5\uff08\u6bd4\u5982 if \u7ed3\u6784\uff09\uff0c\u4f7f\u670d\u52a1\u6309\u7167 `/{book}/pages/{n}` \u7684\u8def\u5f84\u8fd4\u56de\u5404\u5c0f\u8bf4\u7684\u7ae0\u8282\uff0c\u4f8b\u5982\uff1a\u5f53\u8bbf\u95ee [http://localhost:8887/xiyouji/pages/1](http://localhost:8887/xiyouji/pages/1) \u65f6\uff0c\u8fd4\u56de\u300a\u897f\u6e38\u8bb0\u300b\u7684\u7b2c\u4e00\u7ae0\u3002\u7136\u540e\u5728\u6d4f\u89c8\u5668\u4e0a\u4f53\u9a8c\u8be5\u7f51\u7ad9\u3002\n* \uff08\u53ef\u9009\uff09\u6ce8\u518c\u4e00\u4e2a\u57df\u540d\uff0c\u8d2d\u4e70\u4e00\u4e2a\u4e91\u670d\u52a1\u5668\uff0c\u5c06\u670d\u52a1\u90e8\u7f72\u5728\u4e91\u7aef\uff0c\u7136\u540e\u5728\u672c\u5730\u8bbe\u5907\u4e0a\u4f53\u9a8c\u4e91\u7f51\u7ad9\u3002\n\n## \u5728\u6d4f\u89c8\u5668\u4e0a\u663e\u793a\u4e00\u5f20\u56fe\u7247\n\n\u6211\u4eec\u5df2\u7ecf\u77e5\u9053\u4e86\u8981\u8fd4\u56de\u4e00\u6bb5\u6587\u672c\u7684\u65b9\u5f0f\u4e3a\uff1a\n\n```python\nasync def get_1(request: Request):\n    return 'Hi, Cliapi GET request successful!'\n```\n\n\u90a3\u4e48\u5982\u4f55\u8fd4\u56de\u4e00\u5f20 jpeg \u56fe\u7247\u5462\uff1f\u53ef\u80fd\u6709\u5b66\u8005\u3010\u731c\u60f3\u3011\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u8fd9\u79cd\u65b9\u5f0f\uff1a\n\n```python\nfrom pathlib import Path\n\nasync def get_1(request: Request):\n    return Path('_ig_.jpeg').read_bytes()\n```\n\n\u90a3\u4e48\uff0c\u8fd9\u79cd\u65b9\u5f0f\u7a76\u7adf\u662f\u5426\u53ef\u884c\u5462\uff1f\n\n\u7b54\u6848\u662f\uff1a\u8fd9\u79cd\u65b9\u5f0f\u53ef\u884c\u7684\u6982\u7387\u975e\u5e38\u4f4e\uff0c\u56e0\u4e3a\u6d4f\u89c8\u5668\u4e00\u822c\u4e0d\u4f1a\u81ea\u52a8\u6839\u636e\u5185\u5bb9\u63a8\u65ad\u7c7b\u578b\uff08\u4f46\u5177\u4f53\u60c5\u51b5\u53d6\u51b3\u4e8e\u6d4f\u89c8\u5668\u7684\u7279\u6027\uff0c\u4e0d\u6392\u9664\u6781\u5c11\u6570\u6d4f\u89c8\u5668\u5177\u5907\u4e86\u6839\u636e\u5185\u5bb9\u63a8\u65ad\u7c7b\u578b\u7684\u7279\u6027\uff09\uff0c\u6211\u4eec\u9700\u8981\u544a\u8bc9\u6d4f\u89c8\u5668\u3010\u8be5\u6570\u636e\u662f\u4e00\u5f20\u56fe\u7247\u3011\u3002\n\n\u4e3a\u4e86\u544a\u8bc9\u6d4f\u89c8\u5668\u3010\u8be5\u6570\u636e\u662f\u4e00\u5f20\u56fe\u7247\u3011\uff0c\u53ef\u4ee5\u91c7\u53d6\u4ee5\u4e0b\u4e24\u79cd\u65b9\u5f0f\u4e2d\u7684\u4efb\u610f\u4e00\u79cd\uff1a\n\n### \u65b9\u5f0f\u4e00\n\n\u5c06 URL \u7684\u540e\u7f00\u8bbe\u7f6e\u4e3a `.jpeg` \uff0c\u6bd4\u5982\uff0c\u8bbe\u5b9a\u5f53\u8bbf\u95ee [http://localhost:8887/xiyouji/cover.jpeg](http://localhost:8887/xiyouji/cover.jpeg) \u65f6\uff0c\u8fd4\u56de\u4e00\u5f20\u56fe\u7247\u3002\u4ee3\u7801\u793a\u4f8b\uff1a\n\n```python\nfrom pathlib import Path\n\nasync def get_1(request: Request):\n    if request.path.asstr() == '/xiyouji/cover.jpeg':\n        return Path('_ig_1.jpeg').read_bytes()\n  \n    if request.path.asstr() == '/shuihuzhuan/cover.jpeg':\n        return Path('_ig_2.jpeg').read_bytes()\n  \n    return 'Hi, Cliapi GET request successful!'\n```\n\n### \u65b9\u5f0f\u4e8c\n\n`return` \u65f6\uff0c\u8fd4\u56de\u4e24\u4e2a\u503c\uff0c\u5176\u4e2d\u7b2c\u4e8c\u4e2a\u503c\u5c06\u88ab\u7528\u6765\u544a\u8bc9\u6d4f\u89c8\u5668\u6570\u636e\u7c7b\u578b\uff0c\u4ee3\u7801\u793a\u4f8b\uff1a\n\n```python\nfrom pathlib import Path\n\nasync def get_1(request: Request):\n    if request.path.asstr() == '/xiyouji/cover':\n        return Path('_ig_1.jpeg').read_bytes(), 'jpeg'\n  \n    if request.path.asstr() == '/shuihuzhuan/cover':\n        return Path('_ig_2.jpeg').read_bytes(), 'jpeg'\n  \n    return 'Hi, Cliapi GET request successful!'\n```\n\n### \u8bf4\u660e\n\n1\u3001\u4ee5\u4e0a\u4e24\u79cd\u65b9\u5f0f\u9002\u7528\u4e8e\u4efb\u4f55 MIME \u6570\u636e\u7c7b\u578b\uff0c\u6bd4\u5982\uff1ajpeg\u3001jpg\u3001png\u3001mp3\u3001flac\u3001mp4\u3001avi\u3001txt\u3001html\u3001js\u3001css\u3001json\u3001zip\u3001rar\u3002\n\n2\u3001\u7531\u4e8e\u6d4f\u89c8\u5668\u4e3b\u8981\u662f\u7528\u6765\u5904\u7406 html \u7684\uff0c\u56e0\u6b64\u5f53\u4f60\u672a\u6307\u5b9a\u6570\u636e\u7c7b\u578b\u65f6\uff0c\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u6d4f\u89c8\u5668\u4f1a\u5c06\u6570\u636e\u89c6\u4e3a html \u5904\u7406\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u4ee5\u4e0b\u4e24\u79cd\u5199\u6cd5\u5bf9\u4e8e\u6d4f\u89c8\u5668\u662f\u7b49\u4ef7\u7684\uff1a\n\n```python\nasync def get_1(request: Request):\n    return 'Hi, Cliapi GET request successful!'\n```\n\n```python\nasync def get_1(request: Request):\n    return 'Hi, Cliapi GET request successful!', 'html'\n```\n\n3\u3001\u5f53\u6307\u5b9a\u6570\u636e\u7c7b\u578b\u4e3a `bytes` \u65f6\uff0c\u6d4f\u89c8\u5668\u4f1a\u628a\u8be5\u6587\u4ef6\u4e0b\u8f7d\u5230\u672c\u5730\u3002\n\n## \u4e3a\u300a\u5728\u7ebf\u9605\u8bfb\u56db\u5927\u540d\u8457\u300b\u7f51\u7ad9\u6dfb\u52a0\u542b\u5c01\u9762\u7684\u76ee\u5f55\n\n\u5728\u6b64\u8ba1\u5212\u4e2d\uff0c\u5b66\u8005\u987b\u8981\u5b8c\u6210\u4ee5\u4e0b\u4e8b\u9879\uff1a\n\n* \u5b66\u4f1a\u4f7f\u7528 pathlib.Path \u8bfb\u53d6\u672c\u5730\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u7528\u6765\u8bfb\u53d6\u56fe\u7247\u3002\n* \u7406\u89e3\uff1a\u5728 html \u4e2d\u8d85\u94fe\u63a5\u7684\u5199\u6cd5\u662f `<a href=\"{url}\" target=\"_blank\">{desc}</a>` \uff0c\u4f8b\u5982 `<a href=\"http://localhost:8887/xiyouji/pages/1\" target=\"_blank\">\u897f\u6e38\u8bb0\u00b7\u7b2c\u4e00\u7ae0</a>` \u3002\n* \u7406\u89e3\uff1a\u5728 html \u4e2d\u56fe\u7247\u7684\u5199\u6cd5\u662f `<img src=\"{url}\" style=\"width: 25rem;\">` \uff0c\u4f8b\u5982 `<img src=\"http://localhost:8887/xiyouji/cover.jpeg\" style=\"width: 25rem;\">` \u3002\n* \u5b66\u4f1a `'\\n'.join(['a', 'b'])` \u5f62\u5f0f\u7684\u5b57\u7b26\u4e32\u62fc\u63a5\u65b9\u6cd5\uff0c\u5e76\u5c06\u56fe\u7247\u6807\u7b7e\u4e0e\u7ae0\u8282\u8d85\u94fe\u63a5\u6807\u7b7e\u62fc\u63a5\u6210\u4e00\u4e2a\u6587\u672c\u3002\n* \u6839\u636e request.path.asstr() \u7684\u503c\u5224\u65ad\u5ba2\u6237\u7aef\u60f3\u8bf7\u6c42\u7684\u662f\u54ea\u4e2a\u8d44\u6e90\u3002\n* \u4f7f\u670d\u52a1\u6309\u7167 /{book}/ \u7684\u8def\u5f84\u8fd4\u56de\u5404\u5c0f\u8bf4\u7684\u76ee\u5f55\uff0c\u4f8b\u5982\uff1a\u5f53\u8bbf\u95ee [http://localhost:8887/xiyouji/](http://localhost:8887/xiyouji/) \u65f6\uff0c\u8fd4\u56de\u300a\u897f\u6e38\u8bb0\u300b\u7684\u76ee\u5f55\u3002\n\n## POST \u65b9\u6cd5\u793a\u4f8b\n\n```python\nimport asyncio\nfrom cliapi import server, Request\n\n\nasync def get_1(request: Request):\n    return 'Hi, Cliapi GET request successful!'\n\nasync def post_1(request: Request):\n    return 'Hi, Cliapi POST request successful!'\n\n\nasync def main():\n    app1 = server(get=get_1, post=post_1, port=8887)\n    await asyncio.Event().wait()\n\nasyncio.run(main())\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Cliapi \u662f\u4e00\u4e2a\u4e13\u4e3a Python \u521d\u5b66\u8005\u8bbe\u8ba1\u7684 WEB \u5305\uff0c\u76ee\u7684\u662f\u8ba9\u5b66\u8005\u80fd\u591f\u4ee5\u975e\u5e38\u7b80\u5355\u7684\u65b9\u5f0f\u642d\u5efa\u4e00\u4e2a WEB \u670d\u52a1\uff0c\u8fdb\u800c\u63d0\u9ad8\u5bf9 Python \u7684\u5174\u8da3\uff0c\u6b65\u5165 Python \u4e16\u754c\u3002",
    "version": "1.0.4",
    "project_urls": {
        "Source": "https://github.com/lcctoor/arts/tree/main/arts/cliapi"
    },
    "split_keywords": [
        "tornado",
        " flask",
        " fastapi",
        " django",
        " cliapi"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1f6971569568bf723f8142b20dfaba1ed71fca56e15a6ed4435e4dcb26ef5b3a",
                "md5": "aeb997a2fbf0c63f6b374a43fffc5792",
                "sha256": "f29655929d77e7bb68ae6def851e5224d51ca9045c1e93644260b4b030bf34d7"
            },
            "downloads": -1,
            "filename": "cliapi-1.0.4-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "aeb997a2fbf0c63f6b374a43fffc5792",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 8463,
            "upload_time": "2024-07-31T02:54:43",
            "upload_time_iso_8601": "2024-07-31T02:54:43.349598Z",
            "url": "https://files.pythonhosted.org/packages/1f/69/71569568bf723f8142b20dfaba1ed71fca56e15a6ed4435e4dcb26ef5b3a/cliapi-1.0.4-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "93e3c21e8fab4f393844f1a6e816a4ccf59d779e6ebc817d1ff6940da359ea56",
                "md5": "719bc89c46c81305fc8a773bb8e2cd3e",
                "sha256": "34ae109a8681656e6f396f4b176b09c2d4c6f58c5f49b58d778504515fb20697"
            },
            "downloads": -1,
            "filename": "cliapi-1.0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "719bc89c46c81305fc8a773bb8e2cd3e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 12834,
            "upload_time": "2024-07-31T02:54:47",
            "upload_time_iso_8601": "2024-07-31T02:54:47.634798Z",
            "url": "https://files.pythonhosted.org/packages/93/e3/c21e8fab4f393844f1a6e816a4ccf59d779e6ebc817d1ff6940da359ea56/cliapi-1.0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-07-31 02:54:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lcctoor",
    "github_project": "arts",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "cliapi"
}
        
Elapsed time: 0.34088s