ExpressJS not sending Access-Control-Allow-Origin header - angularjs

I am working on a project where I need an angular web app to be able to access a node/express based backend, and I am attempting to use Cors. However, the express server seemingly won't send the Access-Control-Allow-Origin header, and I have no clue why. I've tried creating a middleware as such:
this.app.use((request, response, next) => {
response.header("Access-Control-Allow-Origin", "*");
next();
}
I've also tried doing something similar individually for each request, using setHeader(), header(), set() and append(), but none of these work either. I'm currently using the cors npm package, but that also isn't working with the following code:
this.app.use(cors({
origin: "http://localhost/4200"
}));
this.app.options("*", cors({
origin: "http://localhost/4200"
})
);
I've checked that none of these are adding the relevant header to the response via postman. Express is adding the "error" header I use to give a human-readable description of the error, but not "Access-Control-Allow-Origin".
I'm writing this in TypeScript.

Did you restart your express server after making the change?
Did you try also adding the Access-Control-Allow-Headers header?

Did you check your middleware is invoked on request?
Did you check your middleware is registered before listen is called?
If both is guaranteed it must have a reason depending on a other part of your Application. So you should provide more information about booting and structure of files and directories.

Turns out the problem wasn't with the code, but with the compiler setup. I deleted and recreated the tsconfig.json file, and it works now.

Related

Can't solve strict-origin-when-cross-origin. React + AdonisJS

I have a server, in which I'm running two different applications. The frontend (express + React) is running on 443 port, and the AdonisJS api is running on 3333 port. They share the same domain (something.com, for example), but I need to add the port when calling the api. The problem is, when I try to hit an endpoint from my api from React, I get this error: strict-origin-when-cross-origin. Actually, I'm not sure if this is an error, but I can't make any request at all. From another client, such as Insomnia, the request works like magic.
I fixed the issue by changing the AdonisJS cors config file. I switched the origin value from true to *.
Besides adding the proxy instruction in package.json
"proxy": "http://localhost:5000", I also had to remove the host from the api url request, so:
const apiData = await axios.get('http://127.0.0.1:5000/api/get-user-data');
became
const apiData = await axios.get('/api/get-user-data');
The link provided by #ShawnYap was really helpful https://create-react-app.dev/docs/proxying-api-requests-in-development/

Cors issue i also set the proxy in pkg.json due to cors and set the api according to it but this error is not remove

GET http://localhost:3000/api/fetch?search=12312321 404 (Not Found)
cors issue in Reactjs and node js
i use the proxy method in Reactjs but can't get rid from it please help me
proxy
"proxy":"http://localhost:5000/"
tried both
"proxy":"http://localhost:5000"
express
RegisterRoute.route('/fetch/:id').get( ( req , res) =>
{
console.log("called by someone ",req.params.id);
res.send("okey will");
});
Reactjs function which will call the backend api
FetchNotification(){
axios({
'method':'GET',
'url':'api/fetch',
'headers': {
'content-type':'application/octet-stream',
'x-rapidapi-host':'example.com',
'x-rapidapi-key': process.env.RAPIDAPI_KEY
}
,
'params': {
'id':'12312321'
},
})
}
when i simply call axios.get it perfectly work but when i give params to it it gives the error xhr:178 404 not found
a simple server which also returns the same result
const express = require('express');
const cors= require('cors');
const app= express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use('*',cors());
app.get('/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
});
app.listen(5000);
I can see that you're using Nodejs as server side. So, you can try changing following line
app.use('*',cors());
to
app.use(cors());
If this doesn't solve the issue, you can try adding a google chrome extension for CORS (Most probably). In this way, you'll not need any proxies being set for running servers.
Also, you need to do a small change in URL, instead of calling
'url':'api/fetch'
you need to provide an id in your call, because the backend api is accepting a parameter
'url':'api/fetch/some_id'
I feel there are multiple issues. I'll try to address them one by one.
Firstly, if you are proxying your requests correctly (which I think you are as per your package.json), then you'd not require the cors package. So you can get rid of that package.
Read more about why you shouldn't let all incoming request bypass the CORS check from security point of view -> Is it safe to enable CORS to * for a public and readonly webservice?
Now secondly, the url which you've specified on the frontend is 'url':'api/fetch', which means browser will make a call to http://localhost:3000/api/fetch?search=12312321 which it correctly did as seen in your error statement for 404.
Specifying the proxy as "proxy":"http://localhost:5000" in package.json means that now you are making requests to http://localhost:5000 instead of http://localhost:3000, but the browser would still think its http://localhost:3000. That's the whole purpose of proxying and how you kinda fool browser to do CORS without throwing any error.
But because on your server, you are listening to app.get('/fetch/:id',(req , res) instead of app.get('api/fetch/:id',(req , res), it doesn't matches with this URL as you have not explicitly handled requests starting with /api in some separate router module either.
So you should either update the url in the axios call to url':'/fetch while the proxy value in package.json is "proxy":"http://localhost:5000" or url':'fetch and "proxy":"http://localhost:5000/" respectively. Notice how i've used the /
OR
You can update the URL on the express end to app.get('api/fetch/:id',(req , res)
Lastly, whenever you receive a request, you need to return some value(string or JSON or even status code) as result.
In your case, you've simply console.log("calling",req.params.id); and didn't send back any response to the UI.
So even if your 404 would resolve after fixing the URL, you'd bump into request timeout error (408) as your UI will keep waiting for a response from the server while you didn't send any.
So you should do something like this maybe:
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});
Notice how there's a response being sent back -> https://expressjs.com/en/starter/hello-world.html
If you don't want to send back a response, then you can simply return status like 200, 504 etc.
if you apply below code in backend/server i thing it will debug.
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});

How do I fix a network error received from axios response reactjs

I'm making a post request using axios in reactjs after users login. Here it is:
axios.post('https://localhost:3000/api/login/authentication', {
email: email,
password: password
})
.then(response => {
this.props.history.push('/Main')
})
.catch(error => {
console.log(error)
})
It goes in the error and I log it to the console. This is what I get:
Error: "Network Error"
createErrorhttp://localhost:3000/static/js/0.chunk.js:26742:15 handleErrorhttp://localhost:3000/static/js/0.chunk.js:26293:14
Also in case it's any help, I get this warning before the error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://localhost:3000/api/login/authentication. (Reason: CORS request did not succeed)
Can anyone please help me solve this issue? Thanks in advance!
If you're using a front-end application that makes request to a back-end API, you need to include certain headers in the API server if the API server is running on a different port.
For example, if you're serving a ReactJS application with webpack in development mode, webpack acts as a server, sending the reactJS application to the client. Then, making requests to the API server will require that the API server, running on a different port, include Access-Control-Allow-Origin headers in all http responses.
Basically, before generating every response, you need to set 'Access-Control-Allow-Origin' to localhost:<port you visit in the browser>.
In a basic express app, you can paste this in your app.js file, for example:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();
});
Note: If you may need to change http://localhost:3001 to match the port you visit in the browser.
EDIT: OP is not using express, but is using Webpack. The question is: What is an express-agnostic solution?
Answer: The solution is still the same: regardless of what API server you are using, just set the response headers for every response.
There is another solution that involves Webpack, though:
In the package.json file of your front end code that's being served with webpack, add the following: "proxy" :"http://localhost:<port API server is running on>"
For example, is webpack is serving your front end app to localhost:3000 and your api server is running on localhost:3001, then the proxy in package.json would be:
"proxy":"http://localhost:3001"
You can add the CORS header in webpack dev server config as follows:
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
This will add these two headers in your response. Hence solve your problem. However, when your services run on a different server other than your local machine, these headers need to be added in server response.
The very first thing that i am figuring out in your code is that you are using 'https' but it should be only 'http'to make request, because local host uses http.
2)This might be due to cors, Before making any requests , the browser sends a pre-flight request to the API server to know that "This website has been allowed to access your resources or not", so using cors and specifying origin which can access API resources will solve this problem.

Getting CORS error in angularJS front end

I am using a flask server with an angular front end. Up until recently, I was running the project on my local and had no issues.
I now moved my project to a remote server and have been getting the following error. I am not sure what i'm doing wrong:
My error:
XMLHttpRequest cannot load http://ec2-..../api/loginStatus/. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8100' is therefore not allowed
access. The response had HTTP status code 503.
The snippets of my flask server side code (where I am adding my headers to the response is given below):
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin','http://localhost:8100')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
response.headers.add('Access-Control-Allow-Credentials', 'true')
return response
I use both restangular and $http methods in my front end angularjs.
I have added the following lines in the .config of my main module:
.config(['RestangularProvider', '$stateProvider', '$urlRouterProvider','$httpProvider',
function(RestangularProvider, $stateProvider, $urlRouterProvider,$httpProvider) {
//$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = "http://localhost:8100";
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.headers.common = 'Content-Type: application/json';
delete $httpProvider.defaults.headers.common['X-Requested-With'];
Would someone be able to help me out here? I've referred to a lot of material and I am not sure what i'm doing wrong.
PS: I am getting 200 status messages on my server. I am therefore assuming that the error is in my front end and not my server side. Please correct me if I am wrong
Regards,
Sunil
EDIT
Hi everyone, I have solved the issue. I would like to thank #Mathijs Segers and #Hassan Mehmood for their inputs.
It turns out that there was a nginx configuration issue which led to the server becoming unavailable.
Firstly, there was an issue with the symbolic link that was being created for the flask backend (I am running my server side through a git repo on /home/username and then creating a symbolic link at /var/www/sitename.com
I was also throttling the number of requests that can be sent in a second (users could send only 1 every 2 seconds) resulting in the 503 error.
The original code I put up worked fine after I fixed it.
Eyooo, it is actually on your server side. You need to provide correct headers.
So you've tried this, I have no experience with flask but this I don't like;
response.headers.add('Access-Control-Allow-Origin','http://localhost:8100')
for testing purposes I suggest you just change the http:// part, to *
so
response.headers.add('Access-Control-Allow-Origin','*')
If that doesn't work verify that the header is actually being set, you could use a different program which doesn't care for CORS like postman or directly calling it in the browser if it doesn't depend on Accept headers.
here is some more readings about what it all is about.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
EDIT:
Ok silly of me: The response had HTTP status code 503.
This part in the error actually states what kind of response your server is giving, so currently there is an error on your server side. This happens when it is f/e down or what not.
So it seems that you're not doing anything strange, but your server side seems broken.
XMLHttpRequest cannot load http://ec2-..../api/loginStatus/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 503.
So this error here, I suggest looking at your headers, and maybe disable some. You currently allow only 2 request headers that might cause some issues as well?
Flask-CORS
A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.
Installation
Install the extension with using pip, or easy_install.
$ pip install -U flask-cors
Simple Usage
In the simplest case, initialize the Flask-Cors extension with default arguments in order to allow CORS for all domains on all routes. Read More.
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)
#app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
Reference: https://flask-cors.readthedocs.io/en/latest/

How to properly separate frontend and backend?

I have a project which was built on playFramework. It has much busines logic, which involves actors, different parsers, works with three services through API, etc. Frontend is written with angularJs (single web page application). We also use coffeScript and less, and for that i added sbt plugins to compile them
I felt like it's not right to have this things altogether. Whenever i push commit to repository with changes related to css files, jenkins downloads scala dependencies, build project, etc. It's static content only for user experience.
My fronted developer gets crazy when he needs to make some changes in backend part because he doesn't know scala well enough. So he spends time in not effective way by trying to get it to work whilst i can do this for minimum time.
I think one repository should be for fronted (angular, coffee, less, images, fonts) and second one is for backend.
Today i've read few articles about that problem, got inspired, and i decided to separate them once for all :)
Firstly i installed node, npm, grunt, and http-server
Then i setup plugins for grunt: less, and coffee.
I ran 'grunt http-server' on address: localhost:8282
Launched my play application on address: localhost:9000
Then replaced old angular $resource url '/api/client' with 'localhost:9000/api/client' to check whether it works and i will see clients list on page localhost:8282. But it doesn't work. I get this in js console:
XMLHttpRequest cannot load localhost:9000/api/client. Origin localhost:8282 is not allowed by Access-Control-Allow-Origin
This is cross domain issue, so i googled and changed controller which serves /api/client
Ok(toJson(res.sortBy(_.id))).withHeaders(("Access-Control-Allow-Origin", "*"))
Headers gets applied properly, i checked this in safari. I also configured angular $httpProvider
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
But it still doesn't work.
I'm not skilled in settings up http servers but may be there is a better way? May be to set up some proxy? Or to setup nginx some how?
Any suggestions? Thanks!
Setting up CORS in play consists of two steps
Respond to preflight requests (option requests)
Setting headers for response.
Seems you miss the first step, check this article for details.
Thanks to Rebotnix
You are right, backend didn't response with needed headers.
Scala code in article is outdated a little bit (There is no PlainResult in play 2.3.6), but it explains the point of using CORS.
package controllers.filters
import play.api.mvc.{Filter, RequestHeader, Result}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object CorsFilter extends Filter {
override def apply(nextFilter: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = {
nextFilter(rh).map { result =>
result.withHeaders(
"Access-Control-Allow-Origin" -> "*",
"Access-Control-Allow-Methods" -> "POST, GET, OPTIONS, PUT, DELETE"
)
}
}
}
And global settings:
import controllers.filters.CorsFilter
import play.api.mvc.WithFilters
object Global extends WithFilters(CorsFilter)
And preflight action (the same as article's one)
def preflight(url: String) = Action {
Ok.withHeaders(
"Access-Control-Allow-Origin" -> "*",
"Access-Control-Allow-Headers" -> "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent",
"Access-Control-Allow-Methods" -> "POST, GET, PUT, DELETE, OPTIONS",
"Allow" -> "*"
)
}
and set up route for preflight:
OPTIONS /*anyUrl controllers.Application.preflight(anyUrl:String)
Now everything works!

Resources