whatshot[2021-01-13更新] 虎绿林API:JSON Page

@Ta 2016-12-24发布,11-11 23:01修改 23331点击

更新列表:

[2021-11-11] 所有参数均可通过POST传递:https://hu60.cn/q.php/bbs.topic.101950.html
[2021-11-04] 添加了表情列表接口:https://hu60.cn/q.php/api.face.json
[2021-09-16] 添加了全局参数_topic_summary=最大长度来获取帖子内容摘要,可以在有topic_id字段返回的页面获取帖子内容摘要(演示)。

[2021-09-09]

[2021-02-04] 添加了全局参数_myself=1_myself=newMsg,newAtInfo,newChats,可用于获取与用户自身相关的信息。

[2021-01-19]

[2021-01-14]

  • 为用户生成的内容添加了class标记,详见下面的“用户生成内容中的class标记”部分。
  • JSON Page 不对用户发言中的图片、链接等进行安全跳转(link.url.json?b64e=...),而是直接返回原始链接。

[2021-01-13] 添加了一个新的站点信息接口,返回网站名称、论坛名称、备案号等信息:https://hu60.cn/q.php/site.info.json

[2021-01-12] 今日更新如下:

  • 现在可以通过 http://hu60.cn/q.php/user.stat.json 接口获取会显示在html版页面底部的聊天室新消息了。
  • 全局参数 _content 现在支持四种格式了:html、ubb、json和text,并且ubb和text类型在包括内信和at消息在内的所有地方都可安全使用。
  • 帖子编辑页面(bbs.edittopic.xxx.json)的titlecontent字段现在不进行HTML实体转义(htmlspecialchars)了,如果要插入HTML中,请自行转义,以防XSS攻击。
  • 帖子页面添加GET参数floorReverse=0或1用于调整楼层排序,如正序倒序
  • 现在聊天室删楼提醒已经和帖子删楼提醒统一了,可以正确给出json、ubb、text格式。
  • 添加了参数pageSize=分页大小,可用于所有列表页面。

[2019-07-04] 添加了“用户信息扩展”功能(演示:https://hu60.cn/q.php/bbs.topic.82570.json?_uinfo=name,avatar,sign,contact ),具体见下方描述。

[2017-03-25] 添加了网页插件数据存储API,可供网页插件存储和查询自定义键值对:https://hu60.cn/q.php/bbs.topic.83603.html

[2016-12-25] 全局参数 json 更名为 _json;添加了全局参数 _content=html|ubb|json 用于选择返回内容的格式。

[2016-12-29] 添加了全局参数 _origin=*|域名,可支持浏览器中的跨站Ajax访问。为保证用户安全,跨站Ajax拒绝接受和设置任何Cookie。

[2016-12-31] 修复在JSON页面发at消息,在html页面查看,点击链接跳转到JSON页面的问题。为解决问题,原url中的bid(html或json)用占位符“{$BID}”取代,并在显示时才替换成当前页面的bid。


概述

就在刚刚,虎绿林完成了整站的 JSON API 编写工作。

为了减少工作量,以及保证 API 和网页的一致性,虎绿林用了一种独特的方式提供 API,可能除了虎绿林,没有人用同样的方法提供API了。

我把这种方式称为 JSON Page(JSON页面),它实现的方法很简单,就是用虎绿林的主题切换功能,为网站写一个纯粹用JSON输出的主题。

效果是这样的:
https://hu60.cn/q.php/index.index.json
https://hu60.cn/q.php/bbs.topic.82570.json

把任何一个页面的后缀由 .html 改成 .json,就可以看到这个页面的 JSON 版本。
几乎所有页面都提供了 JSON 版本,欢迎各位用 JSON 版本来做任何事。

注意不是在.html后面加.json,而是把.html改成.json。比如首页的HTML版:
https://hu60.cn/q.php/index.index.html
首页的JSON版:
https://hu60.cn/q.php/index.index.json

JSON 版本的交互方式和网页是一样的:
比如翻页,网页是改变URL,JSON版本也是改变URL。
再比如发言,网页是 POST 提交,JSON版本也是一样,提交的参数也和网页相同,唯一的区别是提交的页面的后缀改成 .json。

JSON版本可能会有错误,如果遇到问题,请及时在这个帖子反馈。


JSON Page 专用参数:


JSON Page 专用页面:


数据存储API:

可供网页插件存储和查询自定义键值对,详见 https://hu60.cn/q.php/bbs.topic.83603.html


七牛云文件上传API:

可上传文件到虎绿林的七牛云存储库,供发帖使用。详见 https://hu60.cn/q.php/bbs.topic.89896.html


JSON压缩(注意,参数名由 json 变成了 _json):

用 _json=compact 参数可以得到压缩后的 JSON 结果
https://hu60.cn/q.php/index.index.json?_json=compact

如果你想要把所有返回的数组都变成对象,可以用 _json=object
https://hu60.cn/q.php/index.index.json?_json=object

这两个参数可以一起用,_json=compact,object

参数可通过GET、POST、Header(x-json)方式传递:

curl https://hu60.cn/q.php/index.index.json?_json=compact
curl --data '_json=compact' https://hu60.cn/q.php/index.index.json
curl --header 'x-json: compact' https://hu60.cn/q.php/index.index.json

获取帖子内容摘要

https://hu60.cn/q.php/index.index.json?_topic_summary=100

100为摘要最大长度,超出则截断并在末尾添加“…”。

在所有会返回topic_id的页面均可用。


用户信息扩展:

可以用于任何返回值中包含uid或者***uid(如byuidtouid)的页面。
添加URL参数_uinfo=name,avatar,sign,contact(逗号分隔,可以删掉不需要的项目),返回值中便会多出如下成员:
_u_name_u_avatar_u_signature_u_contact

https://hu60.cn/q.php/bbs.topic.82570.json?_uinfo=name,avatar,sign,contact

...
"uid": 1,
"_u_name": "老虎会游泳",
"_u_avatar": "http://file.hu60.cn/avatar/1.jpg?1557592687",
"_u_signature": "你好,这里是虎绿林。",
"_u_contact": "QQ 905172616 & 18502433620 & hu60.cn@gmail.com & N/A"
...

如果是***uid,则***位于字段开头,如:
https://hu60.cn/q.php/msg.index.json?_uinfo=name,avatar,sign,contact

...
"touid": 1,
"byuid": 841,
"to_u_name": "老虎会游泳",
"to_u_avatar": "http://file.hu60.cn/avatar/1.jpg?1557592687",
"to_u_signature": "你好,这里是虎绿林。",
"to_u_contact": "QQ 905172616 & 18502433620 & hu60.cn@gmail.com & N/A",
"by_u_name": "000",
"by_u_avatar": "http://file.hu60.cn/avatar/841.jpg",
"by_u_signature": "安静的PHPer",
"by_u_contact": "to7@foxmail.com"
...

参数可通过GET、POST、Header(x-uinfo)方式传递:

curl https://hu60.cn/q.php/index.index.json?_uinfo=name,avatar,sign,contact
curl --data '_uinfo=name,avatar,sign,contact' https://hu60.cn/q.php/index.index.json
curl --header 'x-uinfo: name,avatar,sign,contact' https://hu60.cn/q.php/index.index.json

获取用户自身信息:

可以用于任何页面,可以与上面的“用户信息扩展”结合使用。

添加URL参数_myself=1或者_myself=newMsg,newAtInfo,newChats即可。

为了防止其他信息干扰,我专门选了个几乎没有其他信息的页面演示该功能。该功能实际上可用于任何页面,添加的_myself字段会出现在JSON底部。

参数可通过GET、POST、Header(x-myself)方式传递:

curl https://hu60.cn/q.php/index.index.json?_myself=1
curl --data '_myself=1' https://hu60.cn/q.php/index.index.json
curl --header 'x-myself: 1' https://hu60.cn/q.php/index.index.json

仅获取uid

https://hu60.cn/q.php/bbs.search.json?_myself=1

{
    ...
    "_myself": {
        "isLogin": true,
        "uid": 1
    }
}

获取uid,昵称,头像

https://hu60.cn/q.php/bbs.search.json?_myself=1&_uinfo=name,avatar

{
    ...
    "_myself": {
        "isLogin": true,
        "uid": 1,
        "_u_name": "老虎会游泳",
        "_u_avatar": "https://file.hu60.cn/avatar/1.jpg?1588915503"
    }
}

获取uid,昵称,头像,新内信条数,新At消息条数

https://hu60.cn/q.php/bbs.search.json?_myself=newMsg,newAtInfo&_uinfo=name,avatar

{
    ...
    "_myself": {
        "isLogin": true,
        "uid": 1,
        "newMsg": 0,
        "newAtInfo": 1,
        "_u_name": "老虎会游泳",
        "_u_avatar": "https://file.hu60.cn/avatar/1.jpg?1588915503"
    }
}

获取uid,新内信条数,新At消息条数,聊天室最新发言

https://hu60.cn/q.php/bbs.search.json?_myself=newMsg,newAtInfo,newChats

    "_myself": {
        "isLogin": true,
        "uid": 1,
        "newMsg": 0,
        "newAtInfo": 1,
        "newChats": [
            {
                "id": 19038,
                "room": "公共聊天室",
                "lid": 8882,
                "uid": 21479,
                "uname": "我是教官",
                "content": "发言内容省略",
                "time": 1612450046,
                "hidden": 0,
                "review": 0
            },
            {
                "id": 19002,
                "room": "更换聊天室",
                "lid": 6,
                "uid": 1,
                "uname": "老虎会游泳",
                "content": "发言内容省略",
                "time": 1612443635,
                "hidden": 0,
                "review": 0
            },
            {
                "id": 18918,
                "room": "老虎会游泳",
                "lid": 100,
                "uid": 5372,
                "uname": "穴儿",
                "content": "发言内容省略",
                "time": 1612411015,
                "hidden": 0,
                "review": 0
            }
        ]
    }

返回内容格式选择:

https://hu60.cn/q.php/bbs.topic.82570.json?_content=html
https://hu60.cn/q.php/bbs.topic.82570.json?_content=json
https://hu60.cn/q.php/bbs.topic.82570.json?_content=ubb
https://hu60.cn/q.php/bbs.topic.82570.json?_content=text

参数可通过GET、POST、Header(x-content)方式传递:

curl https://hu60.cn/q.php/bbs.topic.82570.json?_content=ubb
curl --data '_content=ubb' https://hu60.cn/q.php/bbs.topic.82570.json
curl --header 'x-content: ubb' https://hu60.cn/q.php/bbs.topic.82570.json

这个参数可以用来改变包含UBB的内容的格式。
支持四种格式:html、json、ubb、text,如果没有这个参数,默认是html。

注意:ubb和text都没有进行HTML实体转义(htmlspecialchars),如果要插入HTML中,请自行转义,以防XSS攻击。

json格式是帖子内容存储在数据库中的格式,其基本形式为:

  1. 每个UBB标记存储为一个 JSON 对象,其中包含 type 属性,记录了UBB的类型。每个类型都有各自不同的其他属性,记录了UBB的实际数据。纯文本的UBB类型为text。
  2. 帖子的所有内容从前往后依次排列构成一个 JSON 数组。

具体的解码方法参考:https://github.com/hu60t/hu60wap6/blob/master/src/class/ubbdisplay.php

此外,2021年1月12日更新后,对内信和at消息使用ubb和text类型就都是安全的了。管理员删除提醒、管理员编辑提醒、管理员沉帖提醒都有了对应的结果,但是结果均为纯文本内容(因为这些提醒没有对应的UBB)。

不过,还是建议使用json类型来获取at消息的机器可读数据(不再建议了,因为msg类型不再是纯文本,而是UBB JSON,解析起来非常复杂。目前建议的解析方式详见67楼。)
at消息的json数据非常容易解析(不再容易了,详见65楼):
https://hu60.cn/q.php/msg.index.@.json?_content=json

"content": [
    {
        "type": "atMsg",
        "uid": 15591,
        "pos": "帖子“虎绿林API:Json Page”的回复中",
        "url": "bbs.topic.82570.{$BID}",
        "msg": "@老虎会游泳,多此一举",
        "len": 60
    }
]

注意URL中的“{$BID}”,它应该被替换为当前页面的bid(如html或json)。

备注:2021年1月12日更新后,聊天室删楼提醒已经和帖子删楼提醒统一了,可以正确给出json、ubb、text格式。


用户生成内容中的class标记

为了方便处理用户生成内容中的链接等元素,JSON Page在返回html格式的帖子、聊天等内容时会给用户生成的某些元素打上对应的class标记,具体如下:

  • userblocked 用户被禁言

    如:<div class="tp info-box userblocked">用户被禁言,发言自动屏蔽。</div>

  • userlatex 用户编写的latex文档

    如:<latex-js class="userlatex">一段latex文档</latex-js>

  • hu60_code 用户贴出来的代码

    如:<pre class="hu60_code"><code class="php">phpinfo();</code></pre>

  • userlink 用户贴出来的链接

    如:<a class="userlink" href="https://g.cn/">一只谷歌鸟</a>

  • usertarget 用户生成的锚链接
    如:<a class="usertarget" name="section1"></a>

  • userimg 用户贴出来的图片

    如:<img class="userimg" src="https://hu60.cn/tpl/jhin/img/logo_u16392_5.png" alt="hu60.net" />

  • userimglink 为用户图片自动生成的链接(用于点击查看大图)

    如:<a class="userimglink" href="https://hu60.cn/tpl/jhin/img/logo_u16392_5.png"><img class="userimg" src="https://hu60.cn/tpl/jhin/img/logo_u16392_5.png" alt="hu60.net" /></a>

  • userthumb 用户缩略图

    如:<img class="userthumb" src="https://hu60.cn/q.php/link.thumb.320.0.68747470733a2f2f687536302e636e2f74706c2f6a68696e2f696d672f6c6f676f5f7531363339325f352e706e67.png" alt="点击查看大图"/>

  • userthumblink 为用户缩略图自动生成的链接(用于点击查看大图)

    如:<a class="userthumblink" href="https://hu60.cn/tpl/jhin/img/logo_u16392_5.png"><img class="userthumb" src="https://hu60.cn/q.php/link.thumb.320.0.68747470733a2f2f687536302e636e2f74706c2f6a68696e2f696d672f6c6f676f5f7531363339325f352e706e67.png" alt="点击查看大图"/></a>

  • uservideosite 自动生成的视频网站链接,在用户视频播放窗口的上方

    请参考《视频:视频网站播放地址》UBB的效果

  • useraudiosite 自动生成的音频网站链接,在用户音频播放窗口的上方

    请参考《音频:音频网站播放地址》UBB的效果

  • uservideolink 自动生成的视频流链接,在用户视频播放窗口的上方

    请参考《视频流:视频下载地址》UBB的效果

  • useraudiolink 自动生成的音频流链接,在用户音频播放窗口的上方

    请参考《音频流:音频下载地址》UBB的效果

  • userbattlenet 用户发的暴雪战网链接(过时)

    如:<a class="userbattlenet" href="http://www.battlenet.com.cn/wow/zh/character/%E5%AE%89%E6%A0%BC%E5%8D%9A%E8%BE%BE/%E8%80%81%E8%99%8E%E4%BC%9A%E6%B8%B8%E6%B3%B3/simple">老虎会游泳@安格博达</a>

  • usermath 用户编写的公式

    如:<hu60-math class="usermath">一段公式</hu60-math>

  • usercss uid-<用户id> 用户定义的CSS

    如:<div class="usercss uid-1" style="color:red">红色文字</div>

  • usermail 用户发的邮箱链接

    如:<a class="usermail" href="mailto:hu60.cn@gmail.com">hu60.cn@gmail.com</a>

  • userinfo 用户个人信息链接(注意该链接是相对链接

    如:<a class="userinfo" href="user.info.1.json">老虎会游泳</a>

  • userat @用户的链接,后接用户个人信息链接

    如:<a class="userat" href="#" onclick="atAdd('虎符图腾',this);return false">@</a><a class="userinfo" href="user.info.1.json">老虎会游泳</a>

  • hu60_pos 虎绿林站内链接(出现在@消息管理员操作提醒内信中,注意该链接是相对链接

    如:<a class="userinfo" href="user.info.1.json">老虎会游泳</a> 在 <a class="hu60_pos" href="addin.chat.%E5%85%AC%E5%85%B1%E8%81%8A%E5%A4%A9%E5%AE%A4.json?floor=1#1">聊天室“公共聊天室”第1楼中</a> at你


常见的数据结构:

任何操作成功都会返回:
{'success':true}

任何操作如果失败,返回的数据都会包含以下字段:
{'success':false, 'notice':'失败原因'}

网站报错之JSON版:
https://hu60.cn/q.php/index.x.html
https://hu60.cn/q.php/index.x.json
{
"error": "true",
"errInfo": {
"code": 1404,
"message": "页面 'index.x.json' 不存在",
"file": "/var/www/hu60.cn/src/class/page.php",
"line": 137,
"trace": "#0 /var/www/hu60.cn/src/q.php(59): page->load()\n#1 {main}"
}
}

要注意,网页报错可能会在任何页面发生,所以最好先检查返回的结果中是否包含error字段。如果包含,那应该是网页报错了。


登录状态保持:

向登录页的JSON版提交用户名和密码,可以获得返回的 sid 和 cookie。

如:

curl --data 'type=1&name=老虎会游泳&pass=123&go=1' https://hu60.cn/q.php/user.login.json

你会得到

{
    "page": "loginPage",
    "success": false,
    "notice": "密码错误。",
    "active": null
}

如果密码正确,你就可以得到sid了。

如果你不保留 cookie,可以选择在之后的每个请求中,在网址的中间部分包含 sid 参数,如:

curl https://hu60.cn/q.php/你的sid/user.index.json

还可以在GET或POST中包含_sid参数:

curl -v https://hu60.cn/q.php/user.index.json?_sid=xxxxx
curl -v --data '_sid=xxx' https://hu60.cn/q.php/user.index.json

还可以通过自定义HTTP请求头x-sid传递sid:

curl -v --header 'x-sid: xxx' https://hu60.cn/q.php/user.index.json

未登录、掉线与重定向:

与 html 页面一样,在 JSON Page 中未登录/掉线用户访问登录后才能查看的页面也会跳转到登录页。

比如访问 https://hu60.cn/q.php/user.index.json 时,自动跳转到 https://hu60.cn/q.php/user.login.json?u=user.index.json

程序设计者应该考虑到这一点,避免因此而发生未预期的错误。


跨域Ajax:

通过 _origin 参数可以指定允许跨域的域名,比如:
https://hu60.cn/q.php/index.index.json?_origin=*
https://hu60.cn/q.php/你的sid/user.stat.json?_origin=g.cn,hu60.org
(_origin 参数在 html、jhtml和json等页面均可用。)

_origin参数可以通过GET或POST方式传递,也可以通过设置自定义HTTP请求头x-origin传递:

curl -v https://hu60.cn/q.php/你的sid/user.index.json?_origin=*
curl -v https://hu60.cn/q.php/user.index.json?_origin=*&_sid=xxxxx
curl -v --data '_origin=*&_sid=xxx' https://hu60.cn/q.php/user.index.json
curl -v --header 'x-origin: *' --header 'x-sid: xxx' https://hu60.cn/q.php/user.index.json

注意:一但出现 _origin 参数,虎绿林将拒绝接受或设置任何Cookie,如果你希望用户能够登录,必须按照上面例子中展示的方法传递sid。

虎绿林通过拒绝接受任何 Cookie 保证了跨域对已经在虎绿林登录的用户是安全的,用户身份信息不会被 XSS 脚本盗用。

通过拒绝设置任何 Cookie,防止跨站应用对已经在虎绿林登录的用户造成副作用,比如在跨站应用中登录另一个帐号,在虎绿林中登录的帐号并不会改变。

检测到跨站数据提交,操作需要确认

请在请求中传递_originsid参数,方法如下:

curl -v https://hu60.cn/q.php/你的sid/user.index.json?_origin=*
curl -v https://hu60.cn/q.php/user.index.json?_origin=*&_sid=xxxxx
curl -v --data '_origin=*&_sid=xxx' https://hu60.cn/q.php/user.index.json
curl -v --header 'x-origin: *' --header 'x-sid: xxx' https://hu60.cn/q.php/user.index.json

如果没有_origin参数,跨站提交就会遇到确认操作提示页面。
如果没有_sid参数,只添加了_origin参数,用户就会处于未登录状态。

总结:必须传递_origin!必须传递_origin!必须传递_origin!没有_origin就会出现“检测到跨站数据提交”。

回复列表(78)
  • @Ta / 2016-12-24
    留名
  • @Ta / 2016-12-24
    不懂
  • @Ta / 2016-12-24
    都是死在前端。。。
  • @Ta / 2016-12-24
    路过
  • @Ta / 2016-12-24
    被锁定
    层主 @小杨 于 2019-09-08 11:31 删除了该楼层。
  • @Ta / 2016-12-24
    我噗
  • @Ta / 2016-12-24
    表示之前就在想把页面的数据用js采集保存成对象 ,, 然后输出一个新的页面在把对象里的各种数据填进去    不过一直没时间去搞~
  • @Ta / 2016-12-24
  • @Ta / 2016-12-24
    @水木易安,上吧,app靠你了,你上次做的还蛮好的
  • @Ta / 2016-12-24
    帖子页面怎么不能返回UBB的形式
  • @Ta / 2016-12-25
    @net909,虎绿林的UBB解析工作非常复杂,因此由客户端自己来解析是不现实的。所以只在编辑时提供UBB,在展示时不提供。
  • @Ta / 2016-12-25
    之后可以提供选项来把相对链接变成绝对链接;不对用户输入的链接进行编码;修改at按钮调用的函数名等。
  • @Ta / 2016-12-25
    用这个写个消息机还不错!
  • @Ta / 2016-12-25
    明明就是偷懒了吧,把本来页面里的参数json打印一下
  • @Ta / 2016-12-25
    cool
  • @Ta / 2016-12-25
    @超级管理员,是啊,这个API的实现方式就是把本来页面里的参数json打印一下啊。

    @net909,说起来你们真的想要返回UBB内容吗?(返回UBB内容和返回html内容要做的事情是一样多的。因为帖子在数据库中的存储形式既不是ubb也不是html,而是php数组。)如果确实有这个需求,我可以提供。
  • @Ta / 2016-12-25
    @老虎会游泳,多此一举
  • @Ta / 2016-12-25
  • @Ta / 2016-12-25
    已经实现 json 版对用户输入的 URL 不进行编码了。
    html 版还是进行编码(从而跳转到 link.url.html)。

    之所以可以很方便的实现这个特性,是因为帖子内容的存储方式是PHP数组,每个UBB标记都被解析成一个对象,因此生成的内容可以很容易被改变。
添加新回复
回复需要登录

[聊天-摸鱼] 姜辰:所有单位在干活,而我在一边摸鱼