How to use Mocha and Supertest to send malformed JSON? - json

I have the current test I want to run:
var request = require('supertest');
it('should be malformed json', function(done) {
request(config.base)
.post('/authenticate')
.send('{"project":{"description":\'test"}}')
.set('Authorization', 'Bearer ' + config.token)
.expect('Content-Type', /json/)
.expect(status.BAD_REQUEST);
});
However, supertest seems to validate it, and it just sends '{}' in the body. Any idea how I can get around this?

You are passing a string to the send method, so it will be sent to the server as is (you could write anything there!).
Once the server receives the string, it parses the JSON and it finds the error. What happens next depend on how the server application is configured (or the framework you're using). It is possible that in this case the server just ignores any malformed JSON input, and thus it's like you called /authenticate without any input.
TL;DR: send() just sends any string you pass it. If you want to raise an error, you need to modify the server, and not the test suite.
EDIT
I did some more digging. First of all, as I said before, send() indeed leaves strings as is. You can see it from the code: https://github.com/visionmedia/superagent/blob/master/lib/client.js#L778
Thus said, you did not tell the server that the request body was in JSON format, so what you're saying is interpreted as "text/plain" and not parsed. To pass a manual JSON string to send() you also need to specify the content-type of the request:
request(config.base)
.post('/authenticate')
.type('json')
.send('{"project":{"description":\'test"}}')
//...

Related

Node.js express res.json behavior

I have been working on one of my projects using node and ng4
when I came across using res.json to send an array back to Angular 4 front end, like res.json(arrayResult). Surprisingly, I cannot use JSON.parse(arrayResult) after Angular receives it because it throws an error saying unexpected end of input. I however can access all the data through result[i], just like any normal array.
I don't quite understand why res.json() does not send my array as a string to the front end. Is there any internal conversion involved? Why I could access the content through index without even parsing it or doing any conversion with it?
The server indeed send your json data as a string. Additionally to the string, the server passes Content-Type header to your client which tells your client what kind of data you received.
So if the Content-Type was text/html your client would think that he received an HTML file.
In your case, res.json using Content-Type: application/json which tells the client that the string that he got is actually a json object, so no need for you to use JSON.parse.
You can see the Content-Type under the response headers property.

Can I intercept an incoming request in Express.js before it's handled?

I'm running Node.js with Express.js and everything works perfectly until someone sends invalid JSON with content-type text/json and then my server responds with a 400.
Now, I realize this is "correct" but I'd like to intercept the incoming data and see if I can fix the data by replacing all the new lines (\n \r) with the string representations thereof ("\n", "\r") because that appears to be the problem with the incoming request. Specifically, the json has instances that look like
{"foo":"bar
and so forth"}
Where the line breaks are some combination of \n and \r.
I'm not seeing where I can look-at/massage the incoming request data before it gets bounced as a 400.
This is precisely what middleware is all about. Just insert a middleware handler as the very first handler (before anything else that might look at the request data such as app.use(BodyParser.json())) and it gets first crack at every request and it can modify the request object as it wants to before any of your other handlers see the data.
// make this the first request handler for Express
app.use(function(req, res, next) {
// examine req here and make any changes as desired
// when done, call next()
next();
});
If it's a GET request, the data is all there. If it's a POST request, you will you have to actually read the request stream to get the data before you can process it. This probably means you have to actually replace bodyParser.json() with your own unless you replace the request stream with a new stream.

Are JSON APIs supposed to return strings or JavaScript Objects?

Let's say I ask Mailchimp for subscriber data, and they send back an http request with JSON in the body. Should I be able to go:
var thingy = body.property;
Or should I have to go:
var object = JSON.parse(body);
var thingy = object.property;
?
Also, does the node.js body parse parse JSON for me?
JSON is sent over the wire from the server as a string. That's what JSON is - a string format.
Whether or not it arrives at your code as a string or as already parsed Javascript object depends entirely upon the code you are using to make the http request and perhaps what headers the server sets and what auto-detection the code doing the Ajax call makes.
If the response header sets the type to json, then some code making the request will automatically parse it for you into Javscript. Other code will leave that to the caller to do. If the server does not set the proper headers, then some code will auto-detect it as JSON and parse it and other code will not.
So ... bottom line. It depends entirely upon what the server is doing in its response and what code is being use to make the request. You can very easily just do a console.log(body) and see whether you have a JSON string or an already parsed Javascript object.
If you really weren't sure what behavior you would get, you can test the type and act accordingly (though a given server and calling code should be consistent so you shouldn't have to vary your behavior) once you test how it behaves.
if (typeof body === "string") {
body = JSON.parse(body);
}
Depends on the API, usually you get the response header Content-type: application/json. If that is the case there's probably no need to parse the response as most of the clients will understand that it's a json object and parse it for you. Anyhow, not all clients will do this automatically.

%40 is not getting decoded to # in Jmeter

I'm trying Jmeter tool for load testing where i'm feeding the data through a csv file which has all the emails and passwords for login request. But while passing the parameter, Jmeter is encoding '#' sign with '%40' and if i put %40 in place of # in my csv, its not getting decoded to # in Jmeter. For other special characters, the encoding and decoding is happening properly. Please help.
It should be totally expected.
If you're logging in via GET request %40 is correct way of encoding # symbol.
If you're sending a POST request, JMeter should automatically send # symbol (at least my JMeter 2.10 does)
You might wish to try one of following:
Add View Results Tree listener, switch to HTTP tab and see what's actually being sent.
Make sure that Encode? box is unchecked for email parameter
Explicitly tell JMeter to decode email via __urldecode() function
Use a Beanshell Pre Processor to properly encode/decode your email
import java.net.URLDecoder;
import java.net.URLEncoder;
String email = "someone#example.com";
String encoded = URLEncoder.encode(email, "UTF-8");
String decoded = URLDecoder.decode(encoded, "UTF-8");
This is coming when we do via Parameters,
If we do using "Body Data" that would work fine.
I used this way.
{"password":"${password}","emailId":"${emailId}"}
For the HTTP Request, Change the Client implementation to Java
Select the Advanced tab from the HTTP Request
In Client Implementation > Choose Java in Implementation

Detect malformed/invalid JSON in an AngularJS $http.post() call

As can be seen in AngularJS's source, any $http.post request that returns an HTTP code in the 200-299 range will trigger the success() callback even if the response contains invalid data (like for example invalid JSON).
I'm specifically setting my call's responseType: 'json' and even then the success callback is fired when something else comes back. This is especially annoying in the development server where PHP's display_errors setting is turned on. When something goes wrong server-side and PHP outputs an error message the AngularJS app doesn't detect this and continues happily.
Is there a way to prevent this? I mean, to make the AngularJS app fire the error() callback when the response data is invalid JSON?
Thanks
so your PHP server responds with a 200 error code even on an error? Not knowing PHP, this feels like a server configuration problem to me. I'd expect a 500 error with a payload. That being said, there are two things that I can think of offhand.
$http includes transformResponse handlers you can set up to inspect the response for problems.
$http also includes the concept of "interceptors" which allow you to pick up the response payload and do something with it. You could use an interceptor to "reject" the response.
More information on transformResponse and "interceptors" in the $http documentation:
http://docs.angularjs.org/api/ng.$http