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

ANY /api/, /api/index

Api首页,仅用来表明登录态,允许 POST GET 方法

返回: Hello sapic(未登录)/<username>(已登录)

2. api.login

POST /api/login

登录接口

Form Parameters:
  • username – 用户名

  • password – 登录密码

  • set_state – boolean: 是否设置登录态

  • remember – boolean: 是否记住我(7d)

Response JSON Object:
  • sid (string) – SessionId

  • expire (string) – 过期时间戳

示例:

http

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

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'

python-requests

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')

response

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:

示例:

http

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

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'

python-requests

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')

response

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:

示例:

http

GET /api/waterfall?limit=1 HTTP/1.0
Host: 127.0.0.1:9514
Authorization: LinkToken Your-LinkToken-Value

curl

curl -i -X GET 'http://127.0.0.1:9514/api/waterfall?limit=1' -H "Authorization: LinkToken Your-LinkToken-Value"

python-requests

requests.get('http://127.0.0.1:9514/api/waterfall?limit=1', headers={'Authorization': 'LinkToken Your-LinkToken-Value'})

response

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:

示例:

http

GET /api/shamgr/sha1.xxxxxxx HTTP/1.0
Host: 127.0.0.1:9514

curl

curl -i -X GET http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx

python-requests

requests.get('http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx')

response

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:

示例:

http

DELETE /api/shamgr/sha1.xxxxxxx HTTP/1.0
Host: 127.0.0.1:9514
Authorization: LinkToken Your-LinkToken-Value

curl

curl -i -X DELETE http://127.0.0.1:9514/api/shamgr/sha1.xxxxxxx -H "Authorization: LinkToken Your-LinkToken-Value"

python-requests

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:

示例:

http

PUT /api/shamgr/sha1.xxxxxxx?Action=updateAlbum HTTP/1.0
Host: 127.0.0.1:9514
Authorization: LinkToken Your-LinkToken-Value

album=newName

curl

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'

python-requests

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:

示例:

http

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

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'

python-requests

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) – 每个相册中的图片数

示例:

http

GET /api/album HTTP/1.0
Host: 127.0.0.1:9514
Authorization: LinkToken Your-LinkToken-Value

curl

curl -i -X GET http://127.0.0.1:9514/api/album -H "Authorization: LinkToken Your-LinkToken-Value"

python-requests

requests.get('http://127.0.0.1:9514/api/album', headers={'Authorization': 'LinkToken Your-LinkToken-Value'})

response

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定制灵活度 很高。

备注

上传流程:

  1. 登录及匿名上传判断

  2. 获取文件(三种方式)

  3. 如果文件有效,初始化相关参数,交给上传类钩子处理图片流并回传结果进行后续处理

  4. 返回响应数据

请求与响应示例:

http

POST /api/upload HTTP/1.0
Host: 127.0.0.1:9514
Authorization: LinkToken Your-LinkToken-Value

response

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:
Response JSON Object:
  • code (int) – 除非传参错误,否则都是0,主要是success字段

  • count (object) – success、fail数量

Response JSON Array of Objects:
  • success (array) – 成功导入的地址

  • fail (array) – 导入失败

Status Codes:

备注

导入流程:

  1. 筛选json数据(传参),把合法url及可以提取出filename的放入todo留待处理

    使用 utils.web.guess_filename_from_url() 尝试解析filename, 文件名无效时(符合管理员控制台允许的图片后缀或默认后缀),扔到fail

  2. 处理todo中合法数据,保存成功的放到success,失败的放到fail

由于图片直接导入,只写入些逻辑数据,所以不会调用存储钩子,故此 图片钩子名保留为:load

请求与响应示例:

http

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

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"]'

python-requests

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'])

response

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
}