Why nodejs is behaving very strange with my code? - javascript

I don't know why but I got confused regarding Nodejs one behaviour.
Following is my nodejs code my server is running at port:8080
const express = require("express");
const app = express();
const multer = require("multer");
const cors = require('cors');
app.use(cors({
origin:"http://localhost:4000"
}))
app.get("/userinfo", async (req, res) => {
console.log("reached heree");
res.json({
message: "access",
});
});
app.listen(
8080,
(error) => {
if (error) {
console.log("error");
}
},
() => {
console.log("listening at port 8080");
}
);
And I am trying to hit API from a different origin [localhost:3000]
import logo from './logo.svg';
import './App.css';
import axios from "axios";
function App() {
const makeRequest =()=>{
axios.get("http://localhost:8080/userinfo").then(response=>{
console.log(response);
}).catch((e)=>{
console.log(e);
})
}
return (
<div className="App">
<button onClick={makeRequest}>Click</button>
</div>
);
}
export default App;
But when I click Click when I inspect the code, I got an error message as expected You are blocked by CORS policy.But when I see in terminal on my server-side, I see output Reached here.
At this point, I got too confused and frustrated at the same time. How cross-site request triggered /userinfo from the different origin?. I don't think this should happen.
How can I solve this issue??

It's not your server that is blocking the request. Your server SHOULD send back the HTTP request because servers and WIFI and your router does not care about CORS.
It is the web browser that blocks the CORS. Blocking CORS does not mean you don't hit the server endpoint. It does not even mean that the HTTP packet is blocked. Blocking CORS means your web browser is refusing to let your javascript code from reading the data returned by the server.
The purpose of CORS is to bypass the original Same-origin policy which is still enforced today. The same-origin policy was added when javascript was added to web browsers. It allows web browsers to make HTTP requests but tries to prevent malicious scripts from listening in to HTTP data by disallowing scripts to read the result of HTTP requests (XMLHttpRequest or fetch) unless the URL is from the same domain as the page.
The only thing CORS adds is a header that your server can send back to the browser that tells the browser that it's OK for javascript code to access the result of the HTTP request.

Related

Firebase realtime database blocked by CORS policy: react js app issue. Axios

I'm executing a simple delete command to remove one of my toDos in my toDoList react app and I get the response the response that XMLHTTPRequest to my url is blocked by CORS policy and AxiosError returns me a network error
Access to XMLHttpRequest at 'url' 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 have checked yt axios tutorials and they don't have this issue. Some solutions I found online is to make a backend with Access-Control-Allow- Origin response header on my domain which I don't really understand because I am still learning backend.
Any tips on fixing the problem without having to set up a backend or a link to a tutorial on setting pu a backend with my react app would be appreciated.
const deleteHandler = async (id) => {
try {
console.log(id)
await axios.delete(
`{url}.json/${id}`
);
const toDoList = toDos.filter((toDo) => toDo.id !== id);
setToDos(toDoList);
} catch (err) {
console.log(err);
}
};
I tried to find solutions to fix the problem but so far nothing worked and i am really stuck. I found a stackoverflow question to oxforddictionary problem that's the same as mine but i don't know how to apply it to my firebaes database.

How can i bypass cors error on the client side when building web apps?

I'm trying to make a get request to githubjobs API in my nuxt app using axios. I have axios properly setup and configured. Here is the action I want to dispatch:
async defaultJobsFetch({commit}){
try{
const res = await axios.get('https://jobs.github.com/positions.json?location=new+york')
const jobs = res.data;
commit('getJobs', jobs)
}catch(error){
commit("errored");
console.log(error)
}
finally{
commit('changeLoading')
}
},
I tried using https://cors-anywhere.herokupp.com/ too, but I still get an error 403 forbidden
I noticed it works fine on my local machine but when i deploy, and try to load the deployed app, I don’t get a response back, i get that 403 error instead. The app is hosted on heroku, http://hubjobs.herokuapp.com, check the console when you visit the site to see the error
One workaround would be to use a chrome extension like CORS unblock or try having this in the header :
Access-Control-Allow-Origin: *
You can try cors.bridged.cc instead of cors-anywhere.herokupp.com

Large firebase function requests seem to cause connection error

I have a firebase function that works perfectly well when I'm running it on my local machine. It sends an email. This is the code:
exports.sendEmail = functions.https.onRequest((req, res) => {
const msg = req.query
return sgMail.send(msg)
.then(mailResponse => {
return cors(req, res, () => {
res.status(200).send(mailResponse)
})
})
.catch(err => {
return cors(req, res, () => {
console.log(err)
res.status(200).send(err)
})
})
})
However, when it is deployed, whether I'm requesting it from my local machine or from my hosted deployment with firebase, I encounter this error:
Access to XMLHttpRequest at ... from origin ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
However, if the request is small enough, then it goes through, fires the function correctly, and produces no error. It's only when I try to push through a relatively large email that has a lot of report data that I encounter this issue.
I tried to switch from a GET to a POST request but this seemed to have no effect.
The firebase functions log says things like Function execution took 696 ms, finished with status: 'connection error' when the error happens.
As per Google documentation for HTTP functions, you may get errors like that if cross-origin resource sharing (CORS) isn't set up properly.
CORS consists of two requests: a preflight OPTIONS request, and a main request that follows the OPTIONS request.
The preflight request contains headers indicating method and additional headers, which will be sent in the main request, as well as the origin of the main request.
To handle a preflight request, you must set the appropriate Access-Control-Allow-* headers to match the requests you want to accept. Please see this link for an example.

Origin 'http://localhost:3000' is therefore not allowed access Twitter API

I'm developing a web application that uses the Twitter API REST. I have a page with Twitter accounts and a button for adding a new account. When the button is pressed, the function in the Angular controller is executed:
// Calls token to add a new Twitter user
$scope.callToken = function () {
$http.get('/token')
.then(function (response) {
console.log(response);
});
};
This is the code in the backend to serve de request. It simply redirects to Twitter to add a new user.
// routes.js
var token = express.Router();
token.route('/token')
.get(cuentasCtrl.getToken);
// Account file
exports.getToken = function(req, res) {
twitter.getRequestToken(function(err, requestToken, requestSecret) {
if (err)
res.status(500).send(err);
else {
_requestSecret = requestSecret;
res.setHeader('Access-Control-Allow-Origin', '*');
res.redirect("https://api.twitter.com/oauth/authenticate?oauth_token=" + requestToken);
}
});
};
But I get the next error:
Origin 'http://localhost:3000' is therefore not allowed access Twitter API
My server is running on localhost:3000 and If I put localhost:3000/token in my browser there is no problem. I have read the solutions for using CORS and tested other browsers but it hasn't worked for me. What have i done wrong?
The redirect you are sending in your express response is caught by the http client you use in the frontend and the redirect happens there. You are in a classical CORS situation and of course this is not how you can interact with the Twitter rest APIs.
You have to make http calls to Twitter on the node side (server to server) or use a client side client library for Twitter (https://dev.twitter.com/web/javascript)

Calling a Node.js server with Vue.js

I have a simple Node.js server up and running. This is the code:
var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
res.writeHead(200, {
'content-type': 'text/plain'
});
res.write('Hello World!');
res.end();
})
server.listen(8090);
server.once('listening', function() {
console.log('Hello World server listening on port %d', 8090);
});
I can call this server using curl from the command line:
$curl localhost:8090
However, when I try to call it from a Vue application, I get an error. I have a Vue application running on localhost:8080, and I want to call my localhost:8090 server. My main.js Vue file is this:
import Vue from 'vue'
import resources from 'vue-resource'
Vue.use(resources)
import App from './components/App.vue'
import style from './styles/main.scss'
/**
* Root Vue instance
* #param {[element]} el: 'body' [Adds to the html body]
* #param {[component]} components: {app: App} [Renders ./component/App]
*/
new Vue({
el: 'body',
components: {
app: App
}
})
And this is the App component:
<template>
<h1>{{ msg }}</h1>
<input v-model="msg">
<button v-on:click="get">Call Server</button>
</template>
<script>
export default {
data: function() {
return {
msg: 'Hello World!'
}
},
methods: {
get: function() {
// GET request
this.$http({
url: 'localhost:8090',
method: 'GET'
}).then(function(response) {
console.log('ok');
}, function(response) {
console.log('failed');
});
}
}
}
</script>
When I click the button I get this error:
XMLHttpRequest cannot load localhost:8090. Cross origin requests are
only supported for protocol schemes: http, data, chrome,
chrome-extension, https, chrome-extension-resource.
When I try to call another server, like google.com, I get this error:
build.js:19188 GET http://localhost:8080/google.com 404 (Not Found)
So it seems like Vue is putting the localhost:8080 in front of the call, and maybe this is where my problem lies? Making server calls is completely new to me, I'm just playing around with Vue and want to learn Node.js while I do so.
This basically has nothing to do with Node or Vue and everything to do with how security in the browser is implemented. CORS is not a workaround. Read up on CORS to see why it is needed. This question of mine, which is quite similar to yours, has some good info in the answers sections as well. To be able to call an API without using CORS it needs to run on the same host, port and protocol, otherwise it will be blocked by your browser.
Years ago, before the advent of CORS, you needed to use JSONP to achieve the same. You can of course have a look at it to see how this works, but nowadays there is very little need for that technique as we have proper cross-domain support in the form of CORS.
Regarding your question in one of the comment sections on "How do people call API's when working with Vue.js?", they do one of the following:
Run the API on another server (such as api.mydomain.com), but set the CORS headers on the response.
As above, but the client and server wraps responses using the JSONP method mentioned above.
Run the API on the same server as the one serving pages. This means api calls will be done against an endpoint such as localhost:8080/api
Twist on #3: just proxy calls coming in on the server to another server. Meaning you can have your api server running elsewhere, but your main server that is accepting calls on /api will just send these requests on the the next server after stripping off the /api prefix. Usually, people either setup an Apache or Nginx instance in front of your app server and do the actual proxying on that, but you can also do it in your app server, using something like node-proxy.
You can probably read this through the lines already, but save yourself some trouble (and time) and just use CORS :) #trquoccuong has the details on doing this in his answer.
CORS problems, you can use cors node module or add request header
if use Express
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
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');
if use http module
res.setHeader

Categories