How to add our own custom JSON message to Blueprint API in Sails.js? - sails.js

I want to send to client side like this:
{
"success": true,
"message": "Your Message",
"result": ""
}

When it comes to Blueprint APIs, we will not be able to send custom responses. In order to send custom responses, you have to define custom actions/controller methods with the desired response and define a custom route for that action/controller method in config/routes.js. If the Blueprint APIs still override the custom methods, you can disable the Blueprint APIs by changing the value of actions to false in config/blueprints.js. This will disable Blueprint APIs completely.
module.exports.blueprints = {
actions: true,
// rest: true,
// shortcuts: true,
};
If you want to disable Blueprint routes on a per-controller basis, checkout https://sailsjs.com/documentation/reference/blueprint-api#?disabling-blueprint-routes-on-a-percontroller-basis for more info.
Even though Blueprint APIs come in handy during development, it is recommended to use custom routes while moving to production, since custom routes are more secure than Blueprint APIs.

Related

REST (HATEOAS) and ReactJS

I'm interested in using the HATEOAS principle of REST to reduce business logic in a SPA application. In a React-specific context, I'd like to know if there are challenges that make this impractical and, if not, what is a good strategy to follow?
Conceptual examples of using HATEOAS to remove business logic from the UI:
Delegating valid bank account actions to the REST service
Delegating role-based access control to the REST service
I've only found one link that suggests React/Flux is not compatible with a HATEOAS strategy, and no meaningful discussion elsewhere. Is it really not feasible in a React/Flux app? That SO post didn't get enough attention. Does anyone have a favorite or recommended approach for achieving success (with or without Flux or Redux)?
Someone gave a fairly detailed example of leveraging HATEOAS in the context of Angular. I'm looking for something similar for React.
Personally, I'm picturing the rel tag in hypermedia links controlling which JSX components are rendered (conditional JSX). Is that naive for a real-world React app? Perhaps conditionally rendered React components are too coarse-grained to be used this way?
I am assuming that hypermedia links are provided by a HAL implementation, or otherwise conform to the ATOM feed convention (RFC4287).
100% HATEOAS IS compatible with React & Flux, HATEOAS is compatible with Angular, HATEOAS is compatible with JQuery and even vanilla JS.
HATEOAS doesn't not impose any technical or implementation requirements on a consuming client.
HATEOAS is in fact simply a concept to which you can design your API (you can use one of several standards though like HAL)
Basically if you can call an API then you can implement a HATEOAS client.
So how to get there:
Step 1, how would you normally do an API call in React? Do it the same way.
Step 2, interrogate response.
Step 3, based on response, respond in the UI appropriately.
For example given a call to the order api /orders, I get the following response:
{
"_links": {
"self": { "href": "/orders" },
"next": { "href": "/orders?page=2" }
}
}
From this I can infer that next is a valid relation, and that if I go to that href I would in fact receive a second page of orders, so in this case in the UI show the next button.
However if I had received the following response:
{
"_links": {
"self": { "href": "/orders" },
}
}
Then I could infer that next is not a valid relation, and in my UI I should disabled or not display a next button.
There is no magic, it is simply a change in thinking, a new paradigm.
Before I spout off my most likely wrong/irrelevant answer, I just want to let you know that I just now read up on what HATEOAS is. That warning there, from what I've briefly read, HATEOAS seems to be mostly about the API telling you how to navigate through itself by providing you a link back to the resources that are relevant to the resource you had just requested.
That being the case, I don't see a reason why you can't implement dynamic url ajax calls in your actions that will alter your SPA's application state (i.e. Redux) based on what has been provided to you, however, you'll still need to have something to represent the state in a visual manner for all parts of your application. Here's a crude semi-pseudo and not very well thought-out representation of what I mean based loosely on your bank account example:
// our component file
import React from 'react'
import { makeAWithdrawl } from './actions'
export default React.createClass({
handleClick: function(e) {
e.preventDefault()
makeAWithdrawl(this.props.account.withdraw.href)
},
render: function () {
<div className="account">
<p className="account_number">{this.props.account.accountNumber}</p>
<p className="balance">{this.props.account.balance}</p>
<p><a href={this.props.account.deposit.href}>Deposit</a></p>
{this.props.account.withdraw ? <p><a onClick={this.handleClick}>Withdraw</a></p> : ''}
</div>
}
})
// our actions file
import store from 'store' // our redux store
import axios from 'axios' // an ajax library
export function makeAWithdrawl(url) {
return axios.post(url).then(function(resp){
store.dispatch({
type: 'MAKE_WITHDRAWL',
action: resp.data
}) // do your reducer stuff
})
}
Your application still knows what it's doing in the SPA, however, this will allow the API to direct you where to call to for whatever action needs to be performed. Hope it helps.

How can I dynamic hide swagger api?

I want hide swagger API in dependence of my deployment environment.
You can hide API by Annotation:
#Api(
hidden = false)
public class MyRESTClass { ... }
It work fine, but is not dynamic. Is there another way to hide or not dynamic the swagger API?
see: ApiMode Swagger
Yes there is a spec-filter interface that you can implement for dynamic spec filtering. You can extend AbstractSpecFilter.java and implement the methods that you want, which allows you to filter based on headers, parameters, etc. It's very flexible.

Can grails application have RestController and normal controller (for GSP) for same domain class

Recently I need to create REST API for existing grails application.
I am thinking that is it really possible to have both of the controllers (Normal and Restful) for same domain class in one single grails application?
Which controller will handle the request if make a HTTP GET request?
Please discuss your thoughts or if it is possible at all please guide me how.
We can define a new Controller to handle to REST API calls. e.g. In my app I have User as Domain Class and have UserController which return the data to GSP pages. I wanted to add REST API support (unfortunately) in the same app and I don't wanted to deal with mess it is already there in UserController. So I added new Controller UserRestController which will specifically handle the REST API calls and following mapping in UrlMappings.groovy which now works fine. Thanks to #codehx for helping me on this.
"/api/users"(controller: "userRest", parseRequest: true) {
action = [GET: "list", POST: "save" }
"/api/users/$id"(controller: "usersRest", parseRequest: true) {
action = [GET: "show", PUT: "update", DELETE: "delete"] }
Which controller will handle the request if make a HTTP GET request?
As far as it is not possible to have two controllers with same name in grails app this will not be confusing.
Just use two different names for Normal controller and for your RESTFUL controller, so obviously the URL for accessing the two urls will be different.

How do I make arbitrary API calls using Ember.js?

What I'm trying to do is described in great detail here:
Call a Server-side Method on a Resource in a RESTful Way
I have Ember Data's RESTAdapter working with my API, but now I want to give Ember.js a way to kick off various server-side actions using custom routes, such as /docs/1/share or /docs/1/activate. The former would possibly modify the record but the latter would not.
What's the best way to do this?
TIA!
Ember has jQuery baked in. In your controller:
actions: {
activate: function() {
var docId= this.get('id'), self= this;
Ember.$.ajax({
url: '/docs/%#/activate'.fmt(docId),
// your other details...
}).then(function(resolve) {
self.set('name', resolve.doc.name);
// process the result...
});
}
}
You can also use ic-ajax which is a nice wrapper around jQuery.ajax, you can see an example here using ix-ajax.

Sailsjs overwrite post action in controller

Short question, tried finding an IRC for sails for such a quick one but got lost so here goes. I have a controller with a route of '/userposts'. I know sails offers some default REST-like functionality without backend code needed but what if I want to overwrite the default POST action what would I do?
I'm forced to write a POST route such as post /userposts/create or I can overwrite the default action and post straight to /userposts which will identify my overwriting and execute it.
I hope I'm making sense. I basically want to create a custom POST route and be able to
socket.post('/userposts', {title: "Foo", content: "Bar"}, function(response){});
I tried with create but it doesn't get executed on a post to /userposts
Sails.js provides blueprints out of the box.
These blueprints provide you with the following CRUD routes that are enabled by default
/:controller/find/:id?
/:controller/create
/:controller/update/:id
/:controller/destroy/:id
To modify the default functionality for your controllers, look at the settings in config/controllers.js
Your routes are defined within config/routes.js, in your case you have a model UserPosts and a corresponding controller named UserPostsController.
In your UserPosts controller, create a function createPost and specify the route(s) to this method
'POST /userposts/create': 'UserPostsController.createPost'
which is shorthand for
'POST /userposts/create': {
controller: 'userposts',
action: 'createPost'
}
you can also override the /:controller route
'POST /userposts': 'UserPostsController.createPost'
These routes will map any POST requests made to the createPost function.
For more information, be sure to check out the Sails.js documentation