我正在开发一个 Web 服务来为jeasyui异步树提供 json 对象。我的 HTML 有以下内容:
<ul id="tt" method="POST" class="easyui-tree" url="http://w.x.y.z:1024/testrest">
</ul>
假设 wxyz 是我服务器的 IP 地址。根据他们的 PHP json 服务的 jeasyui 文档,我需要返回一个字典对象数组,其中包含id
、text
和state
. 好的,到目前为止一切顺利。我正在尝试使用 Microsoft 的 cpprest-sdk 在 c++ 中开发 json 服务。我在 RHEL 7.2 上编译并安装了这个库,并且能够使用它编写一些基本服务。问题在于(我认为)与发送回客户端的 json 编码有关。
这是一个使用 cpprest-sdk 编写的全功能示例 json 服务器,它处理 POST 请求并使用符合 jeasyui 预期协议的字典对象的单个填充数组进行回复:
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#pragma comment(lib, "cpprestlib" )
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
#define TRACE(msg) wcout << msg
void handle_request(http_request request, function<void(const json::value &, json::value &, bool)> action)
{
json::value answer;
TRACE("\nHandle_request\n");
// Spit out the HTTP header to the console...
const auto HeaderString = request.to_string();
wcout << HeaderString.c_str() << endl;
request
.extract_json()
.then([&answer, &action](pplx::task<json::value> task) {
try
{
const auto & jvalue = task.get();
if (!jvalue.is_null())
{
action(jvalue, answer, false);
}
else
{
action(jvalue, answer, true);
}
}
catch (http_exception const & e)
{
wcout << "HTTP exception in handle_request: " << e.what() << endl;
}
})
.wait();
request.reply(status_codes::OK, answer);
}
void handle_post(http_request request)
{
TRACE("\nHandle POST\n");
handle_request(
request,
[](const json::value & jvalue, json::value & answer, bool bNull)
{
const utility::string_t sID("id");
const utility::string_t sText("text");
const utility::string_t sState("state");
if( bNull )
{
wcout << "jvalue must be null, setting some default values..." << endl;
json::value group;
group[sID] = json::value::string("1");
group[sText] = json::value::string("Hello");
group[sState] = json::value::string("closed");
answer[0] = group;
}
else
{
// To be written once the null case is sorted
}
}
);
}
int main()
{
uri_builder uri("http://w.x.y.z:1024/testrest");
http_listener listener(uri.to_uri());
listener.support(methods::POST, handle_post);
try
{
listener
.open()
.then([&listener]()
{
TRACE(L"\nStarting to listen\n");
})
.wait();
while (true);
}
catch (exception const & e)
{
wcout << e.what() << endl;
}
return 0;
}
这可以干净地编译,我可以使用以下命令在 linux 服务器上启动服务:
./testrest &
Starting to listen
为了帮助调试,我一直在使用curl
直接在同一个 linux 服务器上充当 POST 客户端。我一直在使用以下命令发送内容长度为 0 的 POST 请求:
curl -i -X POST -H 'Content-Type: application/json' http://w.x.y.z:1024/testrest
curl 的输出如下:
HTTP/1.1 200 OK
Content-Length: 44
Content-Type: application/json
[{"id":"1","state":"closed","text":"Hello"}]
来自我的服务的控制台消息如下:
Handle POST
Handle_request
POST /testrest HTTP/1.1
Accept: */*
Content-Type: application/json
Host: w.x.y.z:1024
User-Agent: curl/7.29.0
jvalue must be null, setting some default values...
前两行对应TRACE
于代码中的调用。中间部分是由这段代码生成的:
// Spit out the HTTP header to the console...
const auto HeaderString = request.to_string();
wcout << HeaderString.c_str() << endl;
基于 curl 输出,它是一个字典对象数组,只有一个条目长,我希望这个服务可以与客户端上的jeasyui javascript 一起正常工作。但是,事实并非如此。我的异步树永远不会填充,我什么也看不到。
我怀疑编码有问题,所以我使用 web2py 编写了另一个服务来测试它是否可以在那里工作。我的 default.py 控制器中存在以下代码:
@service.json
def testweb2py():
aRet=[]
if request.post_vars.id is None:
mydict={'id':'1','text':'Hello','state':'closed'}
aRet.append(mydict)
return aRet
在修改我的客户端easyui-tree
HTML 以指向 web2py URL 后,它完美地填充并且我可以看到该节点。我用 curl 打了 web2py service.json 代码,只是为了看看输出可能会有什么不同:
HTTP/1.1 200 OK
Date: Mon, 23 Jan 2017 18:17:17 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_wsgi/3.4 Python/2.7.5
X-Powered-By: web2py
Expires: Mon, 23 Jan 2017 18:17:18 GMT
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Length: 99
Content-Type: application/json; charset=utf-8
[{"text": "Hello", "state": "closed", "id": "1"}]
除了内容标题完全不同之外,我怀疑有一行可能与它有关:
Content-Type: application/json; charset=utf-8
在对 cpprest 服务的调用中,curl 输出的标头不包含charset=utf-8
在其中。如果我使用开关将 curl 输出转储到文件中-o
,我看不出编码之间有任何明显的区别。我唯一能看到的 json 格式不同的是一些额外的空格和排序:
[{"text": "Hello", "state": "closed", "id": "1"}] // web2py version
[{"id":"1","state":"closed","text":"Hello"}] // cpprest version
我无法控制 json 字典的发送顺序,但我怀疑这与它有什么关系。值条目前面的额外空格似乎也无关紧要。
我已经在 microsoft.github.io/cpprestsdk/index.html 上翻阅了 cpprest 文档,但找不到与设置输出编码相关的任何内容。有许多覆盖http_request::reply
包括用于设置内容类型的选项,我已经走上了用 json 正文和内容类型的硬编码字符串调用它们的道路,json/application; charset=utf-8
但都无济于事。无论如何,我看不到这些覆盖如何与 json::value 对象一起使用,因此我认为这不是此 cpprest 库的最佳路径或可行使用。
jeasyui javascript 代码似乎是故意混淆的,我不太相信能够弄清楚它对 POST 调用的回复做了什么。也许熟悉 jeasyui 的人可以指出调试异步 POST 的可行方法?
请帮忙!