在 C++ REST SDK 中的 http_listener 上添加 Access-Control-Allow-Origin
add Access-Control-Allow-Origin on http_listener in C++ REST SDK
我是 运行 一个带有 web::http::experimental::listener::http_listener 来自 Microsoft C++ REST SDK 1.3.1 的 HTTP 服务器,并尝试编写 HTML&Javascript 作为客户端进行交互服务器。
毫无意外我得到了...
Cross-Origin 请求被阻止:同源策略不允许读取位于......的远程资源(原因:缺少 CORS header 'Access-Control-Allow-Origin')。
如何将 Access-Control-Allow-Origin:* 放在 http 侦听器端(在 C++ 代码中)?
在 C++ REST 1.3.1 中可以吗??
除了 JSONP 之外还有解决方法吗?
服务器
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
http_listener httpSrv;
httpSrv->support(methods::GET, handle_get);
void handle_get(http_request request)
{
const json::value response;
request.reply(status_codes::OK, response);
}
客户端
使用 jQuery v1.12.4 的客户端(绑定到 jQuery UI v1.12.0)
$("button").click(function () {
$.get(rest_url, function(data, status){
console.log(status);
console.log(data);
});
});
----------------更新---------------------
答案中的解决方案
服务器
http_listener httpSrv;
httpSrv.support(methods::GET, handle_get);
httpSrv.support(methods::POST, handle_post);
httpSrv.support(methods::OPTIONS, handle_options);
httpSrv.open().wait();
//...........
void handle_options(http_request request)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), U("GET, POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
request.reply(response);
}
void handle_get(http_request request)
{
request.reply(status_codes::OK, ...);
}
void handle_post(http_request request)
{
json::value jsonResponse;
request
.extract_json()
.then([&jsonResponse](pplx::task<json::value> task)
{
jsonResponse = process_request(task.get());
})
.wait();
http_response response(status_codes::OK);
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.set_body(jsonResponse);
request.reply(response);
}
客户
function requestREST(request/*json*/,onSuccess/*callback with json response*/) {
$.ajax({
type: "POST",
url: "...",
data: JSON.stringify(request),
dataType: 'json',
crossDomain: true,
contentType: "application/json",
success: function (response) {
onSuccess(response);
},
timeout:3000,
statusCode: {
400: function (response) {
alert('Not working!');
},
0: function (response) {
alert('Not working!');
}
}
});
要在 server-side (C++) 上添加 headers,您需要修改用于发回响应的代码。
目前,您正在使用:
request.reply(status_codes::OK, response);
与其在 one-liner 中执行此操作,不如从空响应开始自己编写响应,添加所需的 header,设置实际的 body,然后, 将响应发送回客户端。
要构造一个空响应,我们可以使用以下函数:
web::http::http_response::http_response(http::status_code code)
如the documentation中所述,它将构造一个具有给定状态代码的响应,没有 headers 也没有 body.
要访问响应的 header,我们可以使用以下函数:
web::http::http_response::headers()
返回的 object 将是 http_headers
type which contains a add
function:
web::http::http_headers::add(const key_type &name, const _t1 &value)
如果为 header.
提供了名称和值,此函数将向响应添加 header
设置 header 后,唯一需要设置的是 body。为此,响应具有 set_body
function:
web::http::http_response::set_body(const json::value &body_data)
最后,替换您的 one-liner 以创建空响应的完整代码,设置 header 和 body 然后将其发回,如下所示:
http_response response(status_codes::OK);
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.set_body(jsonResponse);
request.reply(response);
请注意,在代码的最后部分,我使用 U
宏来创建目标平台类型的字符串文字。您可以在 C++ Rest SDK FAQ.
中找到有关此 U
宏的更多信息
关于使用 OPTION
HTTP 动词的预检请求,这些在这种情况下是预期的。默认情况下,C++ REST SDK 包含这些请求的默认实现。可以在 the source code:
中检查默认实现
void details::http_listener_impl::handle_options(http_request message)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), get_supported_methods());
message.reply(response);
}
它基本上是返回 200
状态代码并添加您的服务器可以处理的支持方法列表。
如果你想覆盖默认实现,例如添加一些特定的 headers 用于预检请求,如 Access-Control-Allow-Methods
or Access-Control-Allow-Headers
,你将需要添加一个特定的处理程序,就像你为GET
和 POST
请求使用:
web::http::experimental::listener::http_listener::support(const http::method &method, const std::function< void(http_request)> &handler)
无法使用通用处理程序来处理 OPTION
请求:
web::http::experimental::listener::http_listener::support(const std::function<void(http_request)> &handler)
我们不能使用通用处理程序的原因,如果我们看一下 the source code,是因为如果一个方法没有特定的处理程序并且正在使用 OPTION
HTTP动词(或 TRACE),C++ REST SDK 实现的默认处理程序将被调用:
// Specific method handler takes priority over general.
const method &mtd = msg.method();
if(m_supported_methods.count(mtd))
{
m_supported_methods[mtd](msg);
}
else if(mtd == methods::OPTIONS)
{
handle_options(msg);
}
我是 运行 一个带有 web::http::experimental::listener::http_listener 来自 Microsoft C++ REST SDK 1.3.1 的 HTTP 服务器,并尝试编写 HTML&Javascript 作为客户端进行交互服务器。
毫无意外我得到了... Cross-Origin 请求被阻止:同源策略不允许读取位于......的远程资源(原因:缺少 CORS header 'Access-Control-Allow-Origin')。
如何将 Access-Control-Allow-Origin:* 放在 http 侦听器端(在 C++ 代码中)?
在 C++ REST 1.3.1 中可以吗?? 除了 JSONP 之外还有解决方法吗?
服务器
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
http_listener httpSrv;
httpSrv->support(methods::GET, handle_get);
void handle_get(http_request request)
{
const json::value response;
request.reply(status_codes::OK, response);
}
客户端 使用 jQuery v1.12.4 的客户端(绑定到 jQuery UI v1.12.0)
$("button").click(function () {
$.get(rest_url, function(data, status){
console.log(status);
console.log(data);
});
});
----------------更新---------------------
答案中的解决方案
服务器
http_listener httpSrv;
httpSrv.support(methods::GET, handle_get);
httpSrv.support(methods::POST, handle_post);
httpSrv.support(methods::OPTIONS, handle_options);
httpSrv.open().wait();
//...........
void handle_options(http_request request)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), U("GET, POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
request.reply(response);
}
void handle_get(http_request request)
{
request.reply(status_codes::OK, ...);
}
void handle_post(http_request request)
{
json::value jsonResponse;
request
.extract_json()
.then([&jsonResponse](pplx::task<json::value> task)
{
jsonResponse = process_request(task.get());
})
.wait();
http_response response(status_codes::OK);
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.set_body(jsonResponse);
request.reply(response);
}
客户
function requestREST(request/*json*/,onSuccess/*callback with json response*/) {
$.ajax({
type: "POST",
url: "...",
data: JSON.stringify(request),
dataType: 'json',
crossDomain: true,
contentType: "application/json",
success: function (response) {
onSuccess(response);
},
timeout:3000,
statusCode: {
400: function (response) {
alert('Not working!');
},
0: function (response) {
alert('Not working!');
}
}
});
要在 server-side (C++) 上添加 headers,您需要修改用于发回响应的代码。
目前,您正在使用:
request.reply(status_codes::OK, response);
与其在 one-liner 中执行此操作,不如从空响应开始自己编写响应,添加所需的 header,设置实际的 body,然后, 将响应发送回客户端。
要构造一个空响应,我们可以使用以下函数:
web::http::http_response::http_response(http::status_code code)
如the documentation中所述,它将构造一个具有给定状态代码的响应,没有 headers 也没有 body.
要访问响应的 header,我们可以使用以下函数:
web::http::http_response::headers()
返回的 object 将是 http_headers
type which contains a add
function:
web::http::http_headers::add(const key_type &name, const _t1 &value)
如果为 header.
提供了名称和值,此函数将向响应添加 header设置 header 后,唯一需要设置的是 body。为此,响应具有 set_body
function:
web::http::http_response::set_body(const json::value &body_data)
最后,替换您的 one-liner 以创建空响应的完整代码,设置 header 和 body 然后将其发回,如下所示:
http_response response(status_codes::OK);
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.set_body(jsonResponse);
request.reply(response);
请注意,在代码的最后部分,我使用 U
宏来创建目标平台类型的字符串文字。您可以在 C++ Rest SDK FAQ.
U
宏的更多信息
关于使用 OPTION
HTTP 动词的预检请求,这些在这种情况下是预期的。默认情况下,C++ REST SDK 包含这些请求的默认实现。可以在 the source code:
void details::http_listener_impl::handle_options(http_request message)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), get_supported_methods());
message.reply(response);
}
它基本上是返回 200
状态代码并添加您的服务器可以处理的支持方法列表。
如果你想覆盖默认实现,例如添加一些特定的 headers 用于预检请求,如 Access-Control-Allow-Methods
or Access-Control-Allow-Headers
,你将需要添加一个特定的处理程序,就像你为GET
和 POST
请求使用:
web::http::experimental::listener::http_listener::support(const http::method &method, const std::function< void(http_request)> &handler)
无法使用通用处理程序来处理 OPTION
请求:
web::http::experimental::listener::http_listener::support(const std::function<void(http_request)> &handler)
我们不能使用通用处理程序的原因,如果我们看一下 the source code,是因为如果一个方法没有特定的处理程序并且正在使用 OPTION
HTTP动词(或 TRACE),C++ REST SDK 实现的默认处理程序将被调用:
// Specific method handler takes priority over general.
const method &mtd = msg.method();
if(m_supported_methods.count(mtd))
{
m_supported_methods[mtd](msg);
}
else if(mtd == methods::OPTIONS)
{
handle_options(msg);
}