POST request from React to Node.js - node.js

I don't know why this happens.
When I'm making a request to my server in Node.js and when it's GET then I can get a response. It looks like that:
fetch(config.apiUsersURL, {
method: "GET",
headers: {
"Content-Type": "application/json"
},
credentials: "same-origin",
mode: 'no-cors'
})
.then(res => this.setState({
isConected: true
}))
.catch(error => error);
When I'm requesting to the same url but with POST I'm getting nothing. Am I missing something?
const ObjToSend = { isReady: true };
fetch( config.apiUsersURL, {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify(ObjToSend),
headers: {
"Content-Type": "application/json"
},
credentials: "same-origin",
mode: 'no-cors',
})
.then(res => res.json())
.then(r => this.setState({ questions: r }))
My endpoint looks like that:
let randomProblem2;
router.post('/', (req, resp) => {
resp.append('Access-Control-Allow-Origin', '*')
resp.append('Access-Control-Allow-Headers', 'Content-Type')
console.log("this shows if yes was clicked", req.body)
if(req.body.isReady){ //when clicked
randomProblem2 = problemManager.getRandomProblem();
randomize(randomProblem2, resp);
}
})
function randomize(randomProblem2, resp){
resp.json({
randomProblem : randomProblem2
}
)}

Since the mode you are using is no-cors, you cannot use javascript to access the response
Quoted below from MDN:
no-cors — Prevents the method from being anything other than HEAD, GET
or POST, and the headers from being anything other than simple
headers. If any ServiceWorkers intercept these requests, they may not
add or override any headers except for those that are simple headers.
In addition, JavaScript may not access any properties of the resulting
Response. This ensures that ServiceWorkers do not affect the semantics
of the Web and prevents security and privacy issues arising from
leaking data across domains.
Kindly check the MDN link below for the rest of mode options
https://developer.mozilla.org/en-US/docs/Web/API/Request/mode

Related

MERN simple app CORS error issue - POST request

I am getting,
Access to fetch at 'http://localhost:9000/api/v1/content' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
and
for my FE(react)
and getting syntax err for BE(node),
SyntaxError: Unexpected token " in JSON at position 0
I have no issue with GET request but I can't POST.
Here is my FE
addContent = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:9000/api/v1/content', {
method: 'POST',
body: JSON.stringify(this.state.title),
// mode:'cors', --> tried after researching but it didn't solve my issue
headers: {
'Content-Type': 'application/json'
}
});
if(!response.ok) {
throw Error(response.statusText)
}
} catch (err) {
console.log('addContent failed -', err)
}
}
Here is my BE
origin: ['http://localhost:3000', 'https://localhost:3000'],
credentials: true,
optionsSuccessStatus:200
}
app.use(cors(corsOptions));
Also, when I POST with postman, I was able to POST(got 200) however, it only returns _id. there is no body(content title that I want to post)
I read many articles that explained about cors issue but I couldn't find right answer to solve my issue. Please assume me as beginner of programing.. Thank you ahead!!
Try This
addContent = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:9000/api/v1/content', {
method: 'POST',
body: JSON.stringify(this.state.title),
// mode:'cors', --> tried after researching but it didn't solve my issue
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
}
});
if(!response.ok) {
throw Error(response.statusText)
}
} catch (err) {
console.log('addContent failed -', err)
}
}
And also you can refer https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
And I suggest try once without using cors at express.
origin: ['http://localhost:3000', 'https://localhost:3000'],
credentials: true,
optionsSuccessStatus:200
}
//app.use(cors(corsOptions));
Your error here, means that you are not allowed to access localhost:9000 from any other URL.
I recommend you take a look at this (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
If you want your API to be accessed by anyone, you can set your "Access-Control-Allow-Origin" header to "*".
Here is a full explanation of this header purpose (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin).
I hope it will be useful.

API call from https node application never reaches the destination

I have a node.js application served over https. I would like to call an API from that application. The API is also served over https and it has been generated using the express-generator.
Unfortunately the call never works. There is no error message. The call never reaches the API.
Strangely enough if I try to call another public API (e.g. https://api.publicapis.org/entries') that is working perfectly.
Here is my call:
const requestBody = {
'querystring': searchQuery,
};
const options = {
rejectUnauthorized: false,
keepAlive: false, // switch to true if you're making a lot of calls from this client
};
return new Promise(function (resolve, reject) {
const sslConfiguredAgent = new https.Agent(options);
const requestOptions = {
method: 'POST',
body: JSON.stringify(requestBody),
agent: sslConfiguredAgent,
redirect: 'follow',
};
fetch('https://192.168.112.34:3003/search', requestOptions)
.then(response => response.text())
.then(result => resolve(result))
.catch(error => console.log('error', error));
});
};
And here is the API which I would like to call:
router.post('/', cors(), async function(req, res, next) {
req.body;
queryString = req.body.querystring;
let data = JSON.stringify({
"query": {
"match": {
"phonetic": {
"query": queryString,
"fuzziness": "AUTO",
"operator": "and"
}
}
}
});
const { body } = await client.search({
index: 'phoneticindex',
body: data
});
res.send(body.hits.hits)
});
What is wrong with my API and/or the way I am trying to communicate with it?
UPDATE: I receive the following error in the fetch catch block: 'TypeError: Failed to fetch'
When I create a request in Postman I receive the expected response.
UPDATE 2: This is most probably an SSL related issue. The webapp is expecting an API with a valid certificate. Obviously my API can only have a self signed cert which is not enough here. How can I generate a valid cert for an API which is running on the local network and not publicly available?
UPDATE 3: I managed to make it work by changing the fetch parameters like this:
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
mode: 'cors',
body: raw,
agent: httpsAgent,
redirect: 'follow',
})
and on the API side I added the following headers:
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : 'https://localhost:2200',
'Access-Control-Allow-Methods' : 'POST',
'Access-Control-Allow-Headers' : 'Content-Type, Authorization'
I also added app.use(cors()) and regenerated the self-signed certificates.

Basic Auth is not working with Axios post Nodejs

I am trying to send a request using axios post with basic authorization. It is working fine with postman but not working when I try to send via code.
axios.post(`my-url`, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic **KEY_HERE**',
},
data: {
'id': 'event_order',
'date': '2021-09-09'
}
}).then(async (response) => {
console.log(response.data)
})
It is returning 401 Unauthorized. But, it works as excepted when I call it via Postman:
Postman Setup Image
Did you add your domain to whitelist in your cors module? If not:
app.use(cors({ origin: "PROTOCOL://DOMAIN:PORT", credentials: true }));
edit: Ok, sorry, I was confused and thought you were sending a frontend axios post request to your own NodeJS server. If possible, could you be more precise. But try passing in your headers/auth as the third argument-- since you're passing in everything in the second argument, the API is not parsing out your headers since its part of the data parameter.
const data = {
'id': 'event_order',
'date': '2021-09-09'
}
axios.post(`my-url`, data, {
headers: {'Content-Type': 'application/json'},
auth: {
username: "YOUR_USERNAME",
password: "YOUR_PASS"
}
})
.then(async (response) => {
console.log(response.data)
})
Also try and post the network errors, if you can.

POST request to DeepL api through node.js not working

Can anyone spot any problems that may explain why the api client is giving me the forbidden error? I know the credentials are correct, as GET requests w the same info in the url work find.
Thank you in advance
app.get('/translate', (req, res) => {
var textToTranslate = "Hello friend"
const targetLanguage = "ES"
var link = `https://api-free.deepl.com/v2/translate`
var options =
{
method: 'POST',
headers: {
"Host": 'api-free.deepl.com',
"Content-Length": 54,
"Content-Type": 'application/x-www-form-urlencoded',
"User-Agent": "YourApp",
"Accept": "*/*",
},
body: JSON.stringify({
'auth_key': deeplAccessCode,
'text': textToTranslate,
'target_lang': targetLanguage
}),
}
return fetch(link, options)
.then((response) => {
console.log(response)
return response.json(); //Transform http body to json
})
.then((json)=> {
res.send(json) //return json to browser
})
.catch(e => {
console.log(e)
return res.sendStatus(400);
});
})
It's probably failing because you're setting your Content-Type of your body to be application/x-www-form-urlencoded (which is correct as per the DeepL API specification) but then you provide a JSON body (which would require content type to be application/json).
You need to provide a URL-encoded body instead, like the part you can also append to the URL after the ?. See also this answer on SO.

400 Bad request while fetching data in post call

I am running my React js web app in one port 3000.
For node server I am using 4000.
While calling fetch method it returns `400 Bad request'.
Error
POST http://localhost:4006/auth/admin 400 (Bad Request)
react code npm started in 3000 port
fetch('http://localhost:4000/auth/admin',
{ mode: 'no-cors',
method: "POST",
body: JSON.stringify({
username:"admin",
password:"1234"
}),
headers: {
"Content-Type": "application/json",
'Accept': 'application/json, text/plain, */*',
credentials: "omit", //
// "Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => console.log(response));
node code running in 4000 port
const passport = require("passport");
const route = require("../constants/routeStrings");
const keys = require("../config/keys");
const processStatus = require("../constants/processStatus");
const success = {
status: processStatus.SUCCESS
};
const failute = {
status: processStatus.FAILURE
};
module.exports = app => {
app.post('/auth/admin', passport.authenticate("local"), (req, res) => {
res.send(success);
});
};
Do not stringify the body. Change from
body: JSON.stringify({
username:"admin",
password:"1234"
}),
to
body: {
username:"admin",
password:"1234"
},
The 400 response is raised by passport since it is unable to read your params. You need to tell your "node" app to parse them before your actual routes.
// Import body parser, you should read about this on their git to understand it fully
const parser = require('body-parser');
const urlencodedParser = parser.urlencoded({extended : false});
// before your routes
app.use(parser .json());
app.use(urlencodedParser) // This will parse your body and make it available for your routes to use
Then do your other calls.
Also, make sure that you are sending username and password keys, otherwise read the documentation on how to change these key names to something else
I suffered long hours, but I overcame it throw writing those lines of code blocks. I successfully send the request to the server's controller, hopefully yours: make it try.
First define a async function to make POST request:
async function _postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(data)
});
return response.json();
}
Now create a request JSON payload:
let requestPayload = {
propertyName1: 'property value1',
propertyName2: 'property value23',
propertyName3: 'property value',
So on
}
Note: Request model will be your desired model, what request payload you actually send.
Now make a request using this payload including your end point URL:
_postData('http://servername/example', requestPayload )
.then(json => {
console.log(json) // Handle success
})
.catch(err => {
console.log(err) // Handle errors
});
100% worked on my project.

Resources