Angular failed post request with error 500 - json

I am developing an ionic app that makes a rest call to a backend to send an email, when I make the rest call I get the following error, what can be due to (the rest call in postman works, I use chrome with the cors disabled)
Error:
POST http://172.16.50.92/send 500 (Internal Server Error)
Code Angular:
const params = {
'type': 'mail',
'attributes[to_recipients]': mail,
'attributes[body]': body,
'attributes[subject]': subject,
'attributes[attachments]': attachments
};
endpoint = url + '/send';
var headers_object = new HttpHeaders();
headers_object.append('contentType', 'application/json');
headers_object.append('Authorization', `Basic ${window.btoa(username + ':' + password)}`);
return this.http.post(endpoint, params, [headers_object]);

return this.http.post(endpoint, params, [headers_object]);
You put your headers into an array. But the signature is supposed to be
post(url: string, body: any, options: { headers: HttpHeaders })
for your usecase.
Please change to below and try again.
return this.http.post(endpoint, params, { headers: headers_object });

Related

How do I fix this JSON parsing issue?

I send data with fetch() in HTML to an express API, this is how it comes out in the req.body (I use body-parser)
{
'{"address":"a","town":"NYC","details":"a","appr":': { '"Car1"': '' }
}
it's all "stringy", as the only way I know to "parse it" to send it, is to send it with JSON.stringify. But, upon getting the info, it's "unparseable", JSON.parse errors with "unexpected string in JSON at position 62"
I send it like:
body: JSON.stringify({
address: address,
town: town,
details: details,
appr: apr,
}),
I've tried everything I know how to do to attempt to "make it a JSON" again, but nothing has worked.
1 - Don't forget to add header to fetch
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json' // => this is important
},
body: JSON.stringify(data)
});
2 - Don't forget to add this on express
app.use(bodyParser.json())
Note: If you are using Express v4.16.0 or newer you can use built-in middleware. Thanks to #Dov Rine
app.use(express.json());
3 - req.body will be available as object after this. You should not use JSON.parse(req.body) because body-parser does this for you.
let address = req.body.address;

Easy way to Post HTTPS JSON data (header+body) using Node.js

After reading multiple internet posts related to "JSON POST commands" in NodeJS I'm now totally lost! Have tried to create an easy script to send data to a device Restful API interface using https. Without any luck...
JSON string needs to contain: a Header incl. (Basic)Auth Token & Body
content something similar like:
'{"address":address,"address6":"","comment":"","duids":[],"hostnames":[],"interface":""};
Hoping that someone has a good example available or can point me into right direction again.
You can use in-built module https to make a REST API call, the request signature is as follows:
https.request(url[, options][, callback])
In your case, you can try following code:
var options = {
host: 'host-name',
port: 443,
path: 'api-path',
method: 'POST',
// authentication headers
headers: {
'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
I had the exact same issue just few days ago, and I've ended up creating a super tiny module called json-post.
const jsonPOST = require('json-post');
// or import jsonPOST from 'json-post'
jsonPOST(
'https://whatever:5000/seriously',
// your JSON data as object
{hello: 'world'},
// optionally any extra needed header
{'Authorization': 'Basic ' +
new Buffer(username + ':' + passw).toString('base64')}
).then(
console.info,
console.error
);
The dance is similar to the one shown in the previous reply but it's simplified in various ways. It works well for GitHub OAuth and others services too.
I always use request library whenever I need to do HTTP request in nodejs.
var request = require('request');
request({
method: 'POST',
uri: 'http://myuri.com',
headers: {
'Content-Type' : 'application/json',
'AnotherHeader' : 'anotherValue'
},
json: myjsonobj
}, (err, response, body) => {
// handler here
})
there are other ways of making the request as well like request.post() refer here

Http post request in Angular2 does not pass parameters

I am trying to send a parameter using Angular2 POST to my Python/Tornado back-end which returns a JSON object. The parameters are being sent properly but at the Python side, it is returning 400 POST missing arguments error. I am using Ionic 2/Angular2 in the front-end and Python/Tornado server.
Angular2 code is as follows:
Here content is a variable containing HTML table
let body = JSON.stringify({content: content});
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http.post(url, body, options).map(res => res.json()).subscribe(data => {
console.log(data)
}, error => {
console.log(JSON.stringify(error));
});
Python code is as follows:
def post(self):
print self.request.arguments
print self.get_argument('content')
self.finish(dict(result="ok", data=content))
Here is the error:
[W 160824 06:04:30 web:1493] 400 POST /test (182.69.5.99): Missing argument content
[W 160824 06:04:30 web:1908] 400 POST /test (182.69.5.99) 1.67ms
Your Angular2 code looks reasonable, however your Python code is wrong, because you are treating the request as x-www-form-urlencoded. You have to access the JSON string through the request.body property:
data = tornado.escape.json_decode(self.request.body)
See https://stackoverflow.com/a/28140966/2380400 for an answer to a similar question.
You should maybe try to use something like URLSearchParams() with an URLencoded content type. I don't know much about Tornado but I am using ASP controllers and it works fine.
See Angular2 Documentation : https://angular.io/docs/ts/latest/api/http/index/URLSearchParams-class.html
Watch the following authentication example I am using :
controllerURL: string = "/APIConnexion";
login(aLogin: string, aMdp: string) {
// parameters definition (has to have the same name on the controller)
let params = new URLSearchParams();
params.set("aLogin", aLogin);
params.set("aMdp", aMdp);
// setup http request
let lHttpRequestBody = params.toString();
let lControllerAction: string = "/connexion";
let lControllerFullURL: string = this.controllerURL + lControllerAction;
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
// call http
return this.http.post(lControllerFullURL, lHttpRequestBody, options)
.map((res: any) => {
// data received as JSON
let data = res.json();
// Do something with your data
}
).catch(this.handleError);
}

How to return a JSON object from an Azure Function with Node.js

With Azure Functions, what do you need to do to return a JSON object in the body from a function written in node.js? I can easily return a string, but when I try to return a json object as shown below I appear to have nothing returned.
context.res = {
body: jsonData,
contentType: 'application/json'
};
Based on my recent testing (March 2017). You have to explicitly add content type to response headers to get json back otherwise data shows-up as XML in browser.
"Content-Type":"application/json"
res = {
status: 200, /* Defaults to 200 */
body: {message: "Hello " + (req.query.name || req.body.name)},
headers: {
'Content-Type': 'application/json'
}
};
Full Sample below:
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
context.log(context);
if (req.query.name || (req.body && req.body.name)) {
res = {
// status: 200, /* Defaults to 200 */
body: {message: "Hello " + (req.query.name || req.body.name)},
headers: {
'Content-Type': 'application/json'
}
};
}
else {
res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done(null, res);
};
If your data is a JS object, then this should just work, e.g.
module.exports = function(context, req) {
context.res = {
body: { name: "Azure Functions" }
};
context.done();
};
This will return an application/json response.
If instead you have your data in a json string, you can have:
module.exports = function(context, req) {
context.res = {
body: '{ "name": "Azure Functions" }'
};
context.done();
};
Which will return an application/json response because it sniffs that it is valid json.
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.name || (req.body && req.body.name)) {
context.res = {
// status: 200, /* Defaults to 200 */
body: {"data":"Hello"},
headers: {
'Content-Type': 'application/json'
}
};
}
else {
// res = {
// status: 400,
// body: "Please pass a name on the query string or in the request body"
// };
}
context.done(null,res);
I would like to add one more point. Apart from making the body: a JSON object, the request should also contain proper headers telling server what content type we are interested in. I could see that same Azure function when just invoked via browser using URL gives XML response, but when invoking from script or tools like Postman it gives JSON.
I feel like the answer has been given but it hasn't been clearly presented so I thought I'd answer as well in case it will help anyone coming behind me. I too have created a function that most definitely returns a Javascript object but if I copy and paste the URL in the Azure Function UI and just open a new tab in Chrome and try to view the output, I actually get back an XML document that tells me there's an error (not surprising there's an error as many characters in the Javascript would have blown up the XML). So, as others have mentioned, the key is sending the appropriate headers with your request. When you copy/paste the URL into your browser, the browser is sending a request header that looks similar to this:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
When that happens, you see the XML return as described in this link:
https://github.com/strongloop/strong-remoting/issues/118
In order to get around this problem and see what the data would look like with a JSON request, either use a utility like Postman:
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en
Accept: application/json
Or use a CURL command and pass in the proper Accept header.
As you can see in the screenshot above, when I provided the proper header, I get back the JSON response I would expect.
You can also use JSON.stringify() to make a valid json string out of your js-object:
jsonData = { value: "test" }:
context.res = {
body: JSON.stringify(jsonData)
};

Change User-Agent for XMLHttpRequest in TVML app

I'm working on an Apple TV app using TVMLKit. My app's JavaScript code tries to send an HTTP request to a server using XMLHttpRequest. The server is expecting a specific user agent, so I tried this:
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("User-Agent", "MyApp");
request.send();
The server receives a different User-Agent header:
User-Agent: <Projectname>/1 CFNetwork/758.1.6 Darwin/15.0.0
If I change the header name to something different, it shows up in the request headers. I guess Apple is replacing the User-Agent field right before sending the request. Is there a way to prevent this?
After spending two days on investigating this question I've came to solution with creating native GET and POST methods in swift end exposing them to javascript. This isn't best solution but still I want to share it. Maybe it could help someone.
Here how it works
First we need to install Alamofire library. We will use it for creating requests.
Readme on github has all instructions you need to install it
After installing Alamofire we need to import it in AppDelegate.swift
import Alamofire
Then we need to create function in app controller (AppDelegate.swift) that will expose methods to javascript
func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext)
{
let requests = [String : AnyObject]()
let get: #convention(block) (String, String, [String : String]?) -> Void = { (cId:String, url:String, headers:[String : String]?) in
Alamofire.request(.GET, url, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
let post: #convention(block) (String, String, [String : AnyObject]?, [String : String]?) -> Void = { (cId:String, url:String, parameters:[String : AnyObject]?, headers:[String : String]?) in
Alamofire.request(.POST, url, parameters: parameters, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
jsContext.setObject(requests, forKeyedSubscript: "requests");
jsContext.setObject(unsafeBitCast(get, AnyObject.self), forKeyedSubscript: "nativeGET");
jsContext.setObject(unsafeBitCast(post, AnyObject.self), forKeyedSubscript: "nativePOST");
}
Full code of AppDelegate.swift you can find here
All set! Now we have access to nativeGET and nativePOST functions from javascript.
The last thing is to make requests and retrieve responses. I haven't understand how to make callback executions in swift so I've used jsonp approach using runtime generated functions and passing their names to native functions.
Here how it looks in javascript
export function get(url, headers = {}) {
return new Promise((resolve) => {
const cId = `get${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativeGET(cId, url, headers);
});
}
export function post(url, parameters = {}, headers = {}) {
return new Promise((resolve) => {
const cId = `post${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativePOST(cId, url, parameters, headers);
});
}
The code above is written in ES6 and you'll need to include Promise polifill in your TVJS app.
Now we can make GET and POST requests applying any header we need
post('http://example.com/', {
login: 'xxx',
password: 'yyy'
}, {
'User-Agent': 'My custom User-Agent'
})