Error occurs when retriving data from Firebase - javascript

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.

Related

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

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

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

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']});.

POSTing to external API throws CORS but it works from Postman

I am using the imgur api to upload images via a node js app.
I am converting images to base64 strings and sending them via Postman works great.
I use node-fetch to make api calls.
const fetch = require('node-fetch')
...
async uploadImage(base64image) {
try {
const url = 'https://api.imgur.com/3/image'
const res = await fetch(url,
{
method: 'POST',
body: { image: base64image },
headers: {
'content-type': 'application/json',
'Authorization': 'Client-ID [my-client-id]',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, Access-Control-Allow-Headers',
'Access-Control-Allow-Methods': 'POST',
}
}
)
console.log(res)
} catch(err) {
console.log(err)
}
}
Error:
Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response.
I have tried many 'Access-Control-Allow-xxx' headers but none of them worked..
I assume it must be something simple that I am missing. I have been stuck on this for hours please help me.
Browser restricts HTTP requests to be at the same domain as your web page, so you won't be able to hit imgur api directly from the browser without running into CORS issue.
I am converting images to base64 strings and sending them via Postman
works great.
That's because Postman is not a browser, so is not limited by CORS policy.
I have tried many 'Access-Control-Allow-xxx' headers but none of them
worked..
These headers must be returned by the server in response - in your case by the imgur server. You can't set them in the request from browser, so it'll never work.
Error: Access to fetch at 'https://api.imgur.com/3/image' from origin
'http://localhost:3000' has been blocked by CORS policy: Request
header field Access-Control-Allow-Headers is not allowed by
Access-Control-Allow-Headers in preflight response.
Possible solutions to your problem:
If you have access to the backend api you can set the "Access-Control-Allow-Origin" header on the server and let your app access the api - but as you won't have access to the imgur server - you probably can't do that.
Disable CORS in the browser - you can use a plugin like: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en. This workaound should be fine for development. The plugin will disable your CORS settings and you will be able to hit imgur apis.
The third solution is using a proxy. You can setup a small node server using express. You will then hit your own node server, which in turn will hit the imgur api. As node server is not a browser environment, it won't have any CORS issue and you will be able to access imgur API that way. This is also the reason you were able to hit the API from Postman without any issues. As Postman is not a browser environment, it's not limited by CORS policy.
That's because Access-Control-Allow-Headers, Access-Control-Allow-Methods are the headers that is used by the server. The server appends the header by a middleware.
Now, imagine in the server(in this below example an express server) with CORS enabled this kind of (default) headers are getting set:
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept');
});
And you are sending Access-Control-Allow-Headers from the client side, and server sees that as a header that is not whitelisted.
So, in headers just use these:
headers: {
'content-type': 'application/json',
'Authorization': 'Client-ID [my-client-id]'
}
It should work fine.
Btw, I think it is working with postman because:
Postman cannot set certain headers if you don't install that tiny postman capture extension.
Browser security stops the cross origin requests. If you disable the chrome security it will do any CORS request just fine.
Also, according to this:
I believe this might likely be that Chrome does not support
localhost to go through the Access-Control-Allow-Origin -- see
Chrome issue
To have Chrome send Access-Control-Allow-Origin in the header, just
alias your localhost in your /etc/hosts file to some other domain,
like:
127.0.0.1 localhost yourdomain.com
Then if you'd access your script using yourdomain.com instead of
localhost, the call should succeed.
Note: I don't think the content type should be application/json it should be like image/jpeg or something. Or maybe don't include that header if it doesn't work.
I have some few observations in my own app that helped me solve this issue. I have a node app as a backend api service and a VueJS built front end. I set my node app with cors with a list of endpoints that are allowed to access my node app. Working on my local machine doesn't give me any errors until I upload it to my server.
here are my environments
Local Environment
Nodejs: 12.16.1
OS: Windows 10
DB: MySQL
NodeJS Server Framework: ExpressJS
Upload Module: Multer
Production Environment
Nodejs: 12.19.0
OS: Ubuntu 20.0.4
DB: MySQL
NodeJS Server Framework: ExpressJS
Upload Module: Multer
nginx
Here are my observations based on my production built app.
When I upload a form with image [500kb and above] [post or put], the cors error shows up but less than that, it all went fine.
If I use form data to send data to the server, I see 2 requests in my network tab, the OPTIONS and the actual request.
The actual request failed but I saw that my content-length is very high which leads me to the conclusion that my request is rejected due to the large amount of data that the client sent which my server may have limited. I know that may be misleading but the solution I did works so I don't know why cors issue is popping up even though the data limit is the issue.
MY SOLUTION:
In my nginx config file, I increased my client_max_body_size to 100M. I believe that nginx has a default of 1MB
Open /etc/nginx/sites-available/your-server-file where your-server-file can be like www.example.com or default.
Add the following line inside the server block. You can set it to any amount you want other than 100M.
server {
client_max_body_size 100M;
...
}
type in sudo systemctl restart nginx to restart nginx.
type in sudo nginx -t to check if change is successful.
Reload your app if you are using pm2 and you are done.
According to this article I used this command in linux and SOME OF(!) cross-origins fixed.
google-chrome --disable-web-security --user-data-dir="/tmp/YOUR_TEMPORARY_PATH"
This will not work if you pass headers from frontend. CORS policy is enabled by browsers. Browser blocks the response when they don't found the headers in response.
Possible Solutions:
You can pass the headers in response (If you have the access of backend or ask the API provider for this)
You can setup a middleware to resolve this.
You can get information from here

Axios hitting No 'Access-Control-Allow-Origin' header is present on the requested resource error

https://samples.openweathermap.org/data/2.5/forecast?appid=be2e163d03a0b97a96a89b0230be8e4a&q=klang,my
When I directly paste the URL into the browser, I can make the API request successfully. However, when I try it with Axios I'm hitting below exception
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Based on some research,
I can't understand the logic behind as I'm following the exact same steps provided by online course, by simply firing this API call using Axios should be able to return the result.
import axios from 'axios';
const API_KEY = 'be2e163d03a0b97a96a89b0230be8e4a';
const ROOT_URL = `https://samples.openweathermap.org/data/2.5/forecast?appid=${API_KEY}`
export const FETCH_WEATHER = 'FETCH_WEATHER';
export function fetchWeather(city) {
const url = `${ROOT_URL}&q=${city},my`;
const request = axios.get(url);
return {
type: FETCH_WEATHER,
payload: request
}
}
This exception means the server your hitting does not support CORS (Cross-Origin Resource Sharing).
In the case of openweathermap.org I think you should be using api.openweathermap.org instead of samples.openweathermap.org
Here are the few things i observed:
You are using the sample api(“samples.openweathermap.org”) not the production one(“api.openweathermap.org”) so i think for integration with application you should use production API.On this they give the CORS support.
If you still want to check with sample api endpoint then
The easy way is to just add the extension in google chrome to allow access using CORS.
(https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en-US)
Just enable this extension whenever you want allow access to no 'access-control-allow-origin'header request.
Or
In Windows, paste this command in run window
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Reference: https://openweathermap.desk.com/customer/portal/questions/16823835-cors
You need to add cors in your server app
var cors = require('cors');
app.use(cors());
Hope this help
When you directly access the url in browser there is no cross domain request is issued.
But when you access the resource using axios there might be a chance that you are accessing resource on different domain then the domain present on your browser tab.That is the reason you are getting Access-Control-Allow-Origin not present. For handling this add a logic on server side to add this header in OPTION Response.

Categories

Resources