WordPress有一个功能:当有人引用本站文章时,会添加一条评论在文后,显示引用页面的信息;发博客时WordPress也会通知文章内每个链接,让它知道自己被引用了。这个功能非常赞,让博客间的互动变得更容易。看到屈屈文章Pingback和Xml-RPC便心血来潮,于是在自己博客中添加了此功能。
Pingback是基于XML-RPC协议,需要实现一个client
和一个server
。client
用于文章更新时ping对方服务;server
用于处理对方的ping。
具体实现
client
文章更新时候,提取文章内引用链接。
请求引用链接,获取server地址(响应头:
X-Pingback
)。
const Base = require('./base');
const fetch = require('node-fetch');
const https = require('https');
// 忽略HTTPS证书验证
const agentOptions = {
agent: new https.Agent({ rejectUnauthorized: false }),
};
const isDev = think.env === 'development';
module.exports = class extends Base {
async pingAction() {
const options = await this.model('options').getOptions();
const pingback = JSON.parse(options.pingback);
const data = this.post();
const params = [];
//1.提取url链接
// eslint--next-line no-useless-escape
const urls = data.markdown_content.match(/[^\!]{0,1}\[.*\]\((.*?)\)/gms).map((url) => {
return url.replace(/.*\[.*\]\((.*)\)/, '$1');
});
//2.获取url对应pingback server
for (let i = 0; i < urls.length; i++) {
if (urls[i].endsWith('?pingback=true')) {
continue;
}
const pingbackServer = await fetch(urls[i], agentOptions).then((res) => {
return res.headers.get('X-Pingback') || '';
});
if (pingbackServer !== '') {
params.push({
pagelinkedfrom: `${this.ctx.request.origin}/post/${data.pathname}.html`,
pagelinkedto: urls[i],
pingbackServer: pingbackServer,
});
}
}
//3.通过本地pingback client 调用 远程pingback server
let isPingback = false;
for (let i = 0; i < params.length; i++) {
const res = await fetch(isDev ? 'http://127.0.0.1:8361' : pingback.client, {
method: 'POST',
body: JSON.stringify(params[i]),
}).then((res) => {
if (res.status === 200) {
return 'success';
}
return 'fail';
});
if (res === 'success') {
data.markdown_content = data.markdown_content.replace(
params[i].pagelinkedto,
params[i].pagelinkedto + '?pingback=true',
);
isPingback = true;
}
}
if (isPingback) {
return this.success(data.markdown_content);
}
return this.fail('pingback exist or error');
}
// async backAction(){
// return this.success()
// }
};
- 发送本文地址、引用地址到server。
from http.server import HTTPServer, SimpleHTTPRequestHandler
import xmlrpc.client
import json
host = ('localhost', 8361)
class Resquest(SimpleHTTPRequestHandler):
def do_POST(self):
post = self.rfile.read(int(self.headers['content-length']))
post = json.loads(post.decode("utf-8", 'ignore'))
pingbackServer = post['pingbackServer']
try:
with xmlrpc.client.ServerProxy(pingbackServer) as proxy:
res = proxy.pingback(post["pagelinkedfrom"],post["pagelinkedto"])
if res == "success":
self.send_response(200)
self.send_header("Content-type","text/plain")
self.end_headers()
self.wfile.write(res.encode())
else:
self.send_error(code=500,message="fail")
except Exception:
print(Exception)
self.send_error(code=500,message="fail")
if __name__ == '__main__':
server = HTTPServer(host, Resquest)
print("pingback client, listen at: %s:%s" % host)
server.serve_forever()
server
提取上述本文地址的标题。
调用评论系统api。
import xmlrpc.server
import requests
import re
blogCommentServer = 'https://comment.imyoyo.xyz/comment'
host = ('localhost', 8362)
def extractTitle(url):
r = requests.get(url, verify=False).text
return re.findall(r"<title>(.*)</title>", r)[0]
def pingback(pagelinkedfrom , pagelinkedto):
#1.提取pagelinkedfrom标题
title = extractTitle(pagelinkedfrom)
#2.添加评论
data={
"comment":"博客引文 :[{}]({})".format(title,pagelinkedfrom),
"nick":"引用助手",
"mail":"huyong@bupt.edu.cn",
"link":"https://imyoyo.xyz/",
"url":pagelinkedto[pagelinkedto.find("/post"):]
}
headers={
"content-type": "application/json",
"authorization": "xxxxxx"
}
r = requests.post(blogCommentServer,headers=headers,json=data,verify=False).json()
print(r)
if r["errno"] == 0:
return "success"
else:
return "fail"
def main():
with xmlrpc.server.SimpleXMLRPCServer(host) as server:
server.register_introspection_functions()
server.register_function(pingback)
server.serve_forever()
if __name__ == "__main__":
print("pingback server, listen at: %s:%s" % host)
main()
效果
遇到问题
python requests 在python3.7环境运行报错。
Nginx域名转发配置报错。
Comments