cpprestsdk icon indicating copy to clipboard operation
cpprestsdk copied to clipboard

CORS error

Open Dhruv-m-Shah opened this issue 4 years ago • 4 comments

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.

Dhruv-m-Shah avatar Sep 14 '20 03:09 Dhruv-m-Shah

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?

barcharcraz avatar Oct 21 '20 21:10 barcharcraz

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.

rkubes avatar Dec 21 '20 20:12 rkubes

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);

Kevin4ch avatar Jun 02 '21 02:06 Kevin4ch

Yes. After I understand how CORS works, I add the OPTIONS method and it works!

LuchenCatherine avatar Sep 23 '22 15:09 LuchenCatherine