乐趣区

关于c++:http请求那点事

前言

这次我的项目应用了 angular + 第三方 c ++http 服务对接。没有了脱离了相熟的 springboot,刚加靠近原生。也遇到了很多问题。

回绝连贯

照着第三方库启动 c ++ 服务后,在本机测试能够申请到

然而应用其余电脑,把 localhost 改成服务器 ip 就无奈申请到

通过去看 github 我的项目上的 issue 看到,大家也遇到了如此问题,最初大家的解决办法是以管理员身份运行 vs 并且将代码从

web::http::experimental::listener::http_listener getStatusListener(L"http://127.0.0.1:8015/getStatus");

改成

web::uri_builder uri;
    uri.set_scheme(U("http"));
    uri.set_host(U("+"));
    uri.set_port(U("8015"));
    uri.set_path(U("/getStatus"));
    web::http::experimental::listener::http_listener getStatusListener(uri.to_uri());

具体起因也没有具体阐明(或者我没有看懂)。问了老师后,老师倡议配置一下 nginx 解决。
通过这次配置 nginx,了解了 nginx 实质上还是服务器,原来认为 nginx 只负责端口转发,springboot 起服务作用的是 tomcat。就如 thinphp 的 apache 一样。


通过 nginx 对申请的转发,对于 c ++ 服务来说 nginx 对他的申请就是 localhost 的地址。从而解决问题。
在后盾增加了一个 post 接口,用于启动捕捉数据。应用 API Tester 插件测试接口。

然而在启动前台单元测试进行对接的时候,申请同样的地址,产生了申请谬误。

更加奇怪的是,他间断对同一地址申请了两次,而我只操作了一次。第二次返回了 200,然而服务器端也没有响应打印信息。第一次申请的 CORS error 报错在写上一个 GET 申请接口的时候也遇到过,这是因为前后台不同源,违反了同源策略,解决办法是在相应头上退出 Access-Control-Allow-Origin:* 字段,容许跨域拜访。

// 响应
web::http::http_response response(web::http::status_codes::OK);
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.set_body(jsonResponseFinal);
request.reply(response);

然而再遇到雷同问题,这个解决办法没有胜利。
当初的问题是
1. 为什么同样的谬误解决办法只实用于 GET 申请而不实用与 POST 申请?
2. 并且为什么会申请了两次?
3. 为什么 API Tester 测试没有问题?
带着这些问题问了学长。
学长看了当前发现第二次返回 200 的申请其实是 OPTIONS 申请。

什么是 OPTIONS 申请呢。咱们能够把 OPTIONS 申请当做先遣队。OPTIONS 申请的主要用途有两个
一是获取服务器反对的 HTTP 申请办法;
二是用来查看服务器的性能。

那些可能会操作数据库的申请(除 GET 申请外),都会应用 OPTIONS 发动一个预检申请(preflight request),从而获知服务端是否容许该跨域申请。服务器确认容许之后,才发动理论的 HTTP 申请。
Preflighted Requests 是 CORS 中一种通明服务器验证机制。预检申请首先须要向另外一个域名的资源发送一个 HTTP OPTIONS 申请头,其目标就是为了判断理论发送的申请是否是平安的。
上面的状况须要进行预检:
非简略申请,比方应用 Content-Type 为 application/xml 或 text/xml 的 POST 申请;(什么是简略申请,什么是非简略申请,请移步阮一峰的跨域资源共享 CORS 详解)

上面借用 MDN 的图来更直观的看一下


所以解决也就是在 options 相应头退出容许申请。

web::http::experimental::listener::http_listener startCaptureListener(L"http://127.0.0.1:8015/startCapture");
startCaptureListener.support(web::http::methods::POST, [&](web::http::http_request request) {this->startCapture(request);
});
startCaptureListener.support(web::http::methods::OPTIONS, [&](web::http::http_request request) {this->allow(request);
});

void YzHttp::HttpService::allow(web::http::http_request request) {web::http::http_response response(web::http::status_codes::OK);
    response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
    response.headers().add(U("Access-Control-Allow-Methods"), U("POST"));
    response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"));
    request.reply(response);
}

问题解决。
最初一个问题,为什么用 API Tester 测试能通过呢。可能无奈模仿真正的浏览器拜访吧。

总结

通过构建 c ++http 服务,应用更加原生的代码。更能晓得本人有哪些 http 常识不分明。而 springboot 框架为咱们做好了所有,也让咱们没机会接触这些常识。
感激黄庭祥学长在我解决问题过程中给予的帮忙。

参考连贯

Server does not work from public IP, but localhost or other SDKs are fine
为什么会有 OPTIONS 申请
跨源资源共享(CORS)

退出移动版