intercepting PUT routes on /resources and forwarding internally to /resources/:id - json-server

I want to mock a backend with a PUT API slightly different from the standard PUT /resources/:id.
I found a working ugly solution by intercepting my '/tasks', extracting the id from the JSON body and redirecting to '/tasks/:id'.
With:
server.put('/tasks/', (req, res, next) => {
res.redirect(302, 'http://localhost:3300/tasks/' + req.body.id);
});
But how to do it cleanly ? How to forward internally to the standard json-server processing for /tasks/:id without redirecting ?

Related

ASP.NET Core 5 route redirection

We have an ASP.NET Core 5 Rest API where we have used a pretty simple route:
[Route("api/[controller]")]
The backend is multi-tenant, but tenant-selection has been handled by user credentials.
Now we wish to add the tenant to the path:
[Route("api/{tenant}/{subtenant}/[controller]")]
This makes cross-tenant queries simpler for tools like Excel / PowerQuery, which unfortunately tend to store credentials per url
The problem is to redirect all existing calls to the old route, to the new. We can assume that the missing pieces are available in the credentials (user-id is on form 'tenant/subtenant/username')
I had hope to simply intercept the route-parsing and fill in the tenant/subtenant route values, but have had not luck so far.
The closes thing so far is to have two Route-attributes, but that unfortunately messes up our Swagger documentation; every method will appear with and without the tenant path
If you want to transparently change the incoming path on a request, you can add a middleware to set Path to a new value, for example:
app.Use(async (context,next) =>
{
var newPath = // Logic to determine new path
// Rewrite and continue processing
context.Request.Path = newPath;
await next();
});
This should be placed in the pipeline after you can determine the tenant and before the routing happens.

make meteor restful api/web-service

I have created a new url/route in my app where I need to write a web-service. I need to write a service that deletes user according to the parameters passed in the service. For now, anyone should be able to call that service (will make it secure at later stage). App is built on meteor.
My url is : loaclhost:3000/deleteUser. Now one should be able to call my delete user function defined on this page and pass json structure data as an argument to it. If the data is valid, then the user should be deleted.
Using simple:rest package
Meteor.publish("delUser", function (a, b) {
UserDetails.remove({}); //delete user according to data received
}, {
url: "/testing/delUser", //url where third party will call the function
getArgsFromRequest: function (request) {
// Let's say we want this function to accept a form-encoded request
// with fields named `a` and `b`.
console.log('received : ' + JSON.stringify(request.body) );
var content = request.body;
// Since form enconding doesn't distinguish numbers and strings, we need
// to parse it manually
return [content.a, content.b];
}
})
How to access the function, delUser from a thrid party? I also need to add authentication at a later stage.
Personnally, I use this :
simple:rest
simple:json-routes
simple:rest-accounts-password
I find it easier to implement.
even iron:router comes with server side routes where you can build your own functions and api calls.
http://iron-meteor.github.io/iron-router/#restful-routes
Sample (Server side code) :
Router.map(function () {
this.route("api", {path: "/api/:paramsYouNeed",
where: "server",
action: function(){
this.response.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
if (this.request.method == 'POST') {
var response;
//do whatever you want to do
this.response.end(response);
}
}
});
The other user can call this by making a http.post request to the above url (http:www.a****a.com/api/params)
The easiest way to do this is use the restivus package.
https://atmospherejs.com/nimble/restivus
Restivus makes building REST APIs in Meteor 0.9.0+ easier than ever
before! The package is inspired by RestStop2 and Collection API, and
is built on top of Simple JSON Routes to provide:
A simple interface for creating REST APIs
Easy setup of CRUD endpoints for Mongo Collections
User authentication via the API
Optional login and logout endpoints
Access to this.user in authenticated endpoints
Custom authentication if needed
Role permissions for limiting access to specific endpoints
Works alongside the alanning:roles package - Meteor's accepted role permission package

Scoped redirect when using Express.js Routers

When using Express Routers, a route prefix can be provided:
var router = new Express.Router();
app.use("/scope", router);
Let us say that I have some CRUD routes in my Router.
router.post("/", function(req, res) {
var result = create(req);
res.redirect(result.id);
});
router.put("/:id", function(req, res) {
var result = update(req);
res.redirect(result.id);
});
router.get("/:id", function(req, res) {
var result = findById(req.params.id);
res.render("show.html", {data: result});
});
When requesting to the PUT above, the response is a redirect to "/scope/[id]" as it should be. When requesting to the POST, the response is a redirect to "/[id]" instead of the previous result.
I am not certain where to find the root of the issue, nor how to correct it.
I will answer the question anyway, for the benefit of anyone else who might encounter this issue.
What I suspect your original issue was that, since you had strict mode disabled (Express' default), your client side code was likely POSTing to /scope' (which in non-strict node is the same as/scope/). Within your post handler you did a relative redirect usingres.redirect(result.id). Let sayresult.idis123, then a relative redirect would take you to/123`.
NOTE: Don't forget that Express has little to do with the actual redirects, which are taken care of client-side by the browser.
The issue could have easily been solved by ensuring your client side code POSTed to /scope/, after which a relative redirect to id would take you to /scope/id, just as you expected.

Restangular - how to cancel/implement my own request

I found a few examples of using fullRequestInterceptor and httpConfig.timeout to allow canceling requests in restangular.
example 1 | example 2
this is how I'm adding the interceptor:
app.run(function (Restangular, $q) {
Restangular.addFullRequestInterceptor(function (element, operation, what, url, headers, params, httpConfig) {
I managed to abort the request by putting a resolved promise in timeout (results in an error being logged and the request goes out but is canceled), which is not what I want.
What I'm trying to do - I want to make the AJAX request myself with my own requests and pass the result back to whatever component that used Restangular. Is this possible?
I've been looking a restangular way to solve it, but I should have been looking for an angular way :)
Overriding dependency at runtime in AngularJS
Looks like you can extend $http before it ever gets to Restangular. I haven't tried it yet, but it looks like it would fit my needs 100%.
I'm using requestInterceptor a lot, but only to change parameters and headers of my request.
Basically addFullRequestInterceptor is helping you making change on your request before sending it. So why not changing the url you want to call ?
There is the httpConfig object that you can modify and return, and if it's close to the config of $http (and I bet it is) you can change the url and even method, and so change the original request to another one, entirely knew.
After that you don't need timeout only returning an httpConfig customise to your need.
RestangularConfigurer.addFullRequestInterceptor(function (element, operation, route, url, headers, params, httpConfig) {
httpConfig.url = "http://google.com";
httpConfig.method = "GET";
httpConfig.params = "";
return {
httpConfig: httpConfig
};
});
It will be pass on and your service or controller won't know that something change, that's the principle of interceptor, it allow you to change stuff and returning to be use by the next process a bit like a middleware. And so it will be transparent to the one making the call but the call will be made to what you want.

RESTfull implementation and general informatino

I have been reading a lot lately, and even more experimenting with web Development. There are some things that I simply cant understand, therefore any help is appreciated.
I am not trying to get my homework done for me. I have some holes in my knowledge, that I desire to fill. Please, help me out with your views :)
REST questions:
Reading documentation this is perfectly understandable (NODE.JS / Express) example:
EXAMPLE ONE (get):
app.get('/', function(req, res) {
res.send('please select a collection, e.g., /collections/messages')
})
My explanation: When the root of the server is hit, send thie following message
EXAMPLE TWO (get):
app.get('/collections/:collectionName/:id', function(req, res) {
req.collection.findOne({name: req.collection.id(req.params.id)},
function(e, result){
if (e) return next(e)
res.send(result)
})
})
My explanation: When the url in hit, take id from the URL (that is located in params.id) and make search based on it (that is MongoDB).
EXAMPLE THREE (post):
app.post('/collections/:collectionName', function(req, res) {
req.collection.insert(req.body, {}, function(e, results){
if (e) return next(e)
res.send(results)
})
})
My explanation: When the URL is hit, take the payload(JSON in this case) that is located in req.body, and insert it as a new document.
Questions:
Are example one and two both RESTfull?
I am now totally confused with params.id. I do understand that POST is transmitted in rew.body... what is params.id? Is it containing URL variables, such as :ID?
My explanations... are they correct?
Example three is also REST, regardless of the fact that POST is used?
Example three, '/collections/:collectionName. Why is the ':collectionName' passed in URL, I could have placed it in req.body as a parameter (along with new data) and take it from there? What is the benefit of doing it?
Thank you
An API must be using HATEOAS to be RESTful. On first example, if / is the entry point of your API, the response should contain links for the available collections, not a human readable string like that. That's definitely not RESTful.
Exactly.
They're OK, except that there's nothing in the third example implying it's a JSON body. It should check for a Content-Type header sent by the client.
REST isn't dependent on HTTP. As long as you're using the HTTP methods as they were standardized, it's fine. POST is the method to use for any action that isn't standardized, so it's fine to use POST for anything, if there isn't a method specific for that. For instance, it's not correct to use POST for retrieval, but it's fine to use it for creating a new resource if you don't have the full representation.
POST means the data body is subordinated to the resource at the target URI. If collectionName were in the POST body, this would mean you were POSTing to /collections, which would make more sense to create a new collection, not a new item of a collection.