Ejabberd api set_vcard database_failure
Ejabberd api set_vcard database_failure
当我对 ejabberd 使用以下命令时 API 我得到以下响应;
curl -ik -X POST -H 'Authorization: Bearer xxxxxxxxxxx' https://localhost:5280/api/set_vcard -d '{"user":"foo","host":"example.com","name":"FN","content":"foobar"}'
HTTP/1.1 400 Bad Request
Content-Length: 18
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type, Authorization, X-Admin
"database_failure"
在 ejabberd 日志(级别 5)上,我看到了这个;
[info] (<0.607.0>) Accepted connection ::ffff:172.18.0.1:46622 -> ::ffff:172.18.0.3:5280
[debug] S: [{[<<"ws">>],ejabberd_http_ws},{[<<"bosh">>],mod_bosh},{[<<"oauth">>],ejabberd_oauth},{[<<"api">>],mod_http_api},{[<<"admin">>],ejabberd_web_admin}]
[debug] ({tlssock,#Port<0.18819>,#Ref<0.650175335.3240493057.203147>}) http query: 'POST' <<"/api/set_vcard">>
[debug] client data: <<"{\"user\":\"foo\",\"host\":\"example.com\",\"contents\":[\"FN:foobar\"]}">>
[debug] [<<"api">>,<<"set_vcard">>] matches [<<"api">>]
[info] API call set_vcard [{<<"user">>,<<"foo">>},{<<"host">>,<<"example.com">>},{<<"contents">>,[<<"FN:foobar">>]}] from ::ffff:172.18.0.1:46622
[debug] Command 'set_vcard' execution allowed by rule 'api service' (CallerInfo=#{caller_module => mod_http_api,caller_server => <<"example.com">>,ip => {0,0,0,0,0,65535,44050,1},oauth_scope => [<<"ejabberd:api-service">>],usr => {<<"admin">>,<<"example.com">>,<<>>}})
[debug] Executing command mod_admin_extra:set_vcard with Args=[<<"foo">>,<<"example.com">>,<<>>,<<>>,[<<"FN:foobar">>]]
它使用 MySQL 作为数据库(其他一切都正常工作)但是当我查看数据库一般查询日志时,我没有看到我的 API 请求触发任何查询。我看到了所有其他正常的 ejabberd 查询,因此数据库连接没有问题,并且如前所述,其他一切正常。
$ ejabberdctl status
The node ejabberd@e87da11aa894 is started with status: started
ejabberd 18.4.0 is running in that node
有没有人有任何线索可以帮我解决?我 运行 找不到可能是什么问题的线索。
!!!编辑!!!
解决方法
如 https://github.com/processone/ejabberd/issues/2629 中所述,其他人也遇到过此问题。更改配置以禁用缓存并清除数据库中的 vcard table 似乎是一种解决方法;
SQL:
DELETE FROM vcard;
配置:
...
mod_vcard:
search: false
use_cache: false
...
请注意您的日志中显示:
[debug] client data: <<"{\"user\":\"foo\",\"host\":\"example.com\",\"contents\":[\"FN:foobar\"]}">>
contents怎么会是FN:foobar呢?我安装了 18.04,设置 mysql 存储,运行 这个查询:
$ curl -v -H "X-Admin: true" -H "Content-Type:application/json" http://localhost:5280/api/set_vcard -d '{"user":"user1","host":"localhost","name":"FN","content":"mi nombre curllll"}'
日志说:
21:42:29.638 [info] (<0.487.0>) Accepted connection 127.0.0.1:58412 -> 127.0.0.1:5280
21:42:29.638 [debug] S: [{[<<"api">>],mod_http_api},{[<<"bosh">>],mod_bosh},{[<<"oauth">>],ejabberd_oauth},{[<<"presence">>],mod_webpresence},{[<<"register">>],mod_register_web},{[<<"rest">>],mod_rest},{[<<"ws">>],ejabberd_http_ws},{[<<"admin">>],ejabberd_web_admin}]
21:42:29.639 [debug] (#Port<0.18079>) http query: 'POST' <<"/api/set_vcard">>
21:42:29.639 [debug] client data: <<"{\"user\":\"user1\",\"host\":\"localhost\",\"name\":\"FN\",\"content\":\"mi nombre curllll\"}">>
21:42:29.639 [debug] [<<"api">>,<<"set_vcard">>] matches [<<"api">>]
21:42:29.639 [info] API call set_vcard [{<<"user">>,<<"user1">>},{<<"host">>,<<"localhost">>},{<<"name">>,<<"FN">>},{<<"content">>,<<"mi nombre curllll">>}] from 127.0.0.1:58412
21:42:29.640 [debug] Command 'set_vcard' execution allowed by rule 'test commands' (CallerInfo=#{caller_module => mod_http_api,ip => {127,0,0,1}})
21:42:29.640 [debug] Executing command mod_admin_extra:set_vcard with Args=[<<"user1">>,<<"localhost">>,<<"FN">>,<<"mi nombre curllll">>]
21:42:29.640 [debug] SQL: "select vcard from vcard where username='user1' and 0=0"
21:42:29.642 [debug] SQL: "begin;"
21:42:29.642 [debug] SQL: "UPDATE vcard SET vcard='<vCard xmlns=''vcard-temp''><FN>mi nombre curllll</FN><N><FAMILY>mi familia11</FAMILY></N><NICKNAME>mi apodoooooooooooooooooooo11</NICKNAME><PHOTO><BINVAL>R0lGODlhDwAPAJECAP//AAAAAP///wAAACH5BAEAAAIALAAAAAAPAA8AAAIulB2Zx5IA4WIhWnnqvQFJDTyhE4khaG5Wqn4tp4ErFnMY+Sll9naUfGpkFL5DAQA7</BINVAL><TYPE>image/gif</TYPE></PHOTO></vCard>' WHERE username='user1'"
21:42:29.644 [debug] SQL: "UPDATE vcard_search SET username='user1', fn='mi nombre curllll', lfn='mi nombre curllll', family='mi familia11', lfamily='mi familia11', given='', lgiven='', middle='', lmiddle='', nickname='mi apodoooooooooooooooooooo11', lnickname='mi apodoooooooooooooooooooo11', bday='', lbday='', ctry='', lctry='', locality='', llocality='', email='', lemail='', orgname='', lorgname='', orgunit='', lorgunit='' WHERE lusername='user1'"
21:42:29.658 [debug] SQL: "commit;"
API 在允许的范围内相当宽松,但是一旦它在数据库中,记录将无法加载。
对于'set_vcard','名称'是您要更改的字段名称,内容是该字段的内容。
{
"user": "catman",
"host": "the.host",
"name": "FN",
"content": "Cat Man"
}
ejabberd 也缓存查询,所以一旦你有一个 barfed 记录它会 return 'database_failed' 即使你已经更正了你的 api 调用或在数据库中修复它手。可以在模块配置下禁用缓存。
当我对 ejabberd 使用以下命令时 API 我得到以下响应;
curl -ik -X POST -H 'Authorization: Bearer xxxxxxxxxxx' https://localhost:5280/api/set_vcard -d '{"user":"foo","host":"example.com","name":"FN","content":"foobar"}'
HTTP/1.1 400 Bad Request
Content-Length: 18
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type, Authorization, X-Admin
"database_failure"
在 ejabberd 日志(级别 5)上,我看到了这个;
[info] (<0.607.0>) Accepted connection ::ffff:172.18.0.1:46622 -> ::ffff:172.18.0.3:5280
[debug] S: [{[<<"ws">>],ejabberd_http_ws},{[<<"bosh">>],mod_bosh},{[<<"oauth">>],ejabberd_oauth},{[<<"api">>],mod_http_api},{[<<"admin">>],ejabberd_web_admin}]
[debug] ({tlssock,#Port<0.18819>,#Ref<0.650175335.3240493057.203147>}) http query: 'POST' <<"/api/set_vcard">>
[debug] client data: <<"{\"user\":\"foo\",\"host\":\"example.com\",\"contents\":[\"FN:foobar\"]}">>
[debug] [<<"api">>,<<"set_vcard">>] matches [<<"api">>]
[info] API call set_vcard [{<<"user">>,<<"foo">>},{<<"host">>,<<"example.com">>},{<<"contents">>,[<<"FN:foobar">>]}] from ::ffff:172.18.0.1:46622
[debug] Command 'set_vcard' execution allowed by rule 'api service' (CallerInfo=#{caller_module => mod_http_api,caller_server => <<"example.com">>,ip => {0,0,0,0,0,65535,44050,1},oauth_scope => [<<"ejabberd:api-service">>],usr => {<<"admin">>,<<"example.com">>,<<>>}})
[debug] Executing command mod_admin_extra:set_vcard with Args=[<<"foo">>,<<"example.com">>,<<>>,<<>>,[<<"FN:foobar">>]]
它使用 MySQL 作为数据库(其他一切都正常工作)但是当我查看数据库一般查询日志时,我没有看到我的 API 请求触发任何查询。我看到了所有其他正常的 ejabberd 查询,因此数据库连接没有问题,并且如前所述,其他一切正常。
$ ejabberdctl status
The node ejabberd@e87da11aa894 is started with status: started
ejabberd 18.4.0 is running in that node
有没有人有任何线索可以帮我解决?我 运行 找不到可能是什么问题的线索。
!!!编辑!!!
解决方法
如 https://github.com/processone/ejabberd/issues/2629 中所述,其他人也遇到过此问题。更改配置以禁用缓存并清除数据库中的 vcard table 似乎是一种解决方法;
SQL:
DELETE FROM vcard;
配置:
...
mod_vcard:
search: false
use_cache: false
...
请注意您的日志中显示:
[debug] client data: <<"{\"user\":\"foo\",\"host\":\"example.com\",\"contents\":[\"FN:foobar\"]}">>
contents怎么会是FN:foobar呢?我安装了 18.04,设置 mysql 存储,运行 这个查询:
$ curl -v -H "X-Admin: true" -H "Content-Type:application/json" http://localhost:5280/api/set_vcard -d '{"user":"user1","host":"localhost","name":"FN","content":"mi nombre curllll"}'
日志说:
21:42:29.638 [info] (<0.487.0>) Accepted connection 127.0.0.1:58412 -> 127.0.0.1:5280
21:42:29.638 [debug] S: [{[<<"api">>],mod_http_api},{[<<"bosh">>],mod_bosh},{[<<"oauth">>],ejabberd_oauth},{[<<"presence">>],mod_webpresence},{[<<"register">>],mod_register_web},{[<<"rest">>],mod_rest},{[<<"ws">>],ejabberd_http_ws},{[<<"admin">>],ejabberd_web_admin}]
21:42:29.639 [debug] (#Port<0.18079>) http query: 'POST' <<"/api/set_vcard">>
21:42:29.639 [debug] client data: <<"{\"user\":\"user1\",\"host\":\"localhost\",\"name\":\"FN\",\"content\":\"mi nombre curllll\"}">>
21:42:29.639 [debug] [<<"api">>,<<"set_vcard">>] matches [<<"api">>]
21:42:29.639 [info] API call set_vcard [{<<"user">>,<<"user1">>},{<<"host">>,<<"localhost">>},{<<"name">>,<<"FN">>},{<<"content">>,<<"mi nombre curllll">>}] from 127.0.0.1:58412
21:42:29.640 [debug] Command 'set_vcard' execution allowed by rule 'test commands' (CallerInfo=#{caller_module => mod_http_api,ip => {127,0,0,1}})
21:42:29.640 [debug] Executing command mod_admin_extra:set_vcard with Args=[<<"user1">>,<<"localhost">>,<<"FN">>,<<"mi nombre curllll">>]
21:42:29.640 [debug] SQL: "select vcard from vcard where username='user1' and 0=0"
21:42:29.642 [debug] SQL: "begin;"
21:42:29.642 [debug] SQL: "UPDATE vcard SET vcard='<vCard xmlns=''vcard-temp''><FN>mi nombre curllll</FN><N><FAMILY>mi familia11</FAMILY></N><NICKNAME>mi apodoooooooooooooooooooo11</NICKNAME><PHOTO><BINVAL>R0lGODlhDwAPAJECAP//AAAAAP///wAAACH5BAEAAAIALAAAAAAPAA8AAAIulB2Zx5IA4WIhWnnqvQFJDTyhE4khaG5Wqn4tp4ErFnMY+Sll9naUfGpkFL5DAQA7</BINVAL><TYPE>image/gif</TYPE></PHOTO></vCard>' WHERE username='user1'"
21:42:29.644 [debug] SQL: "UPDATE vcard_search SET username='user1', fn='mi nombre curllll', lfn='mi nombre curllll', family='mi familia11', lfamily='mi familia11', given='', lgiven='', middle='', lmiddle='', nickname='mi apodoooooooooooooooooooo11', lnickname='mi apodoooooooooooooooooooo11', bday='', lbday='', ctry='', lctry='', locality='', llocality='', email='', lemail='', orgname='', lorgname='', orgunit='', lorgunit='' WHERE lusername='user1'"
21:42:29.658 [debug] SQL: "commit;"
API 在允许的范围内相当宽松,但是一旦它在数据库中,记录将无法加载。
对于'set_vcard','名称'是您要更改的字段名称,内容是该字段的内容。
{
"user": "catman",
"host": "the.host",
"name": "FN",
"content": "Cat Man"
}
ejabberd 也缓存查询,所以一旦你有一个 barfed 记录它会 return 'database_failed' 即使你已经更正了你的 api 调用或在数据库中修复它手。可以在模块配置下禁用缓存。