I am making a JSON POST request using Pure Javascript XMLHttpRequest, however Express appears to wrap the received JSON in an additional object, how can I prevent this ?
I am using the bodyParser:
app.use(bodyParser.json({limit: '50mb'}));
This is the client sending the JSON data:
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://xxx.my.net/",true);
// This header MUST be present for POST requests.
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Accept", "application/json, text/javascript");
xhr.send(JSON.stringify({"hxx":1}));
And this is Nodejs / Express middleware:
app.use(function(req, res, next){
fn.console.log(req.body);
})
This is the console.log output:
{ '{"hxx":1}': '' }
I know that I can parse the body with:
console.log(JSON.parse(Object.keys(req.body)[0]))
but I would prefer not to have to do this !
IMPORTANT Note
I have already tried using content type = "application/json" but when I do this the request becomes a GET instead of a POST, and Unless I state "application/x-www-form-urlencoded" the request is automatically converted by the browser from a POST to a GET.
Related
I am trying to post data via an API interface.
I have checked the JSON of the data with JSON formatter and tested the API post in ReqBin and they work fine but when I execute it in App Script I get the same error, seemingly ignoring the attributes I put in the options variable.
Error is
{"code":"not_acceptable","message":"I can only talk JSON. Please set 'Accept' and 'Content-Type' to 'application/json' in your http request header."}
Note: I have tried sending just the data as the payload without json.stringify'ing it as it is formatted as JSON to start with.
In all cases it executes, but comes back 406
Is there another way to add 'Accept':"application/json" into the header??
My Code
function exportNation()
{
// Make a POST request with a JSON payload.
var data = {
"person":
{
"email":"mikenizzckelisaweiner#tv.com",
"last_name":"Bozzrovowski",
"first_name":"Edwzzard",
"tags":"Imported Data,Volunteer,Sign Request"
}
};
var options = {
"method":"POST",
"Content-Type":"application/json",
'Accept':"application/json",
'muteHttpExceptions':true,
'payload':JSON.stringify(data)
};
var response = UrlFetchApp.fetch('https://xyz.xyz.com/api/v1/people?
access_token=5604da84fXXXXXXXXXXXXXXXX42da1ea',options );
}
Any help would be greatly appreciated!
Additional HTTP headers need to be sent as a headers object.
See: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#advanced-parameters
var options = {
"method":"POST",
"contentType":"application/json",
"headers": {'Accept':"application/json"},
I use MongoDB as the back-end database for my node/Express application. To summarize the problem I am facing, I don't know how to set up the body-parser configuration in my Express app, because the server side application is not receiving the full JSON posted by the client application (also a node.js app). For the most part, the client is sending JSON in the request body to RESTful endpoints. The exception being a single case where a file needs to be uploaded and since that is a multipart body, I am using request and form-data to build that type of request and using multer on the server side to process the multipart request, since body-parser does not process such requests.
On the server-side (Express), I have the following configuration of the Express app:
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
On the node client, I am using the following code to build up a JSON-style JavaScript object and post it to a RESTful endpoint:
I am having difficulty composing the request on the client side, with node-request:
// class is a JavaScript/JSON object within scope of this code
let req = request.post({
//headers: { 'Content-Type': 'application/json' },
url: 'http://localhost:3000/classes',
//form: class
form: JSON.stringify(class)
}, function (err, resp, body) {
if (err) {
throw err;
}
});
Note that I attempted multiple versions of the above code by explicitly specifying the content type as application/JSON, as well as using JSON.stringify to convert the JavaScript object into a JSON string. The MongoDB collection (class) stores the following type of document, which contains foreign keys to two other collections (subject and student):
{
"_id" : ObjectId("57758f15f68da08c254ebee1"),
"name" : "Grade 5 - Section A",
"scores" : [{
"studentId" : ObjectId("5776bd36ffc8227405d364d2"),
"performance": [{
"subjectId" : ObjectId("577694ecbf6f3a781759c54a"),
"score" : 86,
"maximum" : 100,
"grade" : "B+"
}]
}]
}
In the server logs, I see the following error:
Tue, 05 Jul 2016 04:34:46 GMT classReportApp:routes:classes class received from client: { _id: 577b38e65967097c25876764, scores: [] }
RangeError: Invalid status code: 0
at ServerResponse.writeHead (_http_server.js:192:11)
at ServerResponse.writeHead (C:\Development\classReportApp\node_modules\morgan\node_modules\on-headers\index.js:55:19)
at ServerResponse._implicitHeader (_http_server.js:157:8)
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:566:10)
at ServerResponse.send (C:\Development\classReportApp\node_modules\express\lib\response.js:205:10)
at ServerResponse.json (C:\Development\classReportApp\node_modules\express\lib\response.js:250:15)
at C:\Development\classReportApp\server-process\app.js:80:26
at Layer.handle_error (C:\Development\classReportApp\node_modules\express\lib\router\layer.js:71:5)
at trim_prefix (C:\Development\classReportApp\node_modules\express\lib\router\index.js:310:13)
at C:\Development\classReportApp\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\Development\classReportApp\node_modules\express\lib\router\index.js:330:12)
which is strange because scores array of sub-documents is empty (scores: []), whereas on the client side, I am sending a non-empty array with some students' performances elements in it.
Have I violated the right way to post JSON to Express apps? How do I fix this?
Edited: 7/5/2016
I changed the body parser middle-ware configuration to use extended: true instead.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
The node.js is still using the node-request module to compose and send the POST request, using the following code:
let req = request({
url: 'http://localhost:3000/classes',
method: 'POST',
json: class
}, function (err, resp, body) {
if (err) {
throw err;
}
else {
// process response
}
});
This works now, but what confuses me is that since the content type is application/json, how does the bodyParser.urlencoded({ extended: true }) (or false) matter?
Issue is with form: JSON.stringify(class) in your first request. form takes url encoded form input, stringified json won't work. check content-type header (application/x-www-form-urlencoded)
json: class in your 2nd snippet works as this handles json data and sets correct content type header correctly.
Try .toJSON() method over class before sending.
I'm trying to implement a simple server using Express 4.0 and parsing messages with BodyParser. To test my server I use Postman.
Using x-www-form-urlencoded as message mode it works with no problem but changing messages with JSON I can't parte data using BodyParse.
Here is my code:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
var router = express.Router()
router.get('/', function (req, res){
res.json({message: "nd..."})
})
var sendRoute = router.route('/msg')
sendRoute.post(function(req, res){
// HERE IS THE PROBLEM******************************
// It works with urlencoded request but not with JSON
var dataparam1 = req.body.param1
var dataparam2 = req.body.param2
****************************************************
.
.
.
})
and let's say this is the JSON data I get form the request:
[{"param1":"This is the param1",
"param2":"This is the param2"
}]
What's wrong with my code? how can I get params sent with JSON format?
If your request body is sent as a JSON string, then you must tell your app that via a content-type header.
In Postman, click the Headers button, next to the drop-down to select the method and the URL params button. (Top right)
A table will expand, fill in Content-Type in the left field and application/json in the right field.
Submit the request.
bodyParser can handle multiple types of data, but it must know what format you're submitting. It will not attempt to guess the data type.
The drop-down menu (according to your comment, it's set to 'JSON' at the moment) just above the textarea where you fill in the request body only toggles syntax highlighting, it does not set the Content-Type header for you.
I'm trying to make a server-side API call using a RESTful protocol with a JSON response. I've read up on both the API documentation and this SO post.
The API that I'm trying to pull from tracks busses and returns data in a JSON output. I'm confused on how to make a HTTP GET request with all parameters and options in the actual URL. The API and it's response can even be accessed through a browser or using the 'curl' command. http://developer.cumtd.com/api/v2.2/json/GetStop?key=d99803c970a04223998cabd90a741633&stop_id=it
How do I write Node server-side code to make GET requests to a resource with options in the URL and interpret the JSON response?
request is now deprecated. It is recommended you use an alternative:
native HTTP/S, const https = require('https');
node-fetch
axios
got
superagent
Stats comparision
Some code examples
Original answer:
The request module makes this really easy. Install request into your package from npm, and then you can make a get request.
var request = require("request")
var url = "http://developer.cumtd.com/api/v2.2/json/GetStop?" +
"key=d99803c970a04223998cabd90a741633" +
"&stop_id=it"
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the json response
}
})
You can find documentation for request on npm: https://npmjs.org/package/request
Updated: I'm posting HTML FORM data but expecting to receive JSON data. I am not trying to POST JSON data.
I am trying to get a JSON response back from doing a HTML FORM POST request. I have successfully received a JSON back when using a simple HTML FORM POST request (i.e. not AJAX). My JSON response from the HTML FORM POST is this:
{"success":true,"data":1234567}
The problem occurs when I try to handle the request and response with jQuery's .ajax().
$.ajax({
type: "POST",
url: URL,
data: data1,
dataType: "json",
success: function(data, textStatus, jqXHR) {
alert ("success");
},
error: function(xhr, status, error) {
alert ("Error: " + error);
}
});
After running the above code and debugging in Firebug, it appears that the POST request is going through, but something is going wrong on the handling of the response. Firebug tells me the following regarding the HTTP response from the POST request:
Response Headers
Cache-Control private
Content-Length 31
Content-Type application/json; charset=utf-8
...
So it appears that the 31 bytes of data is being sent. However, when debugging the actual Javascript, the error function gets called and the xhr object is this:
Object { readyState=0, status=0, statusText="error"}
I know the jQuery.ajax() document states that "In jQuery 1.4 the JSON data is parsed in a strict manner; any malformed JSON is rejected and a parse error is thrown." However, I believe my JSON is valid as I have checked it at jsonlint.com.
What else could be going wrong?
It looks to me like you are getting a server error. I would check the status code of the response and fix whatever is causing the request to fail on the server.
your getting an error because data1 is not formatted in json, so when it receives the data it gets a parse error. data1 needs to be formatted:
data1={"apikey":apikey,
"firstname":fName
}
I was having the same problem. It seems that this is an issue with Cross Domain.
Finding this SO answer: https://stackoverflow.com/a/7605563/154513
helped me.
Some times Jquery return Internal Error 500 for currectly data.
There is example for read the same json data withour error
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://reqres.in/api/products/3", true);
xhr.onload = function(){
console.log(xhr.responseText);
};
xhr.send();