Open travi opened 9 years ago
Try setting absolute: true
in the halacious plugin registration options. I'm curious how you are using rep.factory. Can you post a code example?
First, a little context. I've been slowly building out a simple example api to get my head around the details of HAL as compared to more traditional HATEOAS implementations. There may be better ways to accomplish what I'm after, but I was trying to start simple and get something working in a way that I am more familiar with.
I am trying to get the self
links generated and attached to the items in a list. I saw the example in your readme about listing items in the _embedded
section, but it seems to me like the list in the common case is the primary content. Therefore, I'm trying to keep it as a top level attribute in the response rather than under _embedded
, which is for replacement of links in order to make things less chatty. I haven't seen another example of using _embedded
in the particular way that is shown in your readme elsewhere, but would love it if you have a better reference that you could point me to than I've been finding.
Anyway, this is what I landed on to get my approach at least working as I continue to explore what is 'right':
plugins: {
hal: {
api: 'users',
prepare: function (rep, next) {
rep.entity.users.forEach(function (user, index) {
rep.entity.users[index] = rep.factory.create(user, '/users/' + user.id);
});
next();
}
}
}
You can find it in context here, if that would be more helpful. The output can be seen here. I do already have the absolute:true
flag set here and it is working in other places. Even if there is a better way to accomplish what I'm trying to do here, it seemed like the factory should still honor the absolute
flag in this case, so I wanted to pass the observation along.
Lastly, also notice that the absolute links show http
for the protocol even though the api is served from https
. Is there a way for the plugin to detect this, or at least let me configure it? If you'd like me to log a separate issue for this, just let me know.
I have spent some time with documentation and client-side tools and have updated my api to use the _embedded
approach, so this no longer affects me, but I'll leave the issue open as so that you have awareness of this inconsistency. If the factory is exposed as it is, it should probably be consistent with this behavior.
I'll go ahead and open another issue for the question about protocols.
could you post an updated code snippet with your latest approach?
thanks!
Sure, it's essentially what you have in the example in your readme, which puts the list items under embedded:
plugins: {
hal: {
api: 'users',
prepare: function (rep, next) {
rep.entity.users.forEach(function (user) {
rep.embed('users', './' + user.id, user);
});
rep.ignore('users');
next();
}
}
}
Therefore, I'm no longer using the factory in the way that fails to build the absolute links correctly.
have you tried declarative embedding? this should preserve the protocol:
plugins: {
hal: {
api: 'users',
embedded: {
users: {
path: 'users' // payload property to embed,
href: './{item.id}'
}
}
}
I have not, but the issue with the protocol is not specific to the self links on lists. It is consistent across all of the links in the response, which is why I ended up logging that separately as #61.
I just spun up a quick example on the current release (3.1.5). Here's the code:
'use strict';
var hapi = require('hapi');
var halacious = require('../');
var fs = require('fs');
var server = new hapi.Server();
server.connection({
port: 8443,
tls: {
key: fs.readFileSync(__dirname + '/key.pem'),
cert: fs.readFileSync(__dirname + '/cert.pem')
}
});
server.register({ register: halacious, options: { absolute: true }}, function(err){
if (err) console.log(err);
});
server.route({
method: 'get',
path: '/users/{userId}',
config: {
handler: function (req, reply) {
reply({
id: req.params.userId,
name: 'User ' + req.params.userId,
googlePlusId: '107835557095464780852',
boss: {
id: 101,
name: 'Boss Man'
}
});
},
plugins: {
hal: {
links: {
'home': './{googlePlusId}'
},
embedded: {
'mco:boss': {
path: 'boss',
href: '../{item.id}'
}
},
ignore: 'googlePlusId' // remove the id property from the response
}
}
}
});
server.start(function(err){
if (err) return console.log(err);
console.log('Server started at %s', server.info.uri);
});
and here's the response to GET https://127.0.0.1:8443/users/100
{
"_links": {
"self": {
"href": "https://127.0.0.1:8443/users/100"
},
"home": {
"href": "https://127.0.0.1:8443/users/100/107835557095464780852"
}
},
"id": "100",
"name": "User 100",
"_embedded": {
"mco:boss": {
"_links": {
"self": {
"href": "https://127.0.0.1:8443/users/101"
}
},
"id": 101,
"name": "Boss Man"
}
}
}
is this not correct?
That does look correct, but I assume it is because of the configuration of tls
in your connection setup. I am not configuring tls
within my application. Take another look at https://api.travi.org/, and you'll notice that the result there is not the same as yours above.
The signed ssl cert for this api is provided by cloudflare and traffic is routed to heroku with a self-signed cert protecting the traffic between cloudflare and heroku. Hosting details aside, the node app has not been configured in a way that tells it that it is being served over https
. I don't imagine the traffic inside the heroku infrastructure is encrypted, so I don't think I would want to configure my app to expect tls
, would I?
Admittedly, I'm still figuring out some of these details, so don't hesitate to point out details that I'm overlooking or misunderstanding.
I see.
Would global configuration options for protocol and host work for you?
On Jul 26, 2015, at 12:31 PM, Matt Travi notifications@github.com wrote:
That does look correct, but I assume it is because of the configuration of tls in your connection setup. I am not configuring tls within my application. Take another look at https://api.travi.org/ https://api.travi.org/, and you'll notice that the result there is not the same as yours above.
The signed ssl cert for this api is provided by cloudflare and traffic is routed to heroku with a self-signed cert protecting the traffic between cloudflare and heroku. Hosting details aside, the node app has not been configured in a way that tells it that it is being served over https. I don't imagine the traffic inside the heroku infrastructure is encrypted, so I don't think I would want to configure my app to expect tls, would I?
Admittedly, I'm still figuring out some of these details, so don't hesitate to point out details that I'm overlooking or misunderstanding.
— Reply to this email directly or view it on GitHub https://github.com/bleupen/halacious/issues/60#issuecomment-125014040.
Sure, that should work fine. It would probably be ideal if each were independently optional if both are available. Since the host is working properly for me automatically, I would probably choose the minimal route and only configure the protocol.
Can you use the Hapi Connection options uri
for this? http://hapijs.com/api#serverconnectionoptions
I may be doing something wrong, but when using
rep.factory
from theprepare
function, links from bothcreate()
andlink()
get defined directly rather than having the host prepended. Am I missing something or is this intended behavior?