Requesting a JSON using Request module (encoding issue) - Node.js - json

Im trying to request a Json file from a server different from mine but i cant set the right encoding.
I tried using HTTP module and failed.
Now im trying to do this using the 'Request' module.
The response i get is encoded to i dont know what. maybe utf 16 and is not readable at all.
Note: The json has some Hebrew chars in it.
I added the following to try and fix it but also failed:
headers: {'Content-Type': 'application/json; charset=utf-8'}
My code:
var http = require('http');
var request = require('request');
var express = require('express');
var app = express();
var url = 'http://www.oref.org.il/WarningMessages/alerts.json?v=1';
app.listen(process.env.PORT || 8080);
app.get('/', function(req,res){
res.send("Red color");
});
// get Alerts from web-service
app.get('/getAlerts', function(req,res){
request({
url: url,
json: true,
headers: {'Content-Type': 'application/json; charset=utf-8'}
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(response.headers) // Print the json response
res.set({
'content-type': 'application/json'
}).send(body);
}
})
});

That API returns a JSON response encoded in UTF-16-LE, so you'll have to tell request to use that encoding instead.
However, since you're trying to query Pikud Haoref's alerts API, check out pikud-haoref-api on npm to do the heavy lifting for you:
https://www.npmjs.com/package/pikud-haoref-api

Related

How to get a value from returned JSON in HTML?

My client side looks like this:
filename="random_filename.docx"
var response = await fetch("https://backend.wl.r.appspot.com/scriptstuff", {
method: 'POST',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ file: filename })
});
var data = response.json();
console.log(data);
and my backend return looks like this
response = jsonify({'prediction': str(prob)})
response.headers['Access-Control-Allow-Origin'] = '*'
return response, 200
I receive a promise with the value of 'prediction', but I'm not sure how to access that or why the current code isn't working.
EDIT: adding await before response.json() works
You can execute a function upon a promise being fulfilled by appending a .then() to the fetch request. If you're already receiving the JSON object then the values can be accessed by data.some_key.
I'm not an expert but first store str(prob) into a variable and then create an object with it. I think jsonify() takes things very literally.

Change the content type in the request headers

I am supposed to send data from an app to the server and the post method from that app is made using content type as application/json but it is plain text. I cannot update the app to change this header now. The current app is working as the data reaches PHP directly and PHP doesn't parse the incoming data which is specified as json.
import express from 'express'
var http = require('http')
const redirectionRoutes = express.Router()
redirectionRoutes.use(function(req, res, next) {
req.rawBody = ''
req.headers['content-type'] = 'text/plain'
req.on('data', function(chunk) {
req.rawBody += chunk
})
req.on('end', function() {
next()
})
})
redirectionRoutes.post(/^\/update_services\/.*$/, function(request, response) {
var data = request.rawBody
var dataLength = data.length
var options = {
hostname: 'localhost',
port: 80,
path: request.path,
method: 'POST',
json: false,
headers: {
'Content-Type': 'text/plain',
'Content-Length': dataLength
}
}
var buffer = ''
var req = http.request(options, function(res) {
res.on('data', function(chunk) {
buffer += chunk
})
res.on('end', function() {
response.send(buffer)
})
})
req.write(data)
req.end()
})
But in nodejs(my application), as the content type is specified as json, the body parser is parsing the data and as it's not json, I am getting an error:
SyntaxError: Unexpected token # in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (../node_modules/body-parser/lib/types/json.js:157:10)
at parse (../node_modules/body-parser/lib/types/json.js:83:15)
at /Users/../node_modules/body-parser/lib/read.js:116:18
at invokeCallback (/Users/../node_modules/body-parser/node_modules/raw-body/index.js:224:16)
at done (/Users/../node_modules/body-parser/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/Users/../node_modules/body-parser/node_modules/raw-body/index.js:273:7)
at emitNone (events.js:105:13)
at IncomingMessage.emit (events.js:207:7)
at endReadableNT (_stream_readable.js:1047:12)
Is there a way in nodejs/body parser to not to parse this incoming json and let is get into the function as plain text.
It is solved!!
I am exporting this module at the end of the app code along with other pages routers. So, the body-parser being called in previous libraries are being called if I didn't use in this particular router.

POST json file using request module

I am planning to translate the curl API call below to node.js though I am still getting an error when doing a POST.
curl -X POST --user user1#customer1:secret http://demo.test.com/controller/actions/38 -F file=#ExportActions.json
Below is initial code using the request - npm module, but the API call still fails.
var requestdata = fs.readFileSync('./ExportActions.json').toString();
var request = require('request');
request.post({
url: 'https://demo.test.com/controller/actions/38',
auth: {
'user': 'user1#customer1',
'pass': 'secret'
},
body: requestdata
}, function(error, response, body){
console.log(body);
});
I am getting the error below every time I run the script:
Could not import Actions: org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Are there any workarounds when posting a JSON file using the npm request module?
Thanks!
You are trying to upload to file by posting it to the body. It looks like the server wants a multi-part upload instead. This might work better
var req = require('request');
request.post({
url: 'https://demo.test.com/controller/actions/38',
auth: {
'user': 'user1#customer1',
'pass': 'secret'
},
}, function(error, response, body){
console.log(body);
});
var form = req.form()
form.append('file', fs.readFileSync('./ExportActions.json'));
You can use Postman client to check this api instead of curl.

POSTing json to express using jQuery

I'm having an issue when sending JSON data from my client to a node server running express.
Here's a simple server that demonstrates my issue:
var express = require('express');
var app = express();
app.configure(function(){
app.use(express.bodyParser());
app.use(app.router);
app.use(express.logger());
});
app.listen(80);
app.post('/', function(req,res){
console.log(req.body);
console.log(req.body.number + 1);
});
This server simply logs all POST data to the console.
If I then paste the following into chrome's development console:
$.post('/', {number:1});
The server prints out:
{ number: '1' }
11
How can I stop the number I'm passing being interpreted as a string?
Is it something to do with the bodyParser middleware I'm using?
Any help appreciated!!
$.post sends url-encoded data, so what is really sent is number=1, which then is parsed as well as it can by bodyParser middleware.
To send json you have to use JSON.stringify({number:1}).
Using $.post unfortunately won't set the appropriate Content-Type header (express will handle it anyway), so it's better to use:
$.ajax({
url: '/',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({number:1})}
)

How do I consume the JSON POST data in an Express application

I'm sending the following JSON string to my server.
(
{
id = 1;
name = foo;
},
{
id = 2;
name = bar;
}
)
On the server I have this.
app.post('/', function(request, response) {
console.log("Got response: " + response.statusCode);
response.on('data', function(chunk) {
queryResponse+=chunk;
console.log('data');
});
response.on('end', function(){
console.log('end');
});
});
When I send the string, it shows that I got a 200 response, but those other two methods never run. Why is that?
I think you're conflating the use of the response object with that of the request.
The response object is for sending the HTTP response back to the calling client, whereas you are wanting to access the body of the request. See this answer which provides some guidance.
If you are using valid JSON and are POSTing it with Content-Type: application/json, then you can use the bodyParser middleware to parse the request body and place the result in request.body of your route.
Update for Express 4.16+
Starting with release 4.16.0, a new express.json() middleware is available.
var express = require('express');
var app = express();
app.use(express.json());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
Updated for Express 4.0 - 4.15
Body parser was split out into its own npm package after v4, requires a separate install npm install body-parser
var express = require('express')
, bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
For earlier versions of Express (< 4)
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
Test along the lines of:
$ curl -d '{"MyKey":"My Value"}' -H "Content-Type: application/json" http://127.0.0.1:3000/
{"MyKey":"My Value"}
For Express v4+
install body-parser from the npm.
$ npm install body-parser
https://www.npmjs.org/package/body-parser#installation
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res, next) {
console.log(req.body) // populated!
next()
})
For those getting an empty object in req.body
I had forgotten to set
headers: {"Content-Type": "application/json"}
in the request. Changing it solved the problem.
#Daniel Thompson mentions that he had forgotten to add {"Content-Type": "application/json"} in the request. He was able to change the request, however, changing requests is not always possible (we are working on the server here).
In my case I needed to force content-type: text/plain to be parsed as json.
If you cannot change the content-type of the request, try using the following code:
app.use(express.json({type: '*/*'}));
Instead of using express.json() globally, I prefer to apply it only where needed, for instance in a POST request:
app.post('/mypost', express.json({type: '*/*'}), (req, res) => {
// echo json
res.json(req.body);
});
const express = require('express');
let app = express();
app.use(express.json());
This app.use(express.json) will now let you read the incoming post JSON object
Sometimes you don't need third party libraries to parse JSON from text.
Sometimes all you need it the following JS command, try it first:
const res_data = JSON.parse(body);
A beginner's mistake...i was using app.use(express.json()); in a local module instead of the main file (entry point).