Koa: Empty response if result is null

Created on 9 Jun 2017  Â·  20Comments  Â·  Source: koajs/koa

Why the following returns an empty response? null is a valid json value.

const config = require('./package.json');

const http = require('http');
const koa = require('koa');
const cors = require('kcors');
const compress = require('koa-compress')
const noTrailingSlash = require('koa-no-trailing-slash');
const json = require('koa-json');
const body = require('koa-body');
const send = require('koa-send');
const router = require('koa-router')();

const app = new koa();

app.use(cors());
app.use(compress());
app.use(noTrailingSlash());
app.use(json({ pretty: true, spaces: 4 }));
app.use(body({ formLimit: '5mb', jsonLimit: '5mb', strict: false, multipart: true }));

app.use(async (ctx, next) => {
    try {
        await next();
    }
    catch(error) {
        ctx.status = 400;
        ctx.body = error.message || error;
    }
});

router.all('/ciao', async ctx => {
    ctx.body = null;
});

app.use(router.routes());
http.createServer(app.callback()).listen(8080);

Reponse is empty:

macbook:react-app damiano$ curl -v localhost:8080/ciao
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /ciao HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
> 
< HTTP/1.1 204 No Content
< Vary: Origin, Accept-Encoding
< Date: Fri, 09 Jun 2017 14:17:57 GMT
< Connection: keep-alive
< 
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
macbook:react-app damiano$ 
PR Welcomed help wanted version-major

Most helpful comment

Below is my case:

request(options, function(error, response, body){
    //...
    ctx.status = response.statusCode; //500
    ctx.body = body; //undefined
    console.log(ctx.status); //204, it confused me
    //...
});

if ctx.body == null and ctx.status is 2XX or not set, we can set ctx.status to 204, otherwise it's better do nothing.

All 20 comments

Nobody experiencing this?! :|

@fengmk2 that's not good: what about an API endpoint returning "null" as data?
Shouldn't koa allow some kind of config about it? @tj @jonathanong
null is a valid json value but returning a 204 will trigger problems front-end side.
We cannot assume everybody is enclosing result in an object.

Just my opinion but personally I most people expect an object or array with json these days, apis returning primitives is a little weird, even if it's technically fine. At very least something like { "user": null } so that the null is self-describing

@tj I agree, but in some cases it may be needed and returning a 204 could be unexpected.
Do you think koa team will consider this or will this be ignored assuming everybody must envelop
the data?
Because in the latter I'll just close the issue (even if I don't agree much) :)

I don't have a super strong opinion there, I guess maybe ideally the client requesting stuff treats 204 as null but it's definitely easier to assume it's always JSON, though that's sort of the same weirdness as doing { "error": MESSAGE } instead of a 4xx or 5xx with MESSAGE as the body which is maybe a bit more correct

it makes way more sense to me to return 204 or an error instead of null. i find anything but an array or object being returned from an API weird.

is there absolutely no way you can change the FE code? this would be a breaking change

@jonathanong if this would cause a breaking change then let's just leave it like this but I'm not sure pretending "always enveloped results" is right.

My 2 cent: could koa check if request header is application/json and if so just encode null instead of returning 204 empty content? I think it's the correct behaviour.

what do you think about it @tj? Could koa check if request header is application/json and if so just encode null instead of returning 204 empty content? I think it's the correct behaviour

Sounds reasonable, my main fear there is that it gets (even more) magical when it starts doing multiple things. I kind of agree that array/objects are the way to go, even if technically less correct

@tj @jonathanong please let me know on this: if you think this is never going to be implemented I'll just close the issue.
Thanks guys for your efforts!

@tj @jonathanong time to close this? Did you take time to think if it's worthful or not?

Could koa check if request header is application/json and if so just encode null instead of returning 204 empty content? I think it's the correct behaviour

that sounds like a good behavior to have. if a content type is set, then the developer intends to set a body.

my only concern is whether this would be a breaking change, which it probably will be for a few people

Below is my case:

request(options, function(error, response, body){
    //...
    ctx.status = response.statusCode; //500
    ctx.body = body; //undefined
    console.log(ctx.status); //204, it confused me
    //...
});

if ctx.body == null and ctx.status is 2XX or not set, we can set ctx.status to 204, otherwise it's better do nothing.

After more than 2 years here I am again xD
I'm trying to return in the json body null but I see koa returning 204.
@lichangwei how did you solve this?

I'm willing to provide a PR. I saw this in the 3.0 roadmap initial issue #1114 as a breaking change.
Instead of breaking the current behaviour I'd suggest that to be a config option one can set when creating the koa app. That way it would not break old clients and clients that need it can enabled it via emptyBodyAs204=false (default is true). Coming up with a good config name was difficult (as naming often is) then I thought maybe one could register

OK , If ctx.body = null equals 204

middleware: 

( async (ctx) => {

ctx.body = null;
ctx.body = 'have result'
return ctx;

})

it still return 204 , anyone have this issue ?

@samtsai15 I handle it something like this:

const statuses = require('statuses');

// ...

app.use(async (ctx, next) => {
  await next();

  if (ctx.fresh) {
    ctx.status = 304;
    ctx.body = null;
  } else if (ctx.length && statuses.empty[ctx.status]) {
    ctx.status = 200;
  }
});

@tj are you willing to solve this issue? We have some microservices in GraphQL and null is a perfect return value when it fits the contract. Im now wrapping Koa results back myself, so not a real dealbreaker but it's weird to see when explicitly returning null it magically disappears, and even worse gets another statusCode because of it.

Also contractually now it doesn't fit, normally with service i do and the contract is then consumed in the other mesh/gateway which now also requires manual work :(. I really liked the performance setup many years ago, but this really surprises me.

@maapteh after 4 years I gave up and came up with a https://www.npmjs.com/package/koa-better-json

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rainesinternationaldev picture rainesinternationaldev  Â·  5Comments

tracker1 picture tracker1  Â·  3Comments

rally25rs picture rally25rs  Â·  4Comments

felixfbecker picture felixfbecker  Â·  5Comments

ke1Del picture ke1Del  Â·  3Comments