I'm getting a 405 (METHOD NOT ALLOWED) on a post request. I know that jsonp only works for GET requests, and that I most likely need to enable CORS. Is there a way to enable CORS through my javascript file? Or any way that doesn't involve creating a separate server side bridge? Here is the code for the ajax request:
function getData(){
var myUrl = 'http://text-processing.com/api/sentiment/';
var searchTerm = "happy";
$.ajax({
url: myUrl,
type: 'POST',
data: { 'text' : searchTerm },
dataType: 'jsonP',
error: function(msg) {
console.log(msg);
},
success: function(response){
console.log("it worked");
console.log(response);
}
});
}
getData();
if you are using ExpressJS
There is a way that is to enable cross domain:
In the file you are posting for, after the requires statements, try to add this code here:
exemplo: you are posting for user.js, so past it in the beginning of the file after you get the routes.
var router = express.Router();
router.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT, GET,POST,OPTIONS");
next();
});
Actually, you can add just:
router.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
or this for specific requests:
router.all('/', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
However, I think this is not so secure. You can do a research like I am doing now to see the best way to use it, but you can use it for test and change it later. At least, you are not going to be stuck in this part.
source : http://enable-cors.org/server.html
http://enable-cors.org/server_expressjs.html
Good Luck! ;)
Related
I am trying to post some data to my nodejs server using fetch api but it seems the fetch request never reaches my server..
Fetch code
const resp = await fetch("http://localhost:5000/api/students/", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: `{
"name": "Ahmed",
"seat": 4
}`
});
console.log(resp);
const json = await resp.json();
return json;
nodeJS post body
route.post("/", CORS, async (req, res) => {
console.log('abc', req.body);
const {
error
} = validateStudent(req.body);
if (error) return res.status(400).send(error.details[0].message);
const result = await addStudent(req.body);
if (!result) return res.status(400).send("Student cannot be added");
res.status(200).send(result);
});
code of CORS middleware
console.log('avcx');
res.header("Access-Control-Allow-Origin", "*").header(
"Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
console.log('acvced');
next();
As you can see I've done some logs on my server but nothing shows up... BTW eveything is working fine with get request..
sending the same request with postman works fine.
I don't know why I'm getting this error I tackled this error for GET requests by creating a middleware 'CORS' but I'm still getting this error for POST request:-
Thanks in advance :)
I solved this problem. I wasn't handling the incoming requests correctly because I didn't know that fetch sends a preflight request with an OPTION method before sending the actual POST request. So I solved it by adding this line in my index file above every other request which will be executed every time a request (with any method) is made.
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*").header(
"Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", " GET, POST, PUT, PATCH, POST, DELETE, OPTIONS");
next();
});
I wanted to give a post request to the required URL but without proxy setting it was giving cors error, I have gone through and end up with setting the proxy but still it is taking the localhost as the URL. I have attached my proxyfile.js and my code snippet with the error below.
export function PostData(userData) {
var targetUrl = "/downloadableReport";
return new Promise((resolve, reject) => {
fetch(targetUrl, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8",
Accept: "application/json"
},
body: JSON.stringify({
requestData: {
userName: userData.userName,
password: userData.password
}
})
}).then(response => response.json());
});
}
This is the setupProxy.js code:
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(
proxy("/downloadableReport", {
target: "http://192.168.1.220:28080/xms/abc",
changeOrigin: true
})
);
};
And this is the error:
If CORS is the problem and you are using express as the backend server,
then
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Role');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.sendStatus(200);
} else {
next();
}
};
and then add
app.use(allowCrossDomain);
Ditch the proxy. To me, your problem looks like, you're POSTing data to the React App itself. If you are indeed having both the API and React, in the same project, I would suggest that you split them.
If they are not indeed together, update the targetUrl to a proper url with the protocol and the domain. Like var targetURl = 'http://localhost:3000/downloadableReport.
UPDATE: I read your comment reply to Sudhir. Edit the target Url as the full path to the API var targetUrl = "http://192.168.1.220:28080/xmsreport/report/downloadableReport" and add the CORS code I have provided above to the API at 192.168.1.220:28080
SOLVED, see my answer below
My server runs on localhost:3000
I develop on localhost:4200
I am creating something and trying to post it on an Amazon API
Angular side code:
sendSomething(something) {
const body = JSON.stringify(something);
// const headers = new Headers({'Content-Type': 'application/json'});
const headers = new Headers({'Access-Control-Allow-Origin': '*'});
return this.http.post('http://Amazon-API:port/send', body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.error.handleError(error.json());
return Observable.throw(error.json());
});
}
Server side:
//////////////app.js//////////////
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*'); //<-- you can change this with a specific url like http://localhost:4200
// res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});
app.use('http://Amazon-API:port', engineRoutes);
//////////////routes/engine.js//////////////
router.post('/send', engine_controller.send_something);
//////////////controllers/engine.controller.js//////////////
exports.send_something = function (req, res, next) {
const somethingID = req.body.something;
Something.findById(somethingID, function(err, something) {
if (err) {
res.status(404).json({
title: 'Something not found',
error: {message: 'Something went wrong'}
});
}
console.log(something);
if (something) {
res.status(200).json({
message: 'Something successfully sent',
something: something
});
}
})
};
I have tried posting to that API with cors, without cors and with the res.headers appended, and every other variation I could think of
I still get this error which I've seen so common around here, but still, their solutions don't seem to work for me. Still getting this error...
Failed to load http://Amazon-API:port/send: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.
That's from NETWORK tab:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7
Access-Control-Request-Headers:access-control-allow-origin
Access-Control-Request-Method:POST
Connection:keep-alive
Host:Amazon-API:port
Origin:http://localhost:4200
Any kind of help would be so much appreciated
I see you added this code but I can't post comment yet, you may try to add this code before other routes
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With,
Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE,
OPTIONS');
next();
});
Solved,
What I did was routing back to the server on the front:
sendSomething(something) {
const body = JSON.stringify(something);
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.post('http://localhost:3000/api/somethings/send-something', body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.error.handleError(error.json());
return Observable.throw(error.json());
});
}
And then accepting this route as it is on the back:
//////////////app.js//////////////////
app.use('/api/somethings/send-something', engineRoutes);
/////////////routes/engine.js/////////
router.post('/', engine_controller.send_something);
And most importantly, in the controller itself I used the newly downloaded request lib to send my json data to my external API:
////////////controlllers/engine.controller.js////////////
const request = require('request');
exports.send_something = function (req, res, next) {
const SomethingID = req.body.something;
Something.findById(SomethingID, function(err, something) {
if (err) {
res.status(404).json({
title: 'Something not found',
error: {message: 'Something went wrong'}
});
}
request({
url: app.get('amazon-API:port/method'),
method: "POST",
json: something
}, function (error, response, body) {
// console.log(error) <--- returns null or error
// console.log(response.statusCode <--- returns 200 / 403 / w.e
// console.log(body) <--- returns response pure html
res.status(200).json({
message: 'Something successfully sent',
response: body,
status: response.statusCode
});
});
})
};
Now as a response I'm getting what the server which I posted to sends me back, which is exactly what I need.
Ultimately I figured my way thanks to many other questions posted here
So thank you SOF once again!
I'm trying to switch control to another route (NOT next route) having path /getProfile when the condition is not matched. For this, I'm using res.redirect()
(Query 1: Is it the right way to passing control from one router to another? If no, how would I do it?)
Here's some code from my server side JS:
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
next();
});
app.use('/getProfile', function (req, res, next) {
var userName = req.session.userName;
if(userName && userName != 'undefined'){
console.log("if");
next('route');
} else {
console.log("else");
res.redirect("getProfile");
next('route');
}
});
app.post('/getProfile', function (req, res, next) {
//do something
});
Client side code:
$scope.getProfile = function(){
loggedInUser=$("input[name='email']").val();
$http({
method : "POST",
url : "http://192.168.43.200:3000/getProfile",
data: JSON.stringify({userName: loggedInUser}),
headers: {'Content-Type': 'application/json'}
}).then(function mySuccess(response) {
//do something
}, function myError(response) {
//do something
});
}
But I'm getting following error when I hit request to /getProfile from browser:
XMLHttpRequest cannot load http://192.168.43.200:3000/getProfile. Response for preflight is invalid (redirect)
Query 2: Am I doing something wrong?
Query 3: Is there any difference between passing (I don't know what it is called, I've already asked about it in Query 1) control to another route and redirect?
NOTE: I'm getting above error only after introducing app.use("*") and redirect part.
Please answer these queries. I'm really confused.
I have spent too much time trying to debug this but unsure where its coming from or why I am getting this error.
I am trying to make a simple website to practice react and am trying to get some data from Riot's API.
I tried to use isomorphic-fetch but ran into issues with https so I switched to express.
After switching to express I am getting "Uncaught TypeError: Cannot read property 'prototype' of undefined.
I am also using browserify-middleware if that matters at all.
Here is the file that is causing issues.
// import fetch from 'isomorphic-fetch';
// var myHeaders = new Headers();
var express = require('express')
var app = express();
var apiURL = 'https://na.api.pvp.net/api/lol/na/v1.4/';
var apiToken = '?api_key='
// export function fetchSummonerInfo() {
// return fetch(apiURL + 'summoner/by-name/' + AUserName + apiToken, {
// method: 'GET',
// mode: 'no-cors'
// })
// .then((data) => console.log(JSON.stringify(data)))
// // .catch((e) => console.log(e))
// // .then((res) => console.log(res))
// }
//
// app.use(function(req, res, next) {
// res.header("Access-Control-Allow-Origin", "*");
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// next();
// })
export function fetchSummonerInfo() {
app.get(apiURL + 'summoner/by-name/Faxious' + apiToken, middle, function(req, res) {
let body = ""
res.on('data', function(data) {
body += data;
})
res.on('end', function() {
console.log(body);
})
})
}
function middle(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
}
Express is a web framework for your backend to handle the request and provide a response not to execute requests. Have a look at routing guide here.
If you want to make requests i can recommend request module which i personally prefer for my projects and it's pretty straight forward. There are some alternatives such as axios as well.