- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个 Web 服务来为 jeasyui 提供 json 对象。异步树。我的 HTML 有以下内容:
<ul id="tt" method="POST" class="easyui-tree" url="http://w.x.y.z:1024/testrest">
</ul>
id
,
text
, 和
state
.好的,到目前为止一切顺利。我正在尝试使用 Microsoft 的 cpprest-sdk 在 C++ 中开发 json 服务。我在 RHEL 7.2 上编译并安装了这个库,并且能够使用它编写一些基本服务。问题在于(我认为)与发送回客户端的 json 编码有关。
#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;
}
./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
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;
@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
charset=utf-8
在里面。如果我使用
-o
将 curl 输出转储到文件中开关,我看不出编码之间有任何明显的区别。我唯一能看到的 json 格式不同的是一些额外的空格和排序:
[{"text": "Hello", "state": "closed", "id": "1"}] // web2py version
[{"id":"1","state":"closed","text":"Hello"}] // cpprest version
http_request::reply
有许多覆盖。其中包括设置内容类型的选项,我已经走上了用硬编码字符串调用它们的道路,用于 json 正文和
json/application; charset=utf-8
的内容类型,一切都无济于事。无论如何,我看不到这些覆盖如何与 json::value 对象一起使用,因此我认为这不是此 cpprest 库的最佳路径或可行使用。
最佳答案
所以我弄清楚发生了什么。在 Chrome 中打开开发者工具控制台,发现以下错误消息:
XMLHttpRequest 无法加载 http://w.x.y.z:1024/testrest .请求的资源上不存在“Access-Control-Allow-Origin” header 。产地'http://w.x.y.z ' 因此不允许访问。
因此,它与我的 json 数据的格式或编码无关,而是 json 服务被识别为与生成客户端 HTML 的 Web 服务器不同的资源这一事实,因此 Chrome 被阻止它。为了解决这个问题,我必须在发送回客户端的响应中添加一些 header 字段,并添加一个支持方法来处理来自任何可能需要它们的客户端的 OPTIONS 查询。
在我的 main() 函数中,我添加了:
listener.support(methods::OPTIONS, handle_options);
void handle_options(http_request request)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), U("POST, OPTIONS"));
// Modify "Access-Control-Allow-Origin" header below to suit your security needs. * indicates allow all clients
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
request.reply(response);
}
http_response response(status_codes::OK);
// Without these headers, the client browser will likely refuse the data and eat it
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
response.set_body(answer);
request.reply(response);
easyui_tree
不发布 Content-Type 为
application/json
的数据.相反,它发布了一个 Content-Type
application/x-www-form-urlencoded
,所以我不得不添加一个函数来使用 libcurl 解析 url 编码。这也意味着替换
request.extract_json()
与
request.extract_string()
以及对 cpprest 使用的相应 lambda 函数的相关修改。
#include <boost/algorithm/string/replace.hpp>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <curl/curl.h>
#pragma comment(lib, "cpprestlib" )
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <string>
using namespace std;
#define TRACE(msg) wcout << msg
void build_json( const utility::string_t &source, json::value &jvalue )
{
// Use libcurl to unescape the POST body for us
vector<string> splitvec;
// We don't own the string created by curl_easy_unescape, so add a custom deleter
string text = shared_ptr<char>( curl_easy_unescape( 0, source.c_str(), 0, 0 ), curl_free).get();
// This works for this specific example of jeasyui, the class 'easyui-tree', which only passes id=... in the POST.
// Need custom handler to deal with more complicated data formats
boost::split( splitvec, text, boost::is_any_of("="));
if( splitvec.size() == 2 )
{
jvalue[splitvec.at(0)] = json::value::string(splitvec.at(1));
}
}
void handle_request(http_request request, function<void(const json::value &, json::value &, bool)> action)
{
json::value answer;
auto objHeader = request.headers();
auto sContentType = objHeader["Content-Type"];
// Two cases:
// 1) The very first call from easyui_tree, when the HTML is first loaded, will make a zero-length POST with no 'Content-Type' in the header
// 2) Subsequent calls from easyui_tree (e.g. when user opens a node) will have a Content-Type of 'application/x-www-form-urlencoded'
// Nowhere does easyui_tree send json data in the POST, although it expects json in the reply
if( sContentType.size() == 0 ||
!strncasecmp( sContentType.c_str(), "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded") ) )
{
request
.extract_string()
.then([&answer, &action](pplx::task<utility::string_t> task) {
try
{
const auto & svalue = task.get();
json::value jvalue;
if ( svalue.size() == 0 )
{
action(jvalue, answer, true);
}
else
{
build_json( svalue, jvalue );
action(jvalue, answer, false);
}
}
catch (http_exception const & e)
{
wcout << "HTTP exception in handle_request: " << e.what() << endl;
}
})
.wait();
}
else
{
// This Content-Type doesn't appear with easyui_tree, but perhaps it's still useful for future cases...
if( !strncasecmp( sContentType.c_str(), "application/json", strlen("application/json") ) )
{
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();
}
}
http_response response(status_codes::OK);
// Without these headers, the client browser will likely refuse the data and eat it
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
response.set_body(answer);
request.reply(response);
}
void handle_options(http_request request)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), U("POST, OPTIONS"));
// Modify "Access-Control-Allow-Origin" header below to suit your security needs. * indicates allow all clients
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
request.reply(response);
}
void handle_post(http_request request)
{
handle_request(
request,
[](const json::value & jvalue, json::value & answer, bool bInitialize)
{
if( bInitialize )
{
// First time the tree is being loaded, first id will be 16, which will yield us 16 child nodes when it POSTs back
json::value jreply;
jreply[U("id")] = json::value::string("16");
jreply[U("text")] = json::value::string("Parent");
jreply[U("state")] = json::value::string("closed");
answer[0] = jreply;
}
else
{
// User has opened a node
if( jvalue.type() == json::value::value_type::Object )
{
if( jvalue.has_field( "id" ) )
{
auto & key = jvalue.at( "id" );
if( key.is_string() )
{
auto value = key.as_string();
int id = atoi(value.c_str());
stringstream ss;
ss << (id / 2); // Each successive layer has half as many child nodes as the one prior
for( int i = 0; i < id; i++ )
{
json::value jreply;
jreply[U("id")] = json::value::string(ss.str());
jreply[U("text")] = json::value::string("Child");
jreply[U("state")] = json::value::string("closed");
answer[i] = jreply;
}
}
}
}
}
}
);
}
int main()
{
uri_builder uri("http://yourserver.com:1024/testrest");
http_listener listener(uri.to_uri());
listener.support(methods::POST, handle_post);
listener.support(methods::OPTIONS, handle_options);
try
{
listener
.open()
.then([&listener]()
{
TRACE(L"\nStarting to listen\n");
})
.wait();
while (true);
}
catch (exception const & e)
{
wcout << e.what() << endl;
}
return 0;
}
<ul id="tt" method="POST" class="easyui-tree" url="http://yourserver.com:1024/testrest">
</ul>
关于json - 使用 cpprest-sdk 的 json 服务的 POST 问题,连接到 jeasyui,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41815713/
最近开始学习MongoDB。今天老师教了我们 mongoexport 命令。在练习时,我遇到了一个典型的问题,包括教练在内的其他同学都没有遇到过。我在我的 Windows 10 机器上使用 Mongo
我是 JSON Schema 的新手,读过什么是 JSON Schema 等等。但我不知道如何将 JSON Schema 链接到 JSON 以针对该 JSON Schema 进行验证。谁能解释一下?
在 xml 中,我可以在另一个 xml 文件中包含一个文件并使用它。如果您的软件从 xml 获取配置文件但没有任何方法来分离配置,如 apache/ngnix(nginx.conf - site-av
我有一个 JSON 对象,其中包含一个本身是 JSON 对象的字符串。我如何反序列化它? 我希望能够做类似的事情: #[derive(Deserialize)] struct B { c: S
考虑以下 JSON { "a": "{\"b\": 12, \"c\": \"test\"}" } 我想定义一个泛型读取 Reads[Outer[T]]对于这种序列化的 Json import
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 11 个月前关闭。 Improve
我的旧项目在 MySQL 中有 Standard JSON 格式的数据。 对于我在 JS (Node.js) 和 DynamoDB 中的全新项目,关于 Standard JSON格式: 是否建议将其转
JSON 值字符串、数字、true、false、null 是否是有效的 JSON? 即,是 true 一个有效的 JSON 文档?还是必须是数组/对象? 一些验证器接受这个(例如 http://jso
我有一个 JSON 字符串,其中一个字段是文本字段。这个文本字段可以包含用户在 UI 中输入的文本,如果他们输入的文本是 JSON 文本,也许是为了说明一些编码,我需要对他们的文本进行编码,以便它不会
我正在通过 IBM MQ 调用处理数据,当由 ColdFusion 10 (10,0,11,285437) 序列化时,0 将作为 +0.0 返回,它会导致无效的 JSON并且无法反序列化。 stPol
我正在从三个数组中生成一个散列,然后尝试构建一个 json。我通过 json object has array 成功了。 require 'json' A = [['A1', 'A2', 'A3'],
我从 API 接收 JSON,响应可以是 30 种类型之一。每种类型都有一组唯一的字段,但所有响应都有一个字段 type 说明它是哪种类型。 我的方法是使用serde .我为每种响应类型创建一个结构并
我正在下载一个 JSON 文件,我已将其检查为带有“https://jsonlint.com”的有效 JSON 到文档目录。然后我打开文件并再次检查,结果显示为无效的 JSON。这怎么可能????这是
我正在尝试根据从 API 接收到的数据动态创建一个 JSON 对象。 收到的示例数据:将数据解码到下面给出的 CiItems 结构中 { "class_name": "test", "
我想从字符串转换为对象。 来自 {"key1": "{\n \"key2\": \"value2\",\n \"key3\": {\n \"key4\": \"value4\"\n }\n
目前我正在使用以下代码将嵌套的 json 转换为扁平化的 json: import ( "fmt" "github.com/nytlabs/gojsonexplode" ) func
我有一个使用来自第三方 API 的数据的应用程序。我需要将 json 解码为一个结构,这需要该结构具有“传入”json 字段的 json 标签。传出的 json 字段具有不同的命名约定,因此我需要不同
我想使用 JSON 架构来验证某些值。我有两个对象,称它们为 trackedItems 和 trackedItemGroups。 trackedItemGroups 是组名称和 trackedItem
考虑以下案例类模式, case class Y (a: String, b: String) case class X (dummy: String, b: Y) 字段b是可选的,我的一些数据集没有字
我正在存储 cat ~/path/to/file/blah | 的输出jq tojson 在一个变量中,稍后在带有 JSON 内容的 curl POST 中使用。它运作良好,但它删除了所有换行符。我知
我是一名优秀的程序员,十分优秀!