cpprestsdk
cpprestsdk copied to clipboard
CORS error
I followed suggestions in this closed issue: https://github.com/microsoft/cpprestsdk/issues/98, but am still getting a "CORS error". Here is the exact error message shown on the browser: "Access to XMLHttpRequest at 'http://127.0.0.1:9999/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Here is the code:
#include <cpprest/http_listener.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <thread>
#include <chrono>
#include <ctime>
// cpprest provides macros for all streams but std::clog in basic_types.h
#ifdef _UTF16_STRINGS
// On Windows, all strings are wide
#define uclog std::wclog
#else
// On POSIX platforms, all strings are narrow
#define uclog std::clog
#endif // endif _UTF16_STRINGS
using namespace std;
using namespace web::http::experimental::listener;
using namespace web::http;
using namespace web;
void respond(const http_request& request, const status_code& status) {
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"));
request.reply(response);
}
int main()
{
// Synchronously bind the listener to all nics.
uclog << U("Starting listener.") << endl;
http_listener listener(U("http://127.0.0.1:9999"));
listener.open().wait();
// Handle incoming requests.
uclog << U("Setting up JSON listener.") << endl;
listener.support(methods::GET, [](http_request req) {
req.headers().add(U("Access-Control-Allow-Origin"), U("*"));
req.headers().add(U("Allow"), U("GET, POST, OPTIONS"));
req.headers().add(U("Access-Control-Allow-Origin"), U("*"));
req.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, OPTIONS"));
auto http_get_vars = uri::split_query(req.request_uri().query());
auto found_name = http_get_vars.find(U("request"));
if (found_name == end(http_get_vars)) {
auto err = U("Request received with get var \"request\" omitted from query.");
uclog << err << endl;
respond(req, status_codes::BadRequest);
return;
}
auto request_name = found_name->second;
uclog << U("Received request: ") << request_name << endl;
respond(req, status_codes::OK);
});
uclog << U("Waiting for incoming connection...") << endl;
while (true) {
this_thread::sleep_for(chrono::milliseconds(2000));
}
uclog << U("Terminating JSON listener.") << endl;
listener.close();
return 0;
}
I am sending a HTTP request using xmlHttpRequest on a web application running on localhost:3000.
I think this is a browser configuration issue rather than a cpprestsdk issue. I know browsers have been getting more strict about cors requests to localhost due to badly configured local servers having security holes.
is it possible you need to respond to an OPTIONS request from the browser?
I just recently worked through this on my end as well. If you're getting the "preflight" error, it's most likely that you're not responding to the OPTIONS method as @barcharcraz pointed out.
I specifically saw this while using Swagger and sending a "DELETE" command. GET, POST, and PUT were all working with my CORS header, but DELETE was always failing with that preflight failure message. It turned out that before it tries to send DELETE, it will check with the resource what methods are allowed. If it doesn't get the right response then it won't even try to send the DELETE to the server.
I basically just stubbed in a dummy handler for OPTIONS that just replies with the required CORS headers, and a status code of 204 (no content). The response code is important, if it sends an error one then the preflight check will also fail. I think 200 may also be ok, but I didn't try that one.
1.first handle options m_listener->support(methods::OPTIONS,std::bind(&MSHttpServer::handle_options, this, std::placeholders::_1));
2.then set response header for OPTIONS method http_response sp(status_codes::OK); sp.headers().add("Access-Control-Allow-Origin","×"); sp.headers().add("Access-Control-Allow-Methods","×"); sp.headers().add("Access-Control-Allow-Headers","×"); resp.reply(sp);
Yes. After I understand how CORS works, I add the OPTIONS method and it works!