SlideShare a Scribd company logo
1 of 58
Download to read offline
Build REST API client like a BOSS
Build RESTful API clients for AngularJS, the proper way
Who are you?
@AlmogBaku nice to meet ya`
1. Entrepreneur
2. Co-Founder & CTO @ Rimoto
3. Developer for 10 years
4. GitHub addicted.
5. Blog about entrepreneurship and development:
www.AlmogBaku.com
What are we going to talk about?
● What tha’ heck is REST?
● Why $resource is sucks?
● $http
● Say hi to Restangular
● Do it like a boss
Disclaimer
You wanna know more? Google it!
What tha’ heck is REST?
Representational State Transfer
Watttt??
What is API?
API is a layer that connects two applications.
Application Programing Interface
What is API?
API is actually a common language, that
both of the parties knows.
REST
REST is a Client-Server API
REST
REST is just the regular way the internet works!
GET http://google.com/
REST
REST is just the regular way the internet works!
GET http://google.com/RESPONSE 200 OK
REST
REST is about resources, not about functions.
Book store api:
1. /api/authors/
2. /api/authors/:authorId/
3. /api/authors/:authorId/books/
4. /api/authors/:authorId/books/:bookId
5. /api/authors/:authorId/books/:bookId/reviews
6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
REST
REST is about resources, not about functions.
Book store api:
1. /api/authors/
2. /api/authors/:authorId/
3. /api/authors/:authorId/books/
4. /api/authors/:authorId/books/:bookId
5. /api/authors/:authorId/books/:bookId/reviews
6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
REST
GET /api/authors/
[
{
"id": 7,
"name": "J.R.R. Tolkien",
"birthday": "1-3-1892"
},
{
"id": 183,
"name": "Douglas Adams",
"birthday": "3-11-1952"
}
]
REST
REST is about resources, not about functions.
Book store api:
1. /api/authors/
2. /api/authors/:authorId/
3. /api/authors/:authorId/books/
4. /api/authors/:authorId/books/:bookId
5. /api/authors/:authorId/books/:bookId/reviews
6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
REST
GET /api/authors/187/
{
"id": 183,
"name": "J.R.R. Tolkien",
"full_name": "John Ronald Reuel Tolkien",
"birthday": "1-3-1892",
"genre": "SciFi"
}
REST
The same URIs can do many different actions...
We can request web pages in one of the following methods:
1. GET - request information about resource
2. POST - create new resource
3. PUT - update resource
4. DELETE - delete resource
5. HEAD - get information only with headers (eg. if resource exists)
6. OPTIONS - list of available methods to the resource (like --help)
REST
Errors are simple http errors
200 - OK
404 - Not found
401 - Unauthorized
500 - Server Error
Etc.
REST
REST is Stateless
- You can’t use cookies
- You need to pass your identification in every request
GET /users/me?access_token=ftjhi89uh5982hbrvt92vgt9qvhg2r0219
REST API
+
REST with AngularJS
It’s pretty simple actually.. just use $resource
var Author = $resource('/api/v1/author/:authorId', {authorId:'@id'});
Author.get({authorId:183}, function(author) {
author.name = 'J.R.R. Tolkien';
author.$save();
});
The thing is…
It just sucks
The thing is…
It just sucks
1. It can be very complex...
var Author = $resource('https://api.rimoto.net/api/v1/author/:authorId', {authorId:'@id'});
Author.get({authorId:183}, function(author) {
author.name = 'J.R.R. Tolkien';
author.$save();
});
var Book = $resource('https://.../api/v1/author/:authorId/books/:bookId', {authorId: 183, bookId:'@id'});
Book.get({bookrId:2}, function(book) {
book.name = 'Lord of the rings';
book.$save();
});
The thing is…
It just sucks
2. Doesn’t allow you to parse the API
3. No way to set base url application wide
4. You can’t handle errors application wide
5. You can’t handle headers application wide
6. You can’t handle anything application wide
Actually- $resource is okay for anything other than serious apps.
What can we do?
We can use $http, in order to add necessary headers:
We can also use the $http interceptor, in order to handle errors...
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': 'application/json'
},
data: { test: 'test' }
};
$http(req).success(function(){...}).error(function(){...});
What can we do?
We can also use the $http interceptor, in order to handle errors...
$provide.factory('myHttpInterceptor', function($q, dependency1) {
return {
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
'response': function(response) {
//parsing here....
return response;
},
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
What can we do?
We can also use the $http interceptor, in order to handle errors...
$provide.factory('myHttpInterceptor', function($q, dependency1) {
return {
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
'response': function(response) {
//parsing here....
return response;
},
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
What can we do?
We can also use the $http interceptor, in order to handle errors...
$provide.factory('myHttpInterceptor', function($q, dependency1) {
return {
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
'response': function(response) {
//parsing here....
return response;
},
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
What can we do?
We can also use the $http interceptor, in order to handle errors...
$provide.factory('myHttpInterceptor', function($q, dependency1) {
return {
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
'response': function(response) {
//parsing here....
return response;
},
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
Say hi to
Restangular
Restangular
1. Restangular solves ‘em all!
2. Published on 2013
3. Very stable and popular angular-module
4. Active community
5. Allows you to configure your REST API in application level
6. Restangular 2 will support AngularJS 2! (WIP)
7. Very easy to use
Configurations
Define initial settings:
Defining base url:
Defining Content-Type headers:
RestangularProvider.setBaseUrl('http://api.rimoto.net/api/v1/');
RestangularConfigurer.setDefaultHeaders({'Content-Type': 'application/json'});
Say hi to Restangular
Let’s create a new author:
var Authors = Restangular.all('authors');
Authors.post({
name: "J.R.R. Tolkien"
});
Say hi to Restangular
Lets’ create a new author:
var Authors = Restangular.all('authors');
Authors.post({
name: "J.R.R. Tolkien"
});
POST
http://api.rimoto.net/api/v1/authors/
Say hi to Restangular
Lets’ create a new author:
var Authors = Restangular.all('authors');
Authors.post({
name: "J.R.R. Tolkien"
});
Say hi to Restangular
Get the author:
Restangular.one('authors', 183).get()
.then(function(author) {
$scope.author = author;
})
;
Say hi to Restangular
Get the author:
Restangular.one('authors', 183).get()
.then(function(author) {
$scope.author = author;
})
;
GET
http://api.rimoto.net/api/v1/authors/183
Say hi to Restangular
Get all his books:
$scope.author.getList('books')
.then(function(books) {
var firstBook = books[0];
firstBook.name="The Hobbit";
firstBook.put();
})
;
Pretty simple.. huh?
Model parsing
RestangularConfigurer.ExtendModel("books", function(book) {
book.published = new Date(book.published);
return book;
});
We can “transform” data from our API to javascript!
Model parsing
<div class="vote-box">
<button ng-click="voteUp($review)" class="up"><i class="up-arrow"></i></button>
<div>{{votes|number}}</div>
<button ng-click="voteDown($review)" class="down"><i class="down-arrow"></i></button>
</div>
Model parsing
<div class="vote-box">
<button ng-click="voteUp($review)" class="up"><i class="up-arrow"></i></button>
<div>{{votes|number}}</div>
<button ng-click="voteDown($review)" class="down"><i class="down-arrow"></i></button>
</div>
Vote done on the controller
Model function
But it’s an API function!
Model parsing
How can we solve that?
Model parsing
How can we solve that?
1. Create a transformer
2. Add the function to the model!
3. Fin.
Model parsing
How can we solve that?
1. Create a transformer
2. Add the model this function!
3. Fin.
RestangularConfigurer.ExtendModel("review", function(review) {
review.voteUp = function() {
return review.getAll("votes").post({
vote_up: true
});
};
return review;
});
Model parsing
We can do use this tool for many cases:
1. Ordering lists
2. Special parsing
3. Add functions
4. Etc.
What about errors?
RestangularConfigurer.setErrorInterceptor(function(response) {
if([401, 403, 405].indexOf(response.status)!=-1) {
logout();
return false;
}
});
Build REST client like a
BOSS
PRO tips
Bundle your whole API as “SDK”, and extend the Restangular to be your own
API service:
module
.factory('API', ['Restangular',
function(Restangular) {
angular.extend(this, Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl("https://api.rimoto.net");
RestangularConfigurer.setRequestSuffix('/');
RestangularConfigurer.setDefaultHeaders({ Accept: 'application/json;v=1' });
}));
return this;
}])
;
PRO tips
1. You can set the `id` parameter (eg. for mongodb):
RestangularProvider.setRestangularFields({
id: '_id'
});
PRO tips
2. Handle the Access-Tokens on application level
Example for Restangular with ngAuth:
/** Login changed **/
$rootScope.$on("Auth.status", function(event, response) {
if(response.access_token) {
Restangular.setDefaultRequestParams({
access_token: response.access_token
});
} else {
Restangular.setDefaultRequestParams({
access_token: null
});
}
});
PRO tips
3. Decouple Restangular to models
4. You can define Restangular to use HATEOAS
5. Keep your API service generic, and handle specific use-cases separately.
module.factory('Users', function(Restangular) {
return Restangular.service('users');
});
RestangularProvider.setRestangularFields({
selfLink: 'self.link'
});
Check it out
github.com/mgonto/restangular
Be creative,
and create your own API
Questions?
Thanks.

More Related Content

What's hot

I18n
I18nI18n
I18n
soon
 

What's hot (20)

Rspec API Documentation
Rspec API DocumentationRspec API Documentation
Rspec API Documentation
 
Lies, Damn Lies, and Benchmarks
Lies, Damn Lies, and BenchmarksLies, Damn Lies, and Benchmarks
Lies, Damn Lies, and Benchmarks
 
I18n
I18nI18n
I18n
 
CBDW2014 - ColdBox RESTFul Services
CBDW2014 - ColdBox RESTFul ServicesCBDW2014 - ColdBox RESTFul Services
CBDW2014 - ColdBox RESTFul Services
 
Python for AngularJS
Python for AngularJSPython for AngularJS
Python for AngularJS
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
Introduction to plugin development
Introduction to plugin developmentIntroduction to plugin development
Introduction to plugin development
 
Extending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh PollockExtending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh Pollock
 
Getting Started-with-Laravel
Getting Started-with-LaravelGetting Started-with-Laravel
Getting Started-with-Laravel
 
Build JSON and XML using RABL gem
Build JSON and XML using RABL gemBuild JSON and XML using RABL gem
Build JSON and XML using RABL gem
 
Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.
 
Hello World on Slim Framework 3.x
Hello World on Slim Framework 3.xHello World on Slim Framework 3.x
Hello World on Slim Framework 3.x
 
2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with Dredd2019-08-23 API contract testing with Dredd
2019-08-23 API contract testing with Dredd
 
Modern Perl
Modern PerlModern Perl
Modern Perl
 
Server Side Swift - AppBuilders 2017
Server Side Swift - AppBuilders 2017Server Side Swift - AppBuilders 2017
Server Side Swift - AppBuilders 2017
 
Developing on the aloashbei platform
Developing on the aloashbei platformDeveloping on the aloashbei platform
Developing on the aloashbei platform
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Lightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
 
Tornado
TornadoTornado
Tornado
 

Similar to Build REST API clients for AngularJS

Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)
True-Vision
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa
 

Similar to Build REST API clients for AngularJS (20)

Plack at YAPC::NA 2010
Plack at YAPC::NA 2010Plack at YAPC::NA 2010
Plack at YAPC::NA 2010
 
Introduction to Retrofit
Introduction to RetrofitIntroduction to Retrofit
Introduction to Retrofit
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss
 
RESTful API 제대로 만들기
RESTful API 제대로 만들기RESTful API 제대로 만들기
RESTful API 제대로 만들기
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
PSR-7, middlewares e o futuro dos frameworks
PSR-7, middlewares e o futuro dos frameworksPSR-7, middlewares e o futuro dos frameworks
PSR-7, middlewares e o futuro dos frameworks
 
Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and Python
 
Creating native apps with WordPress
Creating native apps with WordPressCreating native apps with WordPress
Creating native apps with WordPress
 
Build a bot workshop async primer - php[tek]
Build a bot workshop  async primer - php[tek]Build a bot workshop  async primer - php[tek]
Build a bot workshop async primer - php[tek]
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
ZendCon 2017 - Build a Bot Workshop - Async Primer
ZendCon 2017 - Build a Bot Workshop - Async PrimerZendCon 2017 - Build a Bot Workshop - Async Primer
ZendCon 2017 - Build a Bot Workshop - Async Primer
 
PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
TPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and FluxTPSE Thailand 2015 - Rethinking Web with React and Flux
TPSE Thailand 2015 - Rethinking Web with React and Flux
 
Finding Restfulness - Madrid.rb April 2014
Finding Restfulness - Madrid.rb April 2014Finding Restfulness - Madrid.rb April 2014
Finding Restfulness - Madrid.rb April 2014
 
Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning C
 

More from Almog Baku (6)

gRPC in Go
gRPC in GogRPC in Go
gRPC in Go
 
Android is going to Go! Android and Golang
Android is going to Go! Android and GolangAndroid is going to Go! Android and Golang
Android is going to Go! Android and Golang
 
Symfony2 form type
Symfony2 form typeSymfony2 form type
Symfony2 form type
 
Turbo theming: Introduction to Sass & Compass
Turbo theming: Introduction to Sass & CompassTurbo theming: Introduction to Sass & Compass
Turbo theming: Introduction to Sass & Compass
 
Wordpress optimization
Wordpress optimizationWordpress optimization
Wordpress optimization
 
Drupal & javascript
Drupal & javascriptDrupal & javascript
Drupal & javascript
 

Recently uploaded

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 

Build REST API clients for AngularJS

  • 1. Build REST API client like a BOSS Build RESTful API clients for AngularJS, the proper way
  • 2. Who are you? @AlmogBaku nice to meet ya` 1. Entrepreneur 2. Co-Founder & CTO @ Rimoto 3. Developer for 10 years 4. GitHub addicted. 5. Blog about entrepreneurship and development: www.AlmogBaku.com
  • 3. What are we going to talk about? ● What tha’ heck is REST? ● Why $resource is sucks? ● $http ● Say hi to Restangular ● Do it like a boss
  • 4. Disclaimer You wanna know more? Google it!
  • 5. What tha’ heck is REST? Representational State Transfer
  • 7. What is API? API is a layer that connects two applications. Application Programing Interface
  • 8. What is API? API is actually a common language, that both of the parties knows.
  • 9. REST REST is a Client-Server API
  • 10. REST REST is just the regular way the internet works! GET http://google.com/
  • 11. REST REST is just the regular way the internet works! GET http://google.com/RESPONSE 200 OK
  • 12. REST REST is about resources, not about functions. Book store api: 1. /api/authors/ 2. /api/authors/:authorId/ 3. /api/authors/:authorId/books/ 4. /api/authors/:authorId/books/:bookId 5. /api/authors/:authorId/books/:bookId/reviews 6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
  • 13. REST REST is about resources, not about functions. Book store api: 1. /api/authors/ 2. /api/authors/:authorId/ 3. /api/authors/:authorId/books/ 4. /api/authors/:authorId/books/:bookId 5. /api/authors/:authorId/books/:bookId/reviews 6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
  • 14. REST GET /api/authors/ [ { "id": 7, "name": "J.R.R. Tolkien", "birthday": "1-3-1892" }, { "id": 183, "name": "Douglas Adams", "birthday": "3-11-1952" } ]
  • 15. REST REST is about resources, not about functions. Book store api: 1. /api/authors/ 2. /api/authors/:authorId/ 3. /api/authors/:authorId/books/ 4. /api/authors/:authorId/books/:bookId 5. /api/authors/:authorId/books/:bookId/reviews 6. /api/authors/:authorId/books/:bookId/reviews/:reviewId
  • 16. REST GET /api/authors/187/ { "id": 183, "name": "J.R.R. Tolkien", "full_name": "John Ronald Reuel Tolkien", "birthday": "1-3-1892", "genre": "SciFi" }
  • 17. REST The same URIs can do many different actions... We can request web pages in one of the following methods: 1. GET - request information about resource 2. POST - create new resource 3. PUT - update resource 4. DELETE - delete resource 5. HEAD - get information only with headers (eg. if resource exists) 6. OPTIONS - list of available methods to the resource (like --help)
  • 18. REST Errors are simple http errors 200 - OK 404 - Not found 401 - Unauthorized 500 - Server Error Etc.
  • 19. REST REST is Stateless - You can’t use cookies - You need to pass your identification in every request GET /users/me?access_token=ftjhi89uh5982hbrvt92vgt9qvhg2r0219
  • 21. REST with AngularJS It’s pretty simple actually.. just use $resource var Author = $resource('/api/v1/author/:authorId', {authorId:'@id'}); Author.get({authorId:183}, function(author) { author.name = 'J.R.R. Tolkien'; author.$save(); });
  • 22. The thing is… It just sucks
  • 23. The thing is… It just sucks 1. It can be very complex... var Author = $resource('https://api.rimoto.net/api/v1/author/:authorId', {authorId:'@id'}); Author.get({authorId:183}, function(author) { author.name = 'J.R.R. Tolkien'; author.$save(); }); var Book = $resource('https://.../api/v1/author/:authorId/books/:bookId', {authorId: 183, bookId:'@id'}); Book.get({bookrId:2}, function(book) { book.name = 'Lord of the rings'; book.$save(); });
  • 24. The thing is… It just sucks 2. Doesn’t allow you to parse the API 3. No way to set base url application wide 4. You can’t handle errors application wide 5. You can’t handle headers application wide 6. You can’t handle anything application wide Actually- $resource is okay for anything other than serious apps.
  • 25. What can we do? We can use $http, in order to add necessary headers: We can also use the $http interceptor, in order to handle errors... var req = { method: 'POST', url: 'http://example.com', headers: { 'Content-Type': 'application/json' }, data: { test: 'test' } }; $http(req).success(function(){...}).error(function(){...});
  • 26. What can we do? We can also use the $http interceptor, in order to handle errors... $provide.factory('myHttpInterceptor', function($q, dependency1) { return { 'requestError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); }, 'response': function(response) { //parsing here.... return response; }, 'responseError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); } }; }); $httpProvider.interceptors.push('myHttpInterceptor');
  • 27. What can we do? We can also use the $http interceptor, in order to handle errors... $provide.factory('myHttpInterceptor', function($q, dependency1) { return { 'requestError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); }, 'response': function(response) { //parsing here.... return response; }, 'responseError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); } }; }); $httpProvider.interceptors.push('myHttpInterceptor');
  • 28. What can we do? We can also use the $http interceptor, in order to handle errors... $provide.factory('myHttpInterceptor', function($q, dependency1) { return { 'requestError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); }, 'response': function(response) { //parsing here.... return response; }, 'responseError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); } }; }); $httpProvider.interceptors.push('myHttpInterceptor');
  • 29. What can we do? We can also use the $http interceptor, in order to handle errors... $provide.factory('myHttpInterceptor', function($q, dependency1) { return { 'requestError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); }, 'response': function(response) { //parsing here.... return response; }, 'responseError': function(rejection) { // do something on error if (canRecover(rejection)) { return responseOrNewPromise } return $q.reject(rejection); } }; }); $httpProvider.interceptors.push('myHttpInterceptor');
  • 30.
  • 32. Restangular 1. Restangular solves ‘em all! 2. Published on 2013 3. Very stable and popular angular-module 4. Active community 5. Allows you to configure your REST API in application level 6. Restangular 2 will support AngularJS 2! (WIP) 7. Very easy to use
  • 33. Configurations Define initial settings: Defining base url: Defining Content-Type headers: RestangularProvider.setBaseUrl('http://api.rimoto.net/api/v1/'); RestangularConfigurer.setDefaultHeaders({'Content-Type': 'application/json'});
  • 34. Say hi to Restangular Let’s create a new author: var Authors = Restangular.all('authors'); Authors.post({ name: "J.R.R. Tolkien" });
  • 35. Say hi to Restangular Lets’ create a new author: var Authors = Restangular.all('authors'); Authors.post({ name: "J.R.R. Tolkien" }); POST http://api.rimoto.net/api/v1/authors/
  • 36. Say hi to Restangular Lets’ create a new author: var Authors = Restangular.all('authors'); Authors.post({ name: "J.R.R. Tolkien" });
  • 37. Say hi to Restangular Get the author: Restangular.one('authors', 183).get() .then(function(author) { $scope.author = author; }) ;
  • 38. Say hi to Restangular Get the author: Restangular.one('authors', 183).get() .then(function(author) { $scope.author = author; }) ; GET http://api.rimoto.net/api/v1/authors/183
  • 39. Say hi to Restangular Get all his books: $scope.author.getList('books') .then(function(books) { var firstBook = books[0]; firstBook.name="The Hobbit"; firstBook.put(); }) ;
  • 41. Model parsing RestangularConfigurer.ExtendModel("books", function(book) { book.published = new Date(book.published); return book; }); We can “transform” data from our API to javascript!
  • 42. Model parsing <div class="vote-box"> <button ng-click="voteUp($review)" class="up"><i class="up-arrow"></i></button> <div>{{votes|number}}</div> <button ng-click="voteDown($review)" class="down"><i class="down-arrow"></i></button> </div>
  • 43. Model parsing <div class="vote-box"> <button ng-click="voteUp($review)" class="up"><i class="up-arrow"></i></button> <div>{{votes|number}}</div> <button ng-click="voteDown($review)" class="down"><i class="down-arrow"></i></button> </div> Vote done on the controller
  • 44. Model function But it’s an API function!
  • 45. Model parsing How can we solve that?
  • 46. Model parsing How can we solve that? 1. Create a transformer 2. Add the function to the model! 3. Fin.
  • 47. Model parsing How can we solve that? 1. Create a transformer 2. Add the model this function! 3. Fin. RestangularConfigurer.ExtendModel("review", function(review) { review.voteUp = function() { return review.getAll("votes").post({ vote_up: true }); }; return review; });
  • 48. Model parsing We can do use this tool for many cases: 1. Ordering lists 2. Special parsing 3. Add functions 4. Etc.
  • 49. What about errors? RestangularConfigurer.setErrorInterceptor(function(response) { if([401, 403, 405].indexOf(response.status)!=-1) { logout(); return false; } });
  • 50. Build REST client like a BOSS
  • 51. PRO tips Bundle your whole API as “SDK”, and extend the Restangular to be your own API service: module .factory('API', ['Restangular', function(Restangular) { angular.extend(this, Restangular.withConfig(function(RestangularConfigurer) { RestangularConfigurer.setBaseUrl("https://api.rimoto.net"); RestangularConfigurer.setRequestSuffix('/'); RestangularConfigurer.setDefaultHeaders({ Accept: 'application/json;v=1' }); })); return this; }]) ;
  • 52. PRO tips 1. You can set the `id` parameter (eg. for mongodb): RestangularProvider.setRestangularFields({ id: '_id' });
  • 53. PRO tips 2. Handle the Access-Tokens on application level Example for Restangular with ngAuth: /** Login changed **/ $rootScope.$on("Auth.status", function(event, response) { if(response.access_token) { Restangular.setDefaultRequestParams({ access_token: response.access_token }); } else { Restangular.setDefaultRequestParams({ access_token: null }); } });
  • 54. PRO tips 3. Decouple Restangular to models 4. You can define Restangular to use HATEOAS 5. Keep your API service generic, and handle specific use-cases separately. module.factory('Users', function(Restangular) { return Restangular.service('users'); }); RestangularProvider.setRestangularFields({ selfLink: 'self.link' });
  • 56. Be creative, and create your own API