Q:

Express.js response status code with jsonp payload

I have a MEAN-stack backend where I'd like to respond with 
return res.status(400).jsonp({
  message: 'Parsing failed.',
  code: '123'
});

When an angular app uses this JSONP endpoint and encounters this particular error, it receives a 400 but without its payload. When I change the status to 200/300 it comes through fine, with 400/500 it doesn't.
On other routes (POST) I can respond with a 4** status code and payload without any issues.
return res.status(400).send({
  message: 'Codes do not match.',
  code: '234'
});

Any Idea what I'm overlooking?

A:

It looks like this is a browser-thing: when a remote script is requested (as is the case with JSONP requests), and the response returns a 400 (or higher) HTTP status, any code that may still get returned in the response body isn't evaluated (this actually makes perfect sense).
Angular will only know that the response has been sent, and that it had an error status, but since the callback wasn't called, there is no payload data to pass to your callback.
I tested a standalone HTML page:
<script>
function foo(data) { alert('foo') }
</script>
<script src="/endpoint?callback=foo"></script>

And the following Express handler:
app.get('/endpoint', (req, res) => {
  return res.status(400).jsonp({ hello : 'world' });
});

A 400 status doesn't trigger the alert, a 200 status does. It also doesn't work if the handler returns plain JS (acting like a simple .js file that gets loaded with a <script src=...>).
So for JSONP requests, you should stick to 200 responses and convey any errors in some other way (like setting an error property in the response object).

