NodeJs, Express, BodyParse and JSON - json

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.

Related

How to make a video stream http GET request to img html tag with axios?

I have a Django 2.1 backend that have a video stream endpoint and a Vue-Cli3 as my frontend.
The videostream endpoint in my backend is a GET request. To have the streaming working in my client side all i needed was to add:
<img :src="$store.state.domain + 'cameras/video/' + camera.properties.name + '/'" width="240" alt="Camera live Stream">
This works fine but now i have to protect my back-end route for authenticated users only. For this i just need to add an authentication token in the request header.
The problem is, according to Set custom header for the request made from <img/> tag , an img tag doesn't accept header parameters.
So now I'm trying to build a request using axios library and then stream the request result to my HTML img tag.
my Vue method code so far:
loadStream(){
const vm = this
let accessToken = vm.$store.getters.getAccessToken
let streamURL = `${vm.$store.state.domain}/cameras/video/${vm.camera.properties.name}/`
axios.get(streamURL, {headers: {"Authorization": `Bearer ${accessToken}`},
responseType: 'stream',
adapter: httpAdapter}
).then( response =>{
console.log(`success:${response.data}`)
let imgTag = document.createElement('img')
imgTag.src = URL.createObjectURL(response)
imgTag.classList.add('video-modal', 'popup-video')
imgTag.alt = `Camera ${camera.properties.name} liveStream`
imgTag.setAttribute("crossorigin", '')
let streamDiv = document.getElementById('livestream-img')
streamDiv.appendChild(imgTag)
}).catch( error => {
console.log(`error:${response.data}`)
let imgTag = document.createElement('img')
imgTag.alt = `Camera ${camera.properties.name} liveStream`
let streamDiv = document.getElementById('livestream-img')
streamDiv.appendChild(imgTag)
})
}
All i get is this warning:
Warning: The provided value 'stream' is not a valid enum value of type XMLHttpRequestResponseType.
Also my request never ends. Promise will never hit .then() or .catch() because it's streaming. Seems like responseType isn't working properly. am i missing something?
This is my django backend endpoint:
class CameraVideoStreamingView(APIView):
def get(self, request, name):
cam = Camera.objects.get(name=name)
return StreamingHttpResponse(cam.serve_web_stream(),
content_type="multipart/x-mixed-replace;boundary=frame")
I would recommend sending some sort of auth token in the video's query params, and to handle this, implementing a custom Token Authentication Class which gets the token from a query param rather than the headers. You'd then have to update the authentication_classes property of your view with your new authentication class.

Unable to access data inside a string (i.e. [ object Object ]) that was originally sent as a JSON object

I'm using axios to send a JSON object as a parameter to my api. Before it post request is fired, my data starts of as a JSON object. On the server side, when I console.log(req.params) the data is returned as such
[object Object]
When I used typeof, it returned a string. So then I went to use JSON.parse(). However, when I used that, it returned an error as such
SyntaxError: Unexpected token o in JSON at position 1
I looked for solutions, but nothing I tried seemed to work. Now I'm thinking I'm sending the data to the server incorrectly.
Here's my post request using axios:
createMedia: async function(mediaData) {
console.log("SAVING MEDIA OBJECT");
console.log(typeof mediaData)
let json = await axios.post(`http://localhost:3001/api/media/new/${mediaData}`)
return json;
}
Any thoughts on how I can solve this?
You need to update your code using axios to provide the mediaData in the body of the request instead of the URL:
createMedia: async function(mediaData) {
console.log("SAVING MEDIA OBJECT");
console.log(typeof mediaData)
let json = await axios.post(`http://localhost:3001/api/media/new/`, mediaData)
return json;
}
In the backend (assuming you're using express here), you need to configure your application to use bodyParser:
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
And then in your controller update your console.log(req.params) to console.log(req.body); then restart your node server

Node / Express parsed JSON POST is not valid JSON

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.

Node.js: How to exchange a JSON object [duplicate]

This question already has answers here:
How to access POST form fields in Express
(24 answers)
Closed 6 years ago.
My purpose is to send a JSON object from the client-side to the server. So taking into account the following details of the client:
<script>
var onClickFunct = function() {
trial1.send({
"test": $("#input_test").val(),
});
}
</script>
Where input_test is the name of my tag in the html page.
And where trial1 is implemented with the following code:
var trial1 = {
//notifica al server una nuova registrazione
send: function(data){
$.getJSON('/tst',data);
}
}
My Server can't see the object; infact if I print req.params it shows me "undefined".
app.get('/tst',function(req){
console.log(req.params);
});
My index.html reuire the following script <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
While the server require only express
Try changing:
app.get('/tst',function(req){
console.log(req.params);
});
to:
app.get('/tst',function(req){
console.log(req.query);
});
The req.params is for parameters in your routes, like:
app.get('/test/:name', function (req, res) {
console.log(req.params);
});
When you access /test/abc then the req.params.name will be "abc".
The $.getJSON() sends the data as query parameters, see:
http://api.jquery.com/jquery.getjson/
And for the query parameters you use res.query.
If it was a POST request and you wanted to access parameters passed in the request body then you would user req.body (but you would need to use a bodyParser middleware).
Remember to use GET only for reading operations, where in the query parameters you specify what you want to get or in what form, what order etc.
If you pass data to store in a database or something like that then use POST or PUT for that and pass the data in the request body (which can be JSON).
$ npm install --save body-parser
and then:
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
your endpoint should look like this:
app.post('/tst',function(req){
console.log(req.body);
});
then use Jquery Post:
$.post('/tst',data);
body parser install example taken from here:
How to retrieve POST query parameters?
hope it helps :)

mocha - send json to post express route

I'm trying to send some json data to my '/sign_up' route in mocha test.
request = require 'supertest'
express = require 'express'
app = express()
Authentication = require("#{specDir}/../apps/authentication/routes")
authenticate = new Authentication app
Factory = require "#{specDir}/factories/user"
user = Factory.build 'user'
it 'creates an account', (done) ->
request(app).post('/sign_up').set('Accept', 'application/json').send(user).end (err, res) ->
expect(res.statusCode).to.equal 200
done()
However req.body in the callback function is undefined. Below I've shown a snippet of my route callback
#app.post '/sign_up', (req, res) ->
res.format
html: -> res.status(406).send 'invalid Content-Type'
json: ->
console.log req.body
res.status(200).send status: 'ok'
Probably I'm missing some small detail, but can't see what.. any ideas?
P.S. I'm well aware of that the tests pass and it does what it should, but before I move on to write more tests I gotta know how to send some data.
You're missing a body parser, add app.use(express.json()) in your code somewhere.