RESTful API
约定:
API返回均为JSON,除了api.index接口返回的字符串,其他都是对象,基本字段code、msg。
code值为number,0表示处理成功,否则失败,此时msg有错误消息。
API返回的msg支持中英文,它检测Accept-Language头或cookie的locale字段,zh-CN则返回中文。
API返回的基本字段可以修改,可以用下面三个查询参数修改返回的基本格式:
status_name规定数据状态的字段名称,默认code
ok_code规定成功的状态码,默认0,ok_code=bool则会返回布尔类型,其他值均认为是number类型
msg_name规定状态信息的字段名称,默认msg
$ curl "http://127.0.0.1/api/xx?status_name=status&ok_code=200" - 请求成功 {"status": 200, "msg": null} - 请求失败 {"status": -1, "msg": "errmessage"} $ curl "http://127.0.0.1/api/xx?status_name=success&ok_code=bool&msg_name=message" - 请求成功 {"success": true, "message": null} - 请求失败 {"success": false, "message": "errmessage"} $ curl "http://127.0.0.1:9514/api/xx?ok_code=abc" - ok_code不是number类型或bool值,则一律返回默认 {"code": 0, "msg": null}
API返回的响应头可能有以下两个公共字段。
当内置Token钩子开启后
Access-Control-Allow-Headers: Authorization
当管理员在控制台CORS-Origin设置后
Access-Control-Allow-Origin: *或具体来源
API返回非200状态码时,404、405、413、500都返回JSON基本格式,msg是状态码名字
以下接口要求boolean类型的,值可以是true、True、1、on、yes, 均认为是真,反之则假!
以下接口,顶部的
api.xxx
这部分就叫端点,endpoint,下面是普通用户可能用到的。
1. api.index
2. api.login
- POST /api/login
登录接口
- Form Parameters:
username – 用户名
password – 登录密码
set_state – boolean: 是否设置登录态
remember – boolean: 是否记住我(7d)
- Response JSON Object:
sid (string) – SessionId
expire (string) – 过期时间戳
示例:
POST /api/login HTTP/1.0 Host: 127.0.0.1:9514 Content-Type: application/x-www-form-urlencoded username=xxx&&password=your-password-here
curl -i -X POST http://127.0.0.1:9514/api/login -H "Content-Type: application/x-www-form-urlencoded" --data-raw 'username=xxx&&password=your-password-here'
requests.post('http://127.0.0.1:9514/api/login', headers={'Content-Type': 'application/x-www-form-urlencoded'}, data='username=xxx&&password=your-password-here')
HTTP/1.0 200 OK Content-Type: application/json { "code": 0, "sid": "xxxxxxx", "expire": 123456789 }
3. api.register
- POST /api/register
注册接口
- Form Parameters:
username – 用户名
password – 密码
avatar – 头像地址
nickname – 昵称
- Status Codes:
404 Not Found – 管理员关闭注册时
示例:
POST /api/register HTTP/1.0 Host: 127.0.0.1:9514 Content-Type: application/x-www-form-urlencoded username=xxx&&password=your-password-here
curl -i -X POST http://127.0.0.1:9514/api/register -H "Content-Type: application/x-www-form-urlencoded" --data-raw 'username=xxx&&password=your-password-here'
requests.post('http://127.0.0.1:9514/api/register', headers={'Content-Type': 'application/x-www-form-urlencoded'}, data='username=xxx&&password=your-password-here')
HTTP/1.0 200 OK Content-Type: application/json { "code": 0 }
4. api.waterfall
- GET /api/waterfall
图片列表接口,要求登录,也允许 POST 方法查询。
- Query Parameters:
sort (string) – 根据图片上传时间排序,asc正序,desc倒序
page (number) – 页数,从1开始
limit (number) – 一次性返回条数,默认10
is_mgr (boolean) – 要求以管理员级别查询(当然用户也得是管理员才行)
album (string) – 查询相册,可以用逗号分隔查询多个相册
- Form Parameters:
album – 等于query查询参数的album
- Response JSON Object:
count (number) – 用户的图片总数
pageCount (number) – 根据limit和count计算的总页数
- Response JSON Array of Objects:
albums – 用户的相册列表
data – 用户的图片列表(其中字段参考shamgr接口)
- Status Codes:
403 Forbidden – 未登录时
示例:
GET /api/waterfall?limit=1 HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value
curl -i -X GET 'http://127.0.0.1:9514/api/waterfall?limit=1' -H "Authorization: LinkToken Your-LinkToken-Value"
requests.get('http://127.0.0.1:9514/api/waterfall?limit=1', headers={'Authorization': 'LinkToken Your-LinkToken-Value'})
HTTP/1.0 200 OK Content-Type: application/json { "albums": [ "misc", "gif", "test", "LinkPlugin" ], "code": 0, "count": 57, "data": [ { "agent": "homepage/0.5.5", "album": "", "ctime": 1589266897, "filename": "1589266897617.gif", "sender": "up2local", "senders": [ { "code": 0, "sender": "up2local", "src": "http://127.0.0.1:9514/static/upload/admin/1589266897617.gif" } ], "sha": "sha1.1589266897.6169922.80b939eca2183d30281bfdc29ba41aac8f8a21ed", "src": "http://127.0.0.1:9514/static/upload/admin/1589266897617.gif", "status": "enabled", "upload_path": "admin/", "user": "admin" } ], "msg": null, "pageCount": 57 }
5. api.shamgr
- GET /api/shamgr/<string:sha>
图片详情接口
- Parameters:
sha (string) – 图片的唯一标识
- Response JSON Object:
data (object) – 图片详情(上述接口的图片列表中包含的就是此详情数据)
album – 相册(当前及下方字段位于data内)
src – 图片在sapic中的链接
sender – 图片保存者(钩子名)
tpl (object) – URL文本复制的模板
agent – 上传来源UserAgent
filename – 最终保存到服务器文件名
sha – 图片唯一标识
status – 状态
user – 所属用户
upload_path – 图片前缀路径
- Status Codes:
404 Not Found – 没有对应图片时
示例:
GET /api/shamgr/sha1.xxxxxxx HTTP/1.0 Host: 127.0.0.1:9514
curl -i -X GET http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx
requests.get('http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx')
HTTP/1.0 200 OK Content-Type: application/json { "code": 0, "data": { "album": "", "src": "http://127.0.0.1:9514/static/upload/admin/1589266897617.gif", "sender": "up2local", "tpl": { "URL": "http://127.0.0.1:9514/static/upload/admin/1589266897617.gif", "rST": ".. image:: http://127.0.0.1:9514/static/upload/admin/1589266897617.gif", "HTML": "<img src='http://127.0.0.1:9514/static/upload/admin/1589266897617.gif' alt='1589266897617.gif'>", "Markdown": "![1589266897617.gif](http://127.0.0.1:9514/static/upload/admin/1589266897617.gif)" }, "agent": "homepage/0.5.5", "filename": "1589266897617.gif", "sha": "sha1.1589266897.6169922.80b939eca2183d30281bfdc29ba41aac8f8a21ed", "status": "enabled", "user": "admin", "upload_path": "admin/", "senders": null, "ctime": 1589266897 } }
- DELETE /api/shamgr/<string:sha>
图片删除接口,要求登录,只有图片所属用户和管理员允许删除。
- Parameters:
sha (string) – 图片的唯一标识
- Status Codes:
404 Not Found – 没有对应图片时
403 Forbidden – 未登录或图片所属用户与请求用户不匹配
示例:
DELETE /api/shamgr/sha1.xxxxxxx HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value
curl -i -X DELETE http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx -H "Authorization: LinkToken Your-LinkToken-Value"
requests.delete('http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx', headers={'Authorization': 'LinkToken Your-LinkToken-Value'})
- PUT /api/shamgr/<string:sha>
图片数据更新接口,要求登录,只有图片所属用户和管理员允许修改。
- Parameters:
sha (string) – 图片的唯一标识
- Query Parameters:
Action (string) – 更新指令,目前仅支持一个updateAlbum(更新相册名)
- Form Parameters:
album – 相册名
- Status Codes:
404 Not Found – 没有对应图片时
403 Forbidden – 未登录或图片所属用户与请求用户不匹配
示例:
PUT /api/shamgr/sha1.xxxxxxx?Action=updateAlbum HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value album=newName
curl -i -X PUT 'http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx?Action=updateAlbum' -H "Authorization: LinkToken Your-LinkToken-Value" --data-raw 'album=newName'
requests.put('http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx?Action=updateAlbum', headers={'Authorization': 'LinkToken Your-LinkToken-Value'}, data='album=newName')
- POST /api/shamgr/<string:sha>
与PUT类似,也是图片更新接口,要求登录,只有图片所属用户允许操作。
- Parameters:
sha (string) – 图片的唯一标识
- Query Parameters:
Action (string) – 更新指令,目前仅支持一个overrideUpload(覆盖上传)
- Form Parameters:
picbed – 上传字段,表单图片文件
- Status Codes:
404 Not Found – 没有对应图片时
403 Forbidden – 未登录或图片所属用户与请求用户不匹配
示例:
POST /api/shamgr/sha1.xxxxxxx?Action=overrideUpload HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value Content-Type: multipart/form-data picbed=@new-image-path
curl -i -X POST 'http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx?Action=overrideUpload' -H "Content-Type: multipart/form-data" -H "Authorization: LinkToken Your-LinkToken-Value" --data-raw 'picbed=@new-image-path'
requests.post('http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx?Action=overrideUpload', headers={'Content-Type': 'multipart/form-data', 'Authorization': 'LinkToken Your-LinkToken-Value'}, data='picbed=@new-image-path')
6. api.album
- GET /api/album
用户相册列表接口,要求登录,也允许 POST 方法查询。
- Response JSON Array of Objects:
data – 相册列表
- Response JSON Object:
counter (object) – 每个相册中的图片数
示例:
GET /api/album HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value
curl -i -X GET http://127.0.0.1:9514/api/album -H "Authorization: LinkToken Your-LinkToken-Value"
requests.get('http://127.0.0.1:9514/api/album', headers={'Authorization': 'LinkToken Your-LinkToken-Value'})
HTTP/1.0 200 OK Content-Type: application/json { "msg": null, "code": 0, "data": [ "misc", "gif", "test", "LinkPlugin" ], "counter": { "misc": 1, "gif": 1, "test": 7, "aaaaa": 1, "LinkPlugin": 2 } }
7. api.upload
- POST /api/upload
图片上传接口,默认不允许匿名(可由管理员开启允许),有两种上传方式, 文件域表单和base64。
在 1.2.0 版本发生变更: v1.2.0新增一种图片链接上传(目前共三种上传方式),picbed字段值为URL形式时, 会尝试下载图片(URL符合规则且下载的确实是图片类型才能成功)。
上传方式优先级:文件域 > Image URL > Image base64
在 1.9.0 版本发生变更: 增加title和expire字段,前者设置图片描述,后者添加为临时图片
在 1.13.0 版本发生变更: 真正实现上传限制!
之前的版本在后台设置的上传限制仅仅在首页上传时由前端限制,后端接口并无限制, 现在『弯道超车』目前三种上传方式都有size接口读取上传大小进而限制。
增加了 _upload_field 指定上传字段。
允许上传视频(beta)!
备注
获取上传数据的字段默认是picbed,管理员可以在控制台修改,但是不建议改, 如果要改,首页上传会自动更新,但引用uploader.js在外部上传的话,那就需要 设置 name 值,具体参考 外部上传图片插件 ,有一个name选项 可以设置其他值。
- Query Parameters:
format (string) – 指定图片地址的显示字段
- Form Parameters:
format – 等于query查询参数的format
album – 图片所属相册(匿名时总是直接设置为anonymous)
_upload_field – 指定上传字段,否则依次读取后台设置、默认值(picbed)
picbed – 上传字段名(可由后台设置)
title – 图片简单描述,页面显示时作为title
expire – 表明上传临时图片,int类型,单位秒,过期删除数据(不会物理删除图片)
filename – 使用 base64/url 方式上传时此值有效,设定文件名
- Response JSON Object:
filename (string) – 最终保存到服务器的文件名
sender (string) – 保存图片的钩子名
api (string) – 图片详情接口的地址
src (string) – 图片地址
tpl (object) – 复制模板
- Status Codes:
403 Forbidden – 管理员不允许匿名上传且用户未登录时
小技巧
当接口获取不到文件时,判断picbed字段值,如果以http://或https://开头, 那么进入Image URL上传流程,否则进入Image Base64上传流程。
Image URL上传,程序会从url中尝试查找出文件名,无效时判定失败,除非手动设置文件名。
在 1.4.0 版本发生变更: 优化了图片链接上传,程序自动尝试从链接查找文件名,无果也无妨, 继续请求url,根据其返回内容、类型猜测文件后缀。
在 1.10.0 版本发生变更: 猜测文件名使用
utils.web.guess_filename_from_url()
,相比之前, 额外允许从url本身查询参数filename获取图片文件名。程序通过
utils.web.ImgUrlFileStorage
处理,使用get方式请求 url,只有返回状态码是2xx或3xx且Content-Type是image类型时才有效。简而言之,是真正的图片链接才行。当然,还是有被伪造的可能。
base64方式上传允许 Data URI 形式的!
程序通过
utils.web.Base64FileStorage
处理, 使用b64decode解码(非url安全)图片地址src是可以自定义的,利用format参数,允许使用最多一个点号。
举例,默认返回{code:0, src:xx}
format=imgUrl (这种情况最少需要两个字符)
{code:0, imgUrl:xx}
format=data.src
{code:0, data:{src:xx}}
大概是这两种情况,src字段改名或者改为子对象中的字段。
再结合顶部约定处的公共查询参数自定义返回的基本字段,此处src定制灵活度 很高。
备注
上传流程:
登录及匿名上传判断
获取文件(三种方式)
如果文件有效,初始化相关参数,交给上传类钩子处理图片流并回传结果进行后续处理
返回响应数据
请求与响应示例:
POST /api/upload HTTP/1.0 Host: 127.0.0.1:9514 Authorization: LinkToken Your-LinkToken-Value
HTTP/1.0 200 OK Content-Type: application/json { "src": "http://127.0.0.1:9514/static/upload/admin/1589362171435.jpg", "code": 0, "sender": "up2local", "filename": "1589362171435.jpg", "api": "http://127.0.0.1:9514/api/sha/sha1.1589362171.44.790d07c9a0fd7538ea9dc7c1ec208dbcd291ce35", "msg": null }
文件域上传示例:
curl
$ curl -H "Authorization: LinkToken xxxx" -XPOST \ http://127.0.0.1:9514/api/upload -F "picbed=@上传的图片路径"
python
files = { 'picbed': (filename, open("图片", "rb")) } headers = {"Authorization": "LinkToken xxxx"} requests.post( "http://127.0.0.1:9514/api/upload", files=files, headers=headers, ).json()
Image Base64上传示例:
curl
$ curl -H "Authorization: LinkToken xxxx" -XPOST \ http://127.0.0.1:9514/api/upload -d picbed="图片base64编码" -d filename="test.jpg"
python
headers = {"Authorization": "LinkToken xxxx"} requests.post( "http://127.0.0.1:9514/api/upload", data=dict( picbed="data:image/jpg;base64,图片base64编码" ), headers=headers, ).json()
ajax
$.ajax({ url: 'http://127.0.0.1:9514/api/upload', method:'POST', data: {picbed: 'data:image/png;base64,图片base64编码'}, success:function(res){ console.log(res); } });
Image URL上传示例:
curl
$ url=https://hbimg.huabanimg.com/6b7b7456a3cb7b1b149be2463dca29c18e8c03c2bd0c-DcxKZ5 $ curl -XPOST -H "Authorization: LinkToken xxxx" \ http://127.0.0.1:9514/api/upload -d picbed="${url}" { "code": 0 "src": "xxx", "filename": "xx", "sender": "up2local" }
python
headers = {"Authorization": "LinkToken xxxx"} requests.post( "http://127.0.0.1:9514/api/upload", data=dict( picbed="https://xxxx.com/your-image.png" ), headers=headers, ).json()
8. api.my
修改用户资料、密码等
9. api.ep
专为钩子实现的接口
10. api.load
- POST /api/load
图片导入接口,即可以将已存在其他位置的远程图片导入到系统中。
目前仅支持通过接口方式,提交JSON数组。
在 1.13.1 版本发生变更: 兼容了视频导入
- Request JSON Array of Objects:
url (str) – 图片地址
filename (str) – 图片文件名[建议填写]
title (str) – 描述[可选]
album (str) – 相册[可选]
- Request Headers:
Content-Type – application/json
- Response JSON Object:
code (int) – 除非传参错误,否则都是0,主要是success字段
count (object) – success、fail数量
- Response JSON Array of Objects:
success (array) – 成功导入的地址
fail (array) – 导入失败
- Status Codes:
403 Forbidden – 用户未登录时
备注
导入流程:
- 筛选json数据(传参),把合法url及可以提取出filename的放入todo留待处理
使用
utils.web.guess_filename_from_url()
尝试解析filename, 文件名无效时(符合管理员控制台允许的图片后缀或默认后缀),扔到fail
处理todo中合法数据,保存成功的放到success,失败的放到fail
由于图片直接导入,只写入些逻辑数据,所以不会调用存储钩子,故此 图片钩子名保留为:load
请求与响应示例:
POST /api/load HTTP/1.0 Host: 127.0.0.1:9514 Content-Type: application/json Authorization: LinkToken Your-LinkToken-Value [ { "url": "https://static.saintic.com/misc/test.jpg", "album": "test" }, { "url": "https://hbimg.huabanimg.com/6b7b7456a3cb7b1b149be2463dca29c18e8c03c2bd0c-DcxKZ5", "filename": "huaban-logo.png", "title": "Huaban.com Logo" }, { "url": "xxx" }, "skipped" ]
curl -i -X POST http://127.0.0.1:9514/api/load -H "Content-Type: application/json" -H "Authorization: LinkToken Your-LinkToken-Value" --data-raw '[{"url": "https://static.saintic.com/misc/test.jpg", "album": "test"}, {"url": "https://hbimg.huabanimg.com/6b7b7456a3cb7b1b149be2463dca29c18e8c03c2bd0c-DcxKZ5", "filename": "huaban-logo.png", "title": "Huaban.com Logo"}, {"url": "xxx"}, "skipped"]'
requests.post('http://127.0.0.1:9514/api/load', headers={'Content-Type': 'application/json', 'Authorization': 'LinkToken Your-LinkToken-Value'}, json=[{'url': 'https://static.saintic.com/misc/test.jpg', 'album': 'test'}, {'url': 'https://hbimg.huabanimg.com/6b7b7456a3cb7b1b149be2463dca29c18e8c03c2bd0c-DcxKZ5', 'filename': 'huaban-logo.png', 'title': 'Huaban.com Logo'}, {'url': 'xxx'}, 'skipped'])
HTTP/1.0 200 OK Content-Type: application/json { "count": { "fail": 2, "success": 2 }, "fail": [ { "url": "xxx" }, "skipped" ], "success": [ { "album": "test", "filename": "test.jpg", "sha": "sha1.1598598852.2625027.cb56752477cae6405f85b131872c60d21b967c6a", "url": "https://static.saintic.com/misc/test.jpg" }, { "filename": "huaban-logo.png", "sha": "sha1.1598598852.2630813.052bb5af0535881a3acaf94978cded5d6b249457", "title": "Huaban.com Logo", "url": "https://hbimg.huabanimg.com/6b7b7456a3cb7b1b149be2463dca29c18e8c03c2bd0c-DcxKZ5" } ], "code": 0 }