How to downgrade socket.io websocket to WS from WSS? - javascript

I am making a website that accesses the devices sensors and sends them via socket.io to my local machine.
I can't access the device sensors without HTTPS, so I have to use HTTPS for the website, which is why I uploaded my site to Heroku. The problem is the localhost server I open on my computer is HTTP, and my HTTPS website can't send data from HTTPS (heroku site) to HTTP (local machine: localhost). Is there any way I can share the data between them?
This is the code used to connect to localhost written on the heroku client side site:
const socket = io("https://192.168.1.15:16", { transports: ['websocket', 'polling', 'flashsocket']});
While this is what I use in my local machine:
const httpServer = require("http").createServer(app);
const io = require("socket.io")(httpsServer,{
});
as per socket.io documentation
I get this error:
Mixed Content: The page at '**The website**' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://192.168.1.35:16/socket.io/?EIO=4&transport=websocket'. This request has been blocked; this endpoint must be available over WSS.

Like #R3FL3CT says, it's most likely a CORS issue - check your console to be sure.
It seems that the initial request that it makes is the one getting blocked. For example,
const socket = io('wss://echo.websocket.org/');
socket.on("connection", (socket) => {
console.log(`Connected!`)
});
Would get blocked with the error
Access to XMLHttpRequest at 'https://echo.websocket.org/socket.io/?EIO=4&transport=polling&t=Nb17pKo' from origin 'http://127.0.0.1:5501' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Whereas just using a pure WebSocket
const websocket = new WebSocket('wss://echo.websocket.org/');
websocket.onopen = e => {
console.log(`Connected!`);
}
Connected okay.
So your solution is to either roll back to an earlier version of socket.io that doesn't force cors (before v3), or just use your own WebSocket - example: https://www.websocket.org/echo.html

Here's one way you could do something to try and communicate. If you host your own version of CORS Anywhere, you can communicate with http:// websites. I have a working link you can use, if you don't want to have to host one, but here the Github is. The way it works, is that you append the URL to the end of your URL for CORS Anywhere.
e.g https://cors.anywhere.com/google.com

Related

Problem in communicating with Binance exchange in NodeJS web socket

When I execute the following piece of code in the app.js file
const WebSocket = require('ws');
const ws = new WebSocket('wss://stream.binance.com:9443/ws/!miniTicker#arr');
ws.on('message', function (data){
//const result = JSON.parse(data);
console.log(data);
});
I get the following error and I cannot receive data.
10.10.34.34 (what your DNS server resolved stream.binance.com to) is a local IP address! You are not even reaching Binance. It's probably a captive portal or some firewall.
Open that IP address in the browser and check whether you get some sort of web interface that gives you a clue about what is blocking your request. You can also try changing your DNS server to Google (8.8.8.8) or some other public DNS server instead of relying on your router.
Update:
In your comment you mentioned your DNS server is 178.22.122.100 (i.e., shecan.ir). If I try to resolve the domain with that server, I also get nonsensical results (10.10.34.34 and d0::11). According to this book, this is part of Iranian censorship, and your ISP would handle this IP address to show a page about this domain being blocked if you'd open it in a browser.
So, an alternative public DNS server without censorship such as 8.8.8.8, 1.1.1.1 or 9.9.9.9 should help. If this doesn't work then those DNS servers are also blocked by your ISP and you would need to use a VPN or other means of bypassing government censorship.

How to solve CORS error while fetching an external API?

I'm developing a web app in Angular 10 that works as follows:
I'm dealing with CORS issue. I do not have permission to add code to the server I'm fetching.
I want to be able to:
Fetch the website
Parse the result, and put it in my database
I'm aiming to deploy the solution on an Apache server.
Here is the CORS error I'm dealing with:
Blocking a Cross-Origin Request: The "Same Origin" policy does not
allow viewing the remote resource located at
https://wwwfrance1.CENSORED.eu.com/api/?apikey=CENSORED.
Reason: "Access-Control-Allow-Origin" CORS header is missing. Status
code: 200.
Here is what i've tried:
Using MOSIF mozilla extension (works, but not sustainable for deployment, and for some reason, when I'm ignoring the CORS security, I cannot post on my DB any more)
Adding a header in my fetching request, such as:
/******API SEACH****/
/***Global Update***/
private updateClients() {
let xmlRequestPromise = fetch('https://wwwfrance1.CENSORED.eu.com/api/?apikey=CENSORED&service=list_clients', {
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
}
})
.then(async response => this.clients = this.regexSearchClient(await response.text()))
return xmlRequestPromise
}
But that doesn't work either. I've verified that the header appears in the request.
How to proceed?
What is CORS ?
Cross-origin resource sharing is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. From wiki
In simple terms only an internal webserver can send Requests which are potentially dangerous to it's web server, and requests from other server's are simply blocked.
But few HTTP requests are allowed ,Few of the allowed methods are GET, HEAD, POST.
How do I resolve the issue ?
Apparently in this circumstance you cannot send a fetch request to a web server having CORS header. Instead you can do a GET request to the web server as a web server having CORS allows HTTP GET requests.
Note - If you send a GET request to a web server using angular in your browser it wouldn't work as browser's convert GET requests into fetch requests and fetch requests aren't allowed from a web server with CORS. Instead send a GET request from a webserver/local machine rather than a browser.
Create your own server and make a route which fetches that API. From your Angular application fetch that route on your server.
You have to use a package as a middleware. If you are using nodejs-framework expressjs.At first, you have to run npm install cors -force.Then add the code that is given bellow:-
const cors=require('cors')
app.use(cors({origin:true}))

API request blocked by CORS

I'm trying to use the g-trends API in my vuejs application running from localhost, but keep running into issues of my requests getting blocked due to CORS restrictions: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I know how to fix the issue when performing a fetch request, but not in a scenario where I don't actually see the request URL like when using an API. Is there a way to fix this?
const { ExploreTrendRequest } = require('g-trends');
const explorer = new ExploreTrendRequest();
explorer.past5Years()
.addKeyword("keyword")
.download().then(csv => {
console.log(csv)
})
I usually use a proxy server for avoiding this situation, your app asks your server to do that request for you so the communication with the API is managed by your server, when your server receives the answer it forwards it to your app and there won´t be any CORS problem.

Socket.io and express app not connecting due to CORS error: “The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*'”

I'm slowly losing my mind over a very stupid issue I'm having.
I have a socket.io/express app uploaded to Digital Ocean as a Docker setup.
To allow https, I am using caddy as part of my Docker setup to allow for automatic https.
I've been trying to connect to this setup via my domain and from my local React app that lives on localhost:3000. But I am constantly getting the following error:
Access to XMLHttpRequest at 'https://mediaserver.domain.dev/socket.io/?EIO=3&transport=polling&t=N5BXNK2' from origin 'http://localhost:3000' has been blocked by CORS policy: 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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I know there have been a lot of SO questions about this before and believe me when I say I tried almost all of them.
I tried changing the options of the cors middleware
I tried adding my own middleware and setting headers specifically
I tried using localhost:3000 as origin
...
But nothing seems to work. I have currently no idea what I can still do to fix this.
So any help would be welcome.
My docker-compose file looks as follows:
version: '3.6'
services:
media-server:
build:
dockerfile: Dockerfile
context: ./
ports:
- "8080:5000"
expose:
- "5000"
caddy:
image: abiosoft/caddy:0.11.0
depends_on:
- "media-server"
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /root/Caddyfile:/etc/Caddyfile
- /root/.caddy:/root/.caddy
My Caddyfile is as follows:
https://mediaserver.domain.dev {
proxy / http://media-server:8080 {
websocket
transparent
}
cors
}
And my server setup looks as follows:
import cors from 'cors';
import express from 'express';
import socket from 'socket.io';
import { intialiseWebSocketConnection } from './socketio';
const app = express();
app.use(cors());
const server = app.listen(5000, function () {
console.log('Server is connectedd on *:5000');
});
const io = socket.listen(server);
intialiseWebSocketConnection(io);
You are attempting to make a cross-origin request with the credentials flag set and the Access-Control-Allow-Origin set to any (*). This is not allowed for security reasons. There are two ways to solve the problem. If you don't need to send credentials make sure the credentials flag is false. That is, if you are using an XMLHttpRequest make sure withCredentials is not true (it is false by default). If you are using the Fetch API make sure Request.credentials is set to "omit".
If you do need to send credentials for some reason, you have to set the Access-Control-Allow-Origin in your server's response to the origin from where you are sending requests to the server and not to any (*).
To figure out what your origin is just check to what the Origin header is set to in the requests you send to the server.
By default cors() sets the Access-Control-Allow-Origin to *. Try changing it to:
cors({
origin: "http://localhost:3000",
credentials: true
});
Also note Chrome does not support localhost as an origin. To get around that you can start Chrome with the --disable-web-security flag during development.
There's a simple way to bypass CORS errors for socket.io connections. By default socket.io starts each connection with several regular http calls. If things go well, it converts to a webSocket transport (and runs socket.io over the webSocket transport). Those initial http calls are subject to CORs restrictions.
But, if you tell socket.io to just start out with the webSocket transport right away, then you are not subject to CORs restrictions. You can do that in the client by doing this:
const socket = io({transports: ['websocket']});
Even though a webSocket connection always starts with one http request, that particular http request (with the appropriate upgrade header set is not subject to CORs restrictions.
The only downside to this (that I'm aware of) is that your code would not run in a browser that does not support webSockets. That would be a really, really old browser. Even IE10 (released in 2012) supports webSockets and all modern browsers have supported them since at least 2013. I'm actually not quite sure why socket.io still has their http polling as the default as it's far less efficient on the network to start out every connection. Anyway, you can easily bypass it with io({transports: ['websocket']});.

Error occurs when retriving data from Firebase

Hi I stored my mp3 files inside Storage in Firebase. Set permissions under Rules tab to be:
allow read, write, request;
In order to take the files from there I use react-axios.
When I load my page, I get an error that the request has been blocked by CORD policy:
Access to XMLHttpRequest at
'gs://******.appspot.com/****/****' from origin 'http://localhost:3000'
has been blocked by CORS policy: Cross origin requests are only
supported for protocol schemes: http, data, chrome, chrome-extension,
https.
I installed gsutil and then I ran the command:
gsutil cors set cors.json gs://****.appspot.com
I did not get any errors for running this command.
This is the cors.json file:
[
{
"origin": ["http://localhost:3000","gs://******.appspot.com"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
However, when I load my website, I still get the same error...
As the error message states cross origin requests are only allowed for certain protocols. This is a security measure implemented in most browsers. If you are interested why this policiy is what it is, theres a good article on codecademy about that.
My suggested solution for that problem would be to setup a backend api server on that host as well, let it query the needed information from the db, add the necessary CORS headers, and send it to the browser running your frontend.
You could do that using node.js utilizing express.js.
Please see below example.
const cors = require('cors');
const express = require('express');
const app = express();
function getmusicfunction(req, res) {
console.log('GET /getmusic');
# query the db for your file here and store it into your body bariable
res.send(body);
}
const corsOptions = {
origin: '*',
optionsSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.get('/getmusic', (req, res) => getmusicfunction(req, res));
const port = 6667;
app.listen(port, () => console.log('API listening on port ' + port + '!'));
EDIT: I confused Firebase with Firebird. Sorry. I withdraw that answer.
The key parts of the error message are:
Cross origin requests are only supported for protocol schemes
And
Access to XMLHttpRequest at
'gs://******.appspot.com/****/****' from origin 'http://localhost:3000'
You're trying to access a URL starting with gs:// from JavaScript that runs on http://. Those are two different protocols, and the error message says that this is not allowed.
To download a file from Cloud Storage you typically use:
either a download URL you generate for the file, which is a publicly readable (but unguessable) URL. The download URL starts with https:// so is eligible for cross-original requests from your page. See the Firebase documentation on downloading a file via a URL.
or you use the Firebase SDK for accessing the data. The Firebase SDK uses its own protocol, which is not affected by the cross-origin requirements. You could use the gs: URL you now use with that SDK. It looks like this approach is not available in the JavaScript SDK.

Categories

Resources