I'm using loopback with express session to store cartId.
But I need to inject cartId on request session in order to make my tests work.
So on my remote method I have
Cart.get = function (req, cb) {
Service.getCart(req, req.session.cartId)
.then(function (result) {
cb(null, result);
})
.catch(cb);
};
Cart.remoteMethod(
'get',
{
accepts: { arg: 'req', type: 'object', 'http': { source: 'req' } },
returns: { arg: 'cart', type: 'object', root: true },
http: { path: '/', verb: 'get' }
}
);
How can I force req.session.cartId for my tests?
Thanks
If I understand your case correctly, you can do something similar to the code below, you would just add another param (cardId) to your get method definition:
Cart.remoteMethod('get',{
accepts: [
{ arg: "caseId", type: "number", http: {source:'path'} },
{ arg: 'req', type: 'object', http: { source: 'req' } }
],
returns: { arg: 'cart', type: 'object', root: true },
http: { path: '/:caseId/getCart', verb: 'get' }
});
You can simply use "get" remote method and pass cartId through URL or if you have concern about cartId visibility on URL then you can use post method as following code.
Use following cart.js file and explore in loopback api.
module.exports = function (Cart) {
Cart.getCart = function (cartId, cb) {
Cart.findOne({
where: { cartId : cartId }
}, function (err, cart) {
cb(null, users);
});
};
Cart.remoteMethod('getCart', {
accepts: {
arg: "id",
type: "string",
required: true
},
returns: {
arg: 'cart',
type: 'object'
},
http: {
path: '/:cartId/getcart',
verb: 'get'
}
});
};
get call : http://HOST:IP/cart/YourID/getcart
You will retrieve cart by Id.
Hope this will work.
Related
I run my nuxt app inside a docker container, with the aim of building once, running many. When I run a container, I want to pass in NUXT_ENV_COMMUNITY_ID which would be different per container.
However, with the following setup, when I run my container, I get an undefined error:
nuxt.config.js
auth: {
redirect: {
home: '/home'
},
strategies: {
local: {
endpoints: {
login: {url: "/login", method: "post"},
logout: {url: "/logout", method: "post"},
// user: {url: "/user/" + process.env.NUXT_ENV_COMMUNITY_ID, method: "GET"}
},
token: {
property: 'token',
global: true,
maxAge: 14400,
},
redirectUri: undefined,
}
},
plugins: [{ src: '~/plugins/auth', ssr: true }],
},
env: {
COMMUNITY_ID: process.env.NUXT_ENV_COMMUNITY_ID
},
publicRuntimeConfig: {
communityId: process.env.NUXT_ENV_COMMUNITY_ID
},
privateRuntimeConfig: {
communityId: process.env.NUXT_ENV_COMMUNITY_ID
},
The commented out line produces /user/undefined
Auth plugin
export default function({ $auth, $config }) {
$auth.strategies.local.options.endpoints.user = {url: "/user/" + $config.communityId, method: "GET"}
}
When I run a console.log for this.$auth.strategies.local.options.endpoints in nuxtServerInit, it prints out:
login: {
url: '/login',
method: 'post'
},
logout: {
url: '/logout',
method: 'post'
},
user: {
url: '/user/177',
method: 'GET'
}
Which is what I expect, however Nuxt tries to call api/auth/user which doesn't exist. Any advice is greatly appreciated!
Thanks!
Iam trying to use nuxt-auth module with axios and it gives me "Cannot read property 'data' of undefined" ...and login headers gives strange path
"Request URL: http://aqar.abdullah.link/api/api/auth/login",any help please???
Nuxt.config.js
axios: {
baseURL:'http://aqar.abdullah.link/api',
auth: {
strategies: {
local: {
endpoints: {
login: { url: '/office/login', method: 'post', propertyName: 'data.token' },
user: { url: '/auth/me', method: 'post', propertyName: false },
logout: false
}
}
}
}
}
Login Method:
methods:{
async Login(){
try{
await this.$auth.loginWith('local', {
data:{
email: this.email,
password: this.password
}
})
this.$router.push('/')
}catch(e){
this.error = e.response.data
}
},
},
Api response on postman:
login page path in folders
I'm not sure, I used the exact same configurations and it worked for me.
But your nuxt.config.js file has a missing closing }, for the axios object.
it should look like this:
axios: {
baseURL: "http://aqar.abdullah.link/api"
},
auth: {
strategies: {
local: {
endpoints: {
login: {
url: "/office/login",
method: "post",
propertyName: "data.token"
},
user: { url: "/auth/me", method: "post", propertyName: false },
logout: false
}
}
}
},
also make sure you have these modules in you nuxt.config.js as well:
modules: [
"#nuxt/http",
"#nuxtjs/auth",
"#nuxtjs/axios",
],
I have this factory:
angular.module('core.actor').factory('Actor', ['$resource',
function ($resource) {
return $resource('api/actor/:actorId/', {}, {
query: {
method: 'GET',
isArray: true,
cache: true
},
update: {
method: 'PUT'
}
});
}
]);
And this is part of my paging function:
if (self.pk == "-6" && self.searchTerm == undefined) {
self.actorsToAdd = Actor.query({
offset: pageOffset,
limit: pageLimit
})
} else if (self.pk == "-6") {
self.actorsToAdd = Actor.query({
offset: pageOffset,
limit: pageLimit,
search: self.searchTerm
})
} else if (self.searchTerm == undefined) {
self.actorsToAdd = Actor.query({
offset: pageOffset,
limit: pageLimit,
pk: self.pk.toString()
})
} else {
self.actorsToAdd = Actor.query({
offset: pageOffset,
limit: pageLimit,
search: self.searchTerm,
pk: self.pk.toString()
})
}
It changes the GET request generated by Actor depending on certain conditions. I'm looking for a way to parametrize this function so I would be able to replace 'Actor' with a variable.
Something along the lines of:
pageType = Movie;
var page = function (pageType){
self.itemsToAdd = pageType.query({
offset: pageOffset,
limit: pageLimit
})
}
Is it possible? If so, how?
This is how I do it, rather than passing individual parameters into the query, pass in a object, which contains your query parameters.
angular.module('core.actor').factory('Actor', ['$resource',
function ($resource) {
return $resource('api/actor/:actorId/', {}, {
query: {
method: 'GET',
isArray: true,
cache: true,
params: { queryParams: '#_queryParams' }
},
update: {
method: 'PUT'
}
});
}
]);
so your call to it looks like this
Actor.query({ queryParams: {
offset: pageOffset,
limit: pageLimit,
pk: self.pk.toString()
}})
Then on the server I look at which values are contained in my (json parsed) params, in order to construct the appropriate query on the database.
After your latest comment, is this the kind of thing you're looking for?
angular.module('core.actor').factory('Api', ['$resource',
function ($resource) {
return {
actor: $resource('api/actor/:actorId/', {}, {
query: {
method: 'GET',
isArray: true,
cache: true,
params: {queryParams: '#_queryParams'}
},
update: {
method: 'PUT'
}
}),
movie: $resource('api/move/:moveId/', {}, {
query: {
method: 'GET',
isArray: true,
cache: true,
params: {queryParams: '#_queryParams'}
},
update: {
method: 'PUT'
}
})
};
}
]);
You could then call either Api.movie.query() or Api.actor.query()
For completeness, heres how my server side code looks when building my query.
var constructUserQuery = function (queryParams) {
var query = { $or: [], $and: [] };
if (queryParams.name) {
query.$and.push({ displayName: { $regex: queryParams.name, $options: 'i'} });
}
if (queryParams.client) {
query.$or.push({ client: mongoose.Types.ObjectId(queryParams.client) });
}
if (queryParams.roles) {
query.$or.push({ roles: { $in: queryParams.roles }});
}
// Ignore the current user, if it's supplied
if (queryParams.user) {
query.$and.push({ _id: { $ne: queryParams.user._id }});
}
// Clean up any empty arrays
if (query.$or.length === 0) {
delete query.$or;
}
if (query.$and.length === 0) {
delete query.$and;
}
return query;
};
Obviously this is specific to my case but you get the idea. This is the only place where I have any if statements.
I'm trying to execute PHP within a loopback model. When visiting myapi:3000/api/Door/open I'd like it to run the PHP file containing a function.
I have the /Door/open added as a remote method and it shows up in swagger.ui, the api returns "message": "createElement is not defined", even though jquery is included.
Here is my doors.js showing the remote method setup:
module.exports = function(Door) {
Door.open = function(id, cb) {
var script = createElement('script');
script.src = 'http://code.jquery.com/jquery-2.1.4.min.js';
script.type = 'text/javascript';
getElementsByTagName('head')[0].appendChild(script);
$.ajax({
url: "http://192.168.10.139/Facility/doorfunc_dynamic.php?dpip=192.168.10.249&doorid=3&func=unlock"
}).done(function(data) {
console.log(data);
});
};
Door.remoteMethod(
'open',
{
description: 'Open a door by id',
accepts: {args: 'id', type: 'number', name: 'id', description: 'Door id'},
returns: {arg: 'open', type: 'string'},
http: {path: '/open', verb: 'get'}
}
);
};
Does anyone know how to resolve this?
I have tried adding a static page within the client folder, however it does not show within the swagger.ui explorer.
If you want to perform only http request, you can use request package.
var request = require('request');
module.exports = function(Door) {
Door.open = function(id, cb) {
request('http://192.168.10.139/Facility/doorfunc_dynamic.php?dpip=192.168.10.249&doorid=3&func=unlock',
function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
});
};
Door.remoteMethod(
'open',
{
description: 'Open a door by id',
accepts: {args: 'id', type: 'number', name: 'id', description: 'Door id'},
returns: {arg: 'open', type: 'string'},
http: {path: '/open', verb: 'get'}
}
);
};
Hope it solves your problem.
I have an image saved on a MongoDB. The model is the following:
picture: {
metadata: {
name: { type: String, default: null },
comment: { type: String, default: null },
publisherID: { type: String,default: null },
date: { type: Date, default: Date.now },
size: { type: Number,default: 0 },
type: { type: String, default: null }
},
data: { type: Buffer, default: null },
tags: Array
}
Now I need to load the image again from the DB.
I make an AJAX call and request the picture with the id.
$.ajax({
type: "POST",
url: window.location.origin + '/picture',
contentType: 'application/json',
dataType: 'json',
async: true,
data: JSON.stringify({ id: id }),
success: function (result) {
console.log(result);
a = result;
var img = result.result[0].picture.data.join("").toString('base64');
img = "data:" + result.result[0].picture.metadata.type + ";base64," + img;
$('#img').attr('src', img);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('error ' + textStatus + " " + errorThrown);
success = false;
}
});
And this is the handler on the server
var Picture = require('../models/picture');
Picture.find({ "_id": req.body.id}, function (err, pic) {
if (err || !pic)
res.end(JSON.stringify({ result: "error" }));
if (pic) {
console.log(pic);
res.end(JSON.stringify({ result: pic }));
}
})
I have translated the binary data into base64 but the image doesnt display.
(I had to join the binary data because they came into an array).
There are some other similar posts however they dont have anything that I havent done (I think).
As stated in the comments, it is better to have a separate endpoint in your application to make these calls "look like" standard static file requests. So the first thing I would do is change your schema a little:
picture: {
metadata: {
name: { type: String, default: null },
comment: { type: String, default: null },
publisherID: { type: String,default: null },
date: { type: Date, default: Date.now },
size: { type: Number,default: 0 },
type: { type: String, default: null }
},
path: { type: String, required: true },
mime: { type: String, required: true },
data: { type: Buffer, default: null },
tags: Array
}
So that adds two fields which are going to identify the "path" to the image to match, and "mime" as the mime-type of the file. So "path" is a more "friendly" identifier than an _id and the "mime-type" would be set in insert to match the returned content type.
Then you set up a route to serve the content:
app.get('/images/:imgname', function(req,res) {
Picture.find({ "picture.path": req.param("imgname") }, function(err,pic) {
if (err) // checking here
// Sending response
res.set('Content-Type', pic.mime);
res.send( pic[0].picture.data );
});
})
So when you did a request like:
wget http://localhost:3000/images/test.png
This would happen:
Find the document matcing "path" for "test.png"
Assign the document property for "picture.mime" as the Content-Type for the response
Send the binary data back as the response
So for the client, it's an actual file as the response, and the point is the that "browser" can cache this and not hit your application where the "cached" copy is valid.
If you are embedding Base64 encoded data in JSON responses then you loose that important part and you send the data every time. It's also a very messy process to handle, as you have discovered.