How do I get both https://example.com and https://www.example.com for endpoints to connect?
socket.io connect no problem at htttps://example.com
but not https://www.example.com
my server looks like
const server = http.createServer(app);
const io = socketIo(server, {
cors: {
origin: "https://www.example.com:3000",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}});
and my client endpoint looks like this
const ENDPOINT = 'https://example.com/';
Configure your DNS to point both example.com and www.example.com to the same host IP address and then support both domains with your cors configuration. Then, either URL will go to the same host.
You can avoid cors entirely if you configure socket.io to start immediately with a webSocket, not with the http polling that it usually starts with. You can do that in the client by adding the transports: ['websocket'] option to the client connect.
And, your custom header was probably blocking CORs and requiring pre-flight permission. CORs has two levels, simple and not-simple. When you add a custom header, you force CORs into the not-simple route where it requires preflight which is probably more than the built-in socketio cors features will handle.
Related
I'm a bit new to react and I am trying to fetch Crypto data from the Nomics API. I read their documentations and used axios for my GET request like so:
fetchChartData(currency, start) {
const data = {
key: "key",
currency: currency,
start: start
}
return axios({
method: "get",
url: API_URL + '/exchange-rates/history',
headers: {
"Access-Control-Allow-Origin": "*",
crossorigin: true
},
data
})
}
For which I get:
Access to XMLHttpRequest at 'https://api.nomics.com/v1/currencies/ticker' from origin
'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
So I decided to use Moesif Origin and CORS changer
Access to XMLHttpRequest at 'https://api.nomics.com/v1/exchange-rates/history' from origin 'http://localhost:3000'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
It does not have HTTP ok status.
I don't know why it is being blocked because it says "localhost requests are always allowed to ease development" in the documentation.
[![Nomics docs on CORS][1]][1]
My other attempts of fixing this are adding stuff to the headers and proxy.
My proxy went like this, (never proxy-ed before):
const API_URL = `https://cors-anywhere.herokuapp.com/https://api.nomics.com/v1`
fetchChartData(currency, start) {
const key = "key";
return axios({
method: "get",
url: API_URL +
'/exchange-rates/history?' +
`?key=${key}
¤cy=${currency}
&start=${start}`
})
}
With proxy, however, I just get a 401 (Unauthorized).
[1]: https://i.stack.imgur.com/zIT7L.png
The Problem
The problem is that the domain you're using does not match the domain that the API is expecting for development. A domain is identified for CORS purposes (also known as the Same Origin Policy) based on three parts: protocol, host, and port. Using the following domain: https://example.com, I'll explain these three parts below:
Protocol - http or https depending on if security is enabled on the domain. For our example it would be https.
Host - for the example above this would be example.com.
Port - The default ports are typically: 80 for http and 443 for https. In our example, our port is 443.
It's important to know the information above so that you can identify the problem in your code snippet. The documentation notes that localhost is always supported for development. However, your domain http://localhost:3000 does not match the documentation because the ports are different.
The Fix
You'll need to run your application locally at http://localhost (default port 80) for the API call to succeed and pass the CORS preflight test. I don't see it noted above, but if the documentation requires a secure localhost environment then you'd want to run your application locally at https://localhost (default port 443). In addition, you'd probably have to create a self-signed SSL certificate for this to work properly.
React or axios do not seem to understand what local host is set to.
I'm serving a react client app on port 3000, and a react api server on port 3030.
I can call curl -s localhost:3030 from command line and get a good reply. But when I call using axios or fetch within my client app, I get net::ERR_CONNECTION_REFUSED.
For example, this works:
axios.post("http://xxx.xx.xxx.xxx:3030/authentication", {
This does not work (net::ERR_CONNECTION_REFUSED):
axios.post("http://localhost:3030/authentication", {
(Where localhost is the same machine with the xxx number above)
I don't think it's a CORS issue as I've tried setting the following headers in the server and sending them in post request.
"Access-Control-Allow-Origin"
"Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"
Also, my browser seems to report CORs errors explicitly (at least, it has previously)
If you are serving your client (React app) from a different port, and in 3030 it's only your backend, then it's probably CORS. You should configure your backend server to accept petitions from your app's domain.
I've been trying for hours to allow an angularjs client (localhost:5000) to access the resources of a python server using flask (localhost:5001), but I keep receiving the same error message "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5001/api. (Reason: expected 'true' in CORS header 'Access-Control-Allow-Credentials').
So far I've tried to:
Allow CORS via flask_cors using
from flask_cors allow CORS
api = Blueprint('api', __name__)
CORS(api, resources={"/api/*: {"origins": "*"}})
Use angular http-proxy-middleware, both with
server.middleware = proxy('/api', {target: 'http://localhost:5001', changeOrigin:true});
and
server.middleware = proxy('/api', {target: 'http://localhost:5001', changeOrigin:true, onProxyRes: function(proxyRes, req, res){proxyRes.headers['Access-Control-Allow-Origin']='*';}});
The Access-Control-Allow-Origin field in the response header is "http://localhost:5000" and not "http://localhost:5001", which is (if I understand it right), what I need. Any ideas?
I had the same problem and fixed it using the CORS decorator #cross_origin() using the parameter supports_credentials=True (note that you can't use origin='*' and support_credentials=True at the same time)
More infos can be found here
I am trying to make Flask-Socketio connection from AngularJS at client side to a Flask server.
Connecting with the Flask server works fine, but when I try to connect to socketio in my Angular controller:
var socket = io.connect('http://localhost:5000');
I see the following error on my browser console:
Failed to load
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=1526477253000-2:
The value of the 'Access-Control-Allow-Origin' header in the response
must not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://localhost:3000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
My client side (AngularJS) is running on port 3000 (gulp) and Flask server is running on port 5000.
I have tried including flask_cors with:
cors = CORS(app, resources={r"/*": {"origins": "*"}})
But still get the same issue.
Any help is appreciated.
Cheers.
cors = CORS(app, resources={r"/": {"origins": ""}})
instead of star mention you are host with port
I am having a bit of trouble setting up my create-react-app application to proxy requests to my test hosting on Microsoft azure. I have set up the proxy in my app's package.json as follows:
"proxy":{
"/api/*":{
"target":"https://mytestbackend.azurewebsites.net",
"secure":false
}
}
I have set up an axios request to be sent to the backend server on azure. It is in a stand-alone .js which I call from one of my react application's events. It looks like this:
import axios from 'axios';
const login = async (username, password) => {
console.log("Username to send is:"+username);
console.log("password to send is:"+password);
let response = await axios.post('/api/user/login', {username:username,password:password});
console.log(response);
};
export {login};
The problem can't be in my react components, because those two console.log() call show that the values entered are being recieved. If I remove the "secure":false setting from package.json, request fails with Http Error: 500. But if I use the secure setting, it fails with a 404 page. Can someone please shed a little light on what am I doing wrong? Can I only use the proxy on "localhost"? The documentation suggests otherwise. Any help is greatly appreciated.
I have verified that CORS is enabled for the domain on which the dev server is running on the Azure Management Portal. And if I do the request by using the backend's URL directly (that is, not using the create-react-app proxy), it works. The problem must be something in the way the proxy is configured.
The response text for the HTTP Errpr 500 which happens when not using secure is :
Proxy error: Could not proxy request /api/user/login from localhost:3000 to https://mytestbackend.azurewebsites.net (undefined).
Additional info: I have also tested by running my Backend locally on my development machine. The error message occurs but the "undefined" in the parenthesis says "UNABLE_TO_VERIFY_LEAF_SIGNATURE". If using "secure: false, I can call the login endpoint successfully, but calls to other endpoints which require authentication fail because the cookie is not sent by axios.
Doing:
curl -v https://mytestbackend.azurewebsites.net/api/user/login
Has this output:
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection #0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
create-react-app use WebPackDevServer which uses https://github.com/chimurai/http-proxy-middleware#options
So you can use all the options from the same
Now one key header that is import in such cases of externally hosted server is host. This at times can issues if not correct, see below example
Websocket works on EC2 url but not on ElasticBeanstalk URL
Next is the cookies might be associated with localhost, i checked and they should go without any modification. But you might want to use the cookieDomainRewrite: "" option as well
So the final config I would use is below
"proxy":{
"/api/*":{
"target":"https://mytestbackend.azurewebsites.net",
"secure":false,
"headers": {
"host": "mytestbackend.azurewebsites.net"
},
"cookieDomainRewrite": ""
}
}
Also on your client you want to use the withCredentials:true
let userinfo =await axios.get('/api/secured/userinfo',{withCredentials:true});
Create react app http-proxy-middleware, and should support the full set of options.
Some things I would try:
The path to match may be /api/** instead of /api/* if you want to nest multiple levels deep (eg. for /api/user/login)
You may need to add changeOrigin: true if you're proxying to something remotely (not on localhost)
You will likely want to keep secure: false as you aren't running localhost with https.
So in total, I would try
"proxy":{
"/api/**": {
"target": "https://mytestbackend.azurewebsites.net",
"secure": false,
"changeOrigin": true
}
}
After days of trying unsuccessfully to do this, I finally found a setup that works. Proxy is configured like this:
"proxy": {
"/api/user/login": {
"target": "https://localhost:44396",
"logLevel": "debug",
"secure": false
},
"/api/secured/userinfo": {
"target": "https://localhost:44396",
"secure": false,
"logLevel":"debug",
"secure":false
}
Request to both endpoints on the client have withCredientials:true
try {
await axios({
method:'post',
url:'/api/user/login',
withCredentials:true,
data:
{username:username,password:password}}
);
let userinfo =await axios.get('/api/secured/userinfo',{withCredentials:true});
return userinfo;
As you can see, I've moved to testing on my local dev machine. For whatever reason, this setup refuses to work on the azure-hosted backend. I would have preferred that it work as I originally intended, but at least now I can continue with my project.