Skip to content

Commit cd75e97

Browse files
committed
Merge pull request #33 from digitalsadhu/fix/406_not_acceptable
Fix 406 Not Acceptable
2 parents 2e6416f + 77e3c4b commit cd75e97

File tree

4 files changed

+105
-27
lines changed

4 files changed

+105
-27
lines changed

lib/headers.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
'use strict';
2-
3-
var bodyParser = require('body-parser');
2+
var is = require('type-is');
43

54
module.exports = function (app, options) {
65

7-
//registered at the beginning of the routes phase due to usage of
8-
//express app.use instead of app.middleware.
9-
//We need to do this as bodyParser doesn't support
10-
//JSON APIs application/vnd.api+json format by default
11-
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
6+
app.remotes().before('**', function (ctx, next) {
7+
if (ctx.req.accepts('application/vnd.api+json')) {
8+
ctx.req.headers.accept = 'application/json';
9+
}
10+
next();
11+
});
12+
13+
app.remotes().options.rest = {
14+
//turn off strong remotings error handler so we can handle ourselves in error.js
15+
handleErrors: false,
16+
17+
//extend support for application/vnd.api+json
18+
supportedTypes: ['json', 'application/javascript', 'text/javascript', 'application/vnd.api+json']
19+
};
20+
21+
//extend rest body parser to also parse application/vnd.api+json
22+
app.remotes().options.json = {
23+
strict: false,
24+
type: function (req) {
25+
//if Content-Type is any of the following, then parse otherwise don't
26+
return !!is(req, ['json', 'application/json', 'application/vnd.api+json']);
27+
}
28+
};
1229
};

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "JSONAPI support for loopback",
55
"main": "lib/index.js",
66
"scripts": {
7-
"test": "npm run lint && mocha --reporter=spec ./test/**/*",
7+
"test": "npm run lint && mocha --reporter=spec ./test/**/*.test.js",
88
"lint": "eslint ."
99
},
1010
"repository": {
@@ -28,7 +28,9 @@
2828
"body-parser": "^1.14.1",
2929
"debug": "^2.2.0",
3030
"inflection": "^1.7.2",
31-
"lodash": "^3.10.1"
31+
"lodash": "^3.10.1",
32+
"loopback": "^2.22.2",
33+
"type-is": "^1.6.9"
3234
},
3335
"devDependencies": {
3436
"babel-eslint": "^4.1.3",

test/create.test.js

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
var request = require('supertest');
22
var loopback = require('loopback');
33
var expect = require('chai').expect;
4+
var query = require('./util/query');
45
var JSONAPIComponent = require('../');
56
var app;
67
var Post;
@@ -17,30 +18,56 @@ describe('loopback json api component create method', function () {
1718
});
1819
app.model(Post);
1920
app.use(loopback.rest());
20-
JSONAPIComponent(app);
21+
JSONAPIComponent(app, { restApiRoot: '' });
2122
});
2223

2324
describe('headers', function () {
25+
it('POST /models should be created when Accept header is set to application/vnd.api+json', function (done) {
26+
request(app).post('/posts')
27+
.send({
28+
data: {
29+
type: 'posts',
30+
attributes: {
31+
title: 'my post',
32+
content: 'my post content'
33+
}
34+
}
35+
})
36+
.set('Accept', 'application/vnd.api+json')
37+
.set('Content-Type', 'application/json')
38+
.expect(201)
39+
.end(done);
40+
});
2441
it('POST /models should have the JSON API Content-Type header set on response', function (done) {
25-
//TODO: superagent/supertest breaks when trying to use JSON API Content-Type header
42+
var data = {
43+
data: {
44+
type: 'posts',
45+
attributes: {
46+
title: 'my post',
47+
content: 'my post content'
48+
}
49+
}
50+
};
51+
52+
var options = {
53+
headers: {
54+
'Accept': 'application/vnd.api+json',
55+
'Content-Type': 'application/vnd.api+json'
56+
}
57+
};
58+
59+
//use http module via util to make this post to check headers are working since
60+
//superagent/supertest breaks when trying to use JSON API Content-Type header
2661
//waiting on a fix
2762
//see https://github.com/visionmedia/superagent/issues/753
28-
//using Content-Type: application/json in the mean time.
29-
//Have tested correct header using curl and all is well
30-
// request(app).post('/posts')
31-
// .send({
32-
// data: {
33-
// type: 'posts',
34-
// attributes: {
35-
// title: 'my post',
36-
// content: 'my post content'
37-
// }
38-
// }
39-
// })
40-
// .set('Content-Type', 'application/vnd.api+json')
41-
// .expect('Content-Type', 'application/vnd.api+json; charset=utf-8')
42-
// .end(done);
43-
done();
63+
query(app).post('/posts', data, options, function (err, res) {
64+
if (err) console.log(err);
65+
expect(res.headers['content-type']).to.match(/application\/vnd\.api\+json/);
66+
expect(res.statusCode).to.equal(201);
67+
expect(res.body).to.have.all.keys('data');
68+
expect(res.body.data).to.have.all.keys('type', 'id', 'links', 'attributes');
69+
done();
70+
});
4471
});
4572

4673
it('POST /models should have the Location header set on response', function (done) {

test/util/query.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var http = require('http');
2+
3+
module.exports = function (app) {
4+
return {
5+
post: function (path, data, options, cb) {
6+
var s = app.listen(function () {
7+
var req = http.request({
8+
port: s.address().port,
9+
path: path,
10+
headers: options.headers || {},
11+
method: 'POST'
12+
}, function (res) {
13+
res.setEncoding('utf8');
14+
res.rawData = '';
15+
res.on('data', function (chunk) {
16+
res.rawData += chunk;
17+
});
18+
res.on('end', function () {
19+
res.body = JSON.parse(res.rawData);
20+
cb(null, res);
21+
});
22+
});
23+
req.on('error', function (err) {
24+
cb(err);
25+
});
26+
var postData = JSON.stringify(data || {});
27+
req.write(postData);
28+
req.end();
29+
});
30+
}
31+
};
32+
};

0 commit comments

Comments
 (0)