此次項目使用了angular + 第三方c++http服務對接。沒有了脫離了熟悉的springboot,剛加接近原生。也遇到了不少問題。php
照着第三方庫啓動c++服務後,在本機測試能夠請求到
html
可是使用其餘電腦,把localhost改爲服務器ip就沒法請求到
經過去看github項目上的issue看到,你們也遇到了如此問題,最後你們的解決辦法是以管理員身份運行vs而且將代碼從nginx
web::http::experimental::listener::http_listener getStatusListener(L"http://127.0.0.1:8015/getStatus");
改爲c++
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同樣。git
經過nginx對請求的轉發,對於c++服務來講nginx對他的請求就是localhost的地址。從而解決問題。
在後臺添加了一個post接口,用於啓動捕獲數據。使用API Tester插件測試接口。
可是在啓動前臺單元測試進行對接的時候,請求一樣的地址,發生了請求錯誤。
更加奇怪的是,他連續對同一地址請求了兩次,而我只操做了一次。第二次返回了200,可是服務器端也沒有響應打印信息。第一次請求的CORS error報錯在寫上一個GET請求接口的時候也遇到過,這是由於先後臺不一樣源,違反了同源策略,解決辦法是在相應頭上加入Access-Control-Allow-Origin:*
字段,容許跨域訪問。github
// 響應 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請求方法;
二是用來檢查服務器的性能。web
那些可能會操做數據庫的請求(除GET請求外),都會使用 OPTIONS 發起一個預檢請求(preflight request),從而獲知服務端是否容許該跨域請求。服務器確認容許以後,才發起實際的 HTTP 請求。
Preflighted Requests是CORS中一種透明服務器驗證機制。預檢請求首先須要向另一個域名的資源發送一個 HTTP OPTIONS 請求頭,其目的就是爲了判斷實際發送的請求是不是安全的。
下面的狀況須要進行預檢:
非簡單請求,好比使用Content-Type 爲 application/xml 或 text/xml 的 POST 請求;(什麼是簡單請求,什麼是非簡單請求,請移步阮一峯的 跨域資源共享 CORS 詳解)
下面借用MDN的圖來更直觀的看一下spring
因此解決也就是在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測試能經過呢。可能沒法模擬真正的瀏覽器訪問吧。apache
經過構建c++http服務,使用更加原生的代碼。更能知道本身有哪些http知識不清楚。而springboot框架爲咱們作好了一切,也讓咱們沒機會接觸這些知識。
感謝黃庭祥學長在我解決問題過程當中給予的幫助。
Server does not work from public IP, but localhost or other SDKs are fine
爲何會有OPTIONS請求
跨源資源共享(CORS)