angular $resource delete won't send body to express.js server - node.js

hye,
i am building an app with angular.js and node.js (Express.js) on the server side.
for some reason i am having a problem handling a delete request. no body is getting to the server side.
this is my angular.js resource code:
$scope.deleteProject = function(projectName){
var postData = {username: 'name', projectName: projectName};
Project.deleteProject.delete({}, postData,
function(res){
alert('Project Deleted');
},
function(err){
alert(err.data);
});
}
on the server side i have this:
var deleteProject = function(req, res){
console.log(req.body);
console.log(req.params);
if (req.body.projectName){
//do something
return res.send(200);
}
else
return res.send(400, 'no project name was specified');
}
now for some reason there is no body at all!! it is empty.
i have defined the route as app.delete.
if i change the route in node.js to post and in angular.js to save it works fine.
what am i missing here (banging my head).
thanks.

As per this stack overflow question and the $http service source code, a DELETE request using $http does not allow for data to be sent in the body of the request. The spec for a DELETE request is somewhat vague on whether or not a request body should be allowed, but Angular does not support it.
The only methods that allow for request bodies are POST, PUT, and PATCH. So the problem is not anywhere in your code, its in Angular's $http service.
My suggestion would be to use the generic $http(...) function and pass in the proper method:
$http({
method: 'DELETE',
url: '/some/url',
data: {...},
headers: {'Content-Type': 'application/json;charset=utf-8'}
})

Angular by default sends the Content-Type as text/plain for DELETE requests. Just add this to the headers:
var config = {
method: "DELETE"
url: yourUrl
data: yourData
headers: {"Content-Type": "application/json;charset=utf-8"}
};
$http(config);
If you want to add them to every single DELETE request add this to the app.config method in your main controller:
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };

If you want to use the $resource object instead of $http you need to add hasBody and headers as follow:
delete: {
method: 'DELETE',
hasBody: true,
headers: {"Content-Type": "application/json;charset=UTF-8"}
}
Worked for me

Just ran into this problem. You'll have to use url params to send an id with delete.
in express:
app.delete('/api/user/:userId', user.remove);
and add to the url in angular:
$http({url: 'whatever/api/'+obj.id, method: 'DELETE'}) ...

The following works for me:
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';
XMLHttpRequest is optional but useful if you are sending ajax.
https://docs.angularjs.org/api/ng/provider/$httpProvider for more information.

This worked for me.
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };
And then
$http.delete(url, { data: data })

Related

node.js how to send multipart form data in post request

I am attempting to get data in the form of an image sent from elsewhere using multipartform, however when trying to understand this via the great sanctuary(stack overflow) there are missing elements I don't quite understand.
const options = {
method: "POST",
url: "https://api.LINK.com/file",
port: 443,
headers: {
"Authorization": "Basic " + auth,
"Content-Type": "multipart/form-data"
},
formData : {
"image" : fs.createReadStream("./images/scr1.png")
}
};
request(options, function (err, res, body) {
if(err) console.log(err);
console.log(body);
});
2 questions:
what is the variable auth, what do I initialize it to/where/how do I declare it
what is the url "api.LINK.com", is this just the site url where this code is on
After your comments I think I may be doing this wrong. The goal is to send data(an image) from somewhere else(like another website) to this node app, then the nodeapp uses the image and sends something back.
So that I would be the one creating the API endpoint

Node.js? API Authentication problems

This is what my "dev" sent me. Someone help please
I'm trying my best, but their API doesn't respond to our methods. This authentication is the root of the problem. I'm right now using Axios(the most popular and only method for making API requests for web apps) but it's not accepting request
and then i told him i would ask for help*
You can ask this question- ` How do I make requests for creating order API in my express app? I've tried to make the request by getting my form data from my EJS form using the request.body. But still, it is saying error 400.
Here is his code:
app.post('/order-labels', checkAuthenticated, (req, res) => {
const data = JSON.stringify(req.body);
console.log(data)
const config = {
method: 'post',
url: 'https://labelsupply.io/api/order',
headers: {
'X-Api-Auth': '32854090-03dd-a3c1-Deleted some for safety',
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
axios(config)
.then(function(response) {
console.log(response.data);
})
.catch(function(error) {
console.log(error);
});
})
by console.logging we are getting the data, but the API doesn't accepting
The API Docs are here.
you may need an account to view just put junk
The API calls for url encoded string.
const data = JSON.stringify(req.body);
console.log(data)
data = new URLSearchParams(Object.entries(data)).toString();
console.log(data); // now should be URL encoded
const config = {
method: 'post',
url: 'https://labelsupply.io/api/order',
headers: {
'X-Api-Auth': '32854090-03dd-a3c1-Deleted some for safety',
'Content-Type': 'application/x-www-form-urlencoded'
},
data: data
};
See if the API likes the new encoding?

Body of a request is empty [duplicate]

I have a React application where I am changing POST method to GET with the request body as it is. It works fine with POST request however when I change the method to GET, it gives me error-
message: "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public
My Front End Code-
export const setData = (getData) => dispatch => {
axios({
method: 'GET',
url: 'http://localhost:8080/api',
headers: {
'Content-Type': 'application/json'
},
data: getData
})
.then (response => {
dispatch({
type: API_DATA,
payload: response.data
})
dispatch({
type: SET_SEARCH_LOADER,
payload: false
})
})
.catch(function(error) {
})
}
Can someone let me know what I am missing here. As per my understanding, http allows to have a request body for GET method.
As per my understanding, http allows to have a request body for GET method.
While this is technically true (although it may be more accurate to say that it just doesn't explicitly disallow it), it's a very odd thing to do, and most systems do not expect GET requests to have bodies.
Consequently, plenty of libraries will not handle this.
The documentation for Axois says:
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
Under the hood, if you run Axios client side in a web browser, it will use XMLHttpRequest. If you look at the specification for that it says:
client . send([body = null])
Initiates the request. The body argument provides the request body, if any, and is ignored if the request method is GET or HEAD.
If you want to send parameters with get request in axios, you should send parameters as params.
If you want to set "Content-type":"application/json" and send params with get request, you should also send an empty data object.
For example:
const AUTH_TOKEN = 'Bearer token'
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': AUTH_TOKEN,
},
data: {},
params: {
"post_id": 1
}
}
axios.get("http://localhost/api/v1/posts/", config)
This is not axios, the error origniates from the java backend you're talking to. The public field in your request body is missing.
If you just want to send the data as parameters (which would be odd), pass it using params instead of data (as shown here: https://github.com/axios/axios#example).
I personally don't think your API should support GET with a request body (talk to the devs and ask for documentation).

override the content-type being set in the req.header with node js?

I have a web service making a post request to an API and in the process, for some reason, the content-type value of the header is being overwritten from 'application/json' to 'text/html'. This is causing the POST request to fail since the API only accepts the content-type: 'application/json'. To overcome this I was going to make the web service touch a proxy web server that would implement the server-side code to modify the req.header value "content-type" back to 'application/json' and send the post request along with the req.body and req.headers to the API. I am trying to do this in node js (with express js). How do i override the req.header on the proxy node js server? I have tried playing with the accept content-type to only application/json but that did not do what i needed :(
let request = require('request');
let proxyRequest = (data,headers)=>{
var options = {
'method': 'POST',
'url': 'your-api-url',
if (headers.hasOwnProperty('Content-Type')){
delete headers['Content-Type']
}
headers['Content-Type']= 'application/json'
body: data
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
};

Mailchimp API v3.0 add email to list via NodeJS http

I'm using NodeJS to call the new MailChimp 3.0 API in order to add an email to a list. While I can get it working via POSTman, I'm having a hard time with Node's http:
var http = require('http');
var subscriber = JSON.stringify({
"email_address": "test#test.com",
"status": "subscribed",
"merge_fields": {
"FNAME": "Tester",
"LNAME": "Testerson"
}
});
var options = {
host: 'https://us11.api.mailchimp.com',
path: '/3.0/lists/<myListID>/members',
method: 'POST',
headers: {
'Authorization': 'randomUser myApiKey',
'Content-Type': 'application/json',
'Content-Length': subscriber.length
}
}
var hreq = http.request(options, function (hres) {
console.log('STATUS CODE: ' + hres.statusCode);
console.log('HEADERS: ' + JSON.stringify(hres.headers));
hres.setEncoding('utf8');
hres.on('data', function (chunk) {
console.log('\n\n===========CHUNK===============')
console.log(chunk);
res.send(chunk);
});
hres.on('end', function(res) {
console.log('\n\n=========RESPONSE END===============');
});
hres.on('error', function (e) {
console.log('ERROR: ' + e.message);
});
});
hreq.write(subscriber);
hreq.end();
Rather than getting even some sort of JSON error from Mailchimp, however, I'm getting HTML:
400 Bad Request
400 Bad Request
nginx
Is it clear at all what I"m doing wrong here? It seems pretty simple, yet nothing I've tried seems to work.
A few additional thoughts:
While http's options have an "auth" property, I'm using the headers instead to ensure the authorization is sent without the encoding (as mentioned here). Still, I've also tried with the "auth" property, and I get the same result.
I'm actually making this call from inside an ExpressJS API (my client calls the Express API, that calls the above code - I've edited all that out of this example for simplicity). That's why my variables are "hres" and "hreq", to distinguish them from the "res" and "req" in Express. Is there any reason that could be the issue?
As mentioned above, I am able to get successful results when using POSTman, so I at least know my host, path, list ID, and API key are correct.
It turns out this had a very simple solution: the "host" property of the options object needed to have only the domain name. IE, remove the "https://" protocol:
var options = {
host: 'us11.api.mailchimp.com',
path: '/3.0/lists/<myListID>/members',
method: 'POST',
headers: {
'Authorization': 'randomUser myApiKey',
'Content-Type': 'application/json',
'Content-Length': subscriber.length
}
}
Try this , its working fine for Me.
var request = require('request');
function mailchimpAddListCall(email, cb){
var subscriber = JSON.stringify({
"email_address": email,
"status": "subscribed"
});
request({
method: 'POST',
url: 'https://us13.api.mailchimp.com/3.0/lists/<Your list id>/members',
body: subscriber,
headers:
{
Authorization: 'apikey <your Mailchimp API key>',
'Content-Type': 'application/json'
}
},
function(error, response, body){
if(error) {
cb(err, null)
} else {
var bodyObj = JSON.parse(body);
console.log(bodyObj.status);
if(bodyObj.status === 400){
cb(bodyObj.detail, null);
}
var bodyObj = JSON.parse(body);
cb(null, bodyObj.email_address +" added to list.");
}
});
}
request is a node module, that you'll need to install into your package.json. npm install --save request
You can use the auth properties just fine with API v3, but if you're getting a 400, that's not the problem. The body of the 400 Error should provide more detailed information, but one thing that jumps out immediately: MailChimp doesn't allow fake or fake-looking emails to be added to lists (like test#test.com), so I'd try a real address and see if that works for you.

Resources