REST API in Practice: What, why and how
Your Code
Your Code
Class Foo
Class Bar
Your Code
Class Foo
Foo.X()
Class Bar
Bar.A()
Your Code
Class Foo
Foo.X()
Foo._Y()
Class Bar
Bar.A()
Bar._B()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
Private methods used by Foo.X()
Private methods used by Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
You want to provide this service to your client
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
How?
You want to provide this service to your client
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
Just give the source code to your client
var Foo = require('./YourCode/Foo.js');
var Bar = require('./YourCode/Bar.js');
let f = new Foo();
let b = new Bar();
f.X();
b.A();
// So much win
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
What's the problem with this solution?
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
Your client doesn't know how to write code
var Foo = require('./YourCode/Foo.js');
var Bar = require('./YourCode/Bar.js');
let f = new Foo();
let b = new Bar();
f.X();
b.A();
// So much win
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
Oh! There's another problem!
var Foo = require('./YourCode/Foo.js');
var Bar = require('./YourCode/Bar.js');
let f = new Foo();
let b = new Bar();
f.X();
b.A();
// So much win
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
You don't want to expose your code
var Foo = require('./YourCode/Foo.js');
var Bar = require('./YourCode/Bar.js');
let f = new Foo();
let b = new Bar();
f.X();
b.A();
// So much win
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
What's your solution now?
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
What's your solution now?
"Expose a simple API" - you say
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
But how to expose this service without exposing your code?
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Request
Response
What's a server anyway?
What's a server anyway?
A simple loop always listening for requests
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
What's missing?
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
The main glue
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
Endpoints
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
Endpoints
/bar
/foo
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
Endpoints
/bar
/foo
that.get("/bar", Bar.A())
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
Endpoints
/bar
/foo
that.get("/bar", Bar.A())
that.get("/foo", Foo.X())
API
Foo.X()
Bar.A()
Your Code
Class Foo
Class Bar
Foo.X()
Foo._Y()
Foo._Z()
Bar.A()
Bar._B()
Bar._C()
JSON
JSON
HTTP Requests
Server
Req
Res
Endpoints
/bar
/foo
The flow of a request
Incoming request (JSON wrapped in HTTP)
The flow of a request
Incoming request (JSON wrapped in HTTP)
Server forwards to a endpoint
/foo
/bar
The flow of a request
Incoming request (JSON wrapped in HTTP)
Server forwards to a endpoint
/foo
/bar
The flow of a request
Incoming request (JSON wrapped in HTTP)
Server forwards to a endpoint
/foo
/bar
Server calls the method (Server.Foo.X())
The flow of a request
Incoming request (JSON wrapped in HTTP)
Server forwards to a endpoint
/foo
/bar
Server calls the method (Server.Foo.X())
Foo.X() processes the request and return response
Core logic
e.g: addDataset()
Core logic
e.g: addDataset()
Server method to handle Req/Res
e.g: Server.Dataset()
Core logic
e.g: addDataset()
Server method to handle Req/Res
Endpoint that will call a server method to handle the request
e.g: that.server.put("/dataset/:id", Server.dataset())
e.g: Server.Dataset()
How the addDataset would look like as a REST API service
How the addDataset would look like as a REST API service
that.rest.put('dataset/:id', SomeClass.putDataset);
How the addDataset would look like as a REST API service
putDataset (req: restify.Request, res: restify.Response, next: restify.Next) {
// Get the dataset data coming from the request
let dataStr = new Buffer(req.params.body).toString('base64');
let iFacade = new InsightFacade();
let datasetName = req.params.id;
// Call your good old AddDataset() -- Remember it is an ASYNC function!!
// ...
// ...
// ...
// Write to response object the code you're returning
res.status(value.code);
// Write to response object the json data you're returning
res.json(value);
// Return this. Because.
return next();
}
How the addDataset would look like as a REST API service
it("It should be able to put the dataset", function () {
// Point to your local test dataset
let file = __dirname + "/rooms.zip";
// Make the request to your local machine (you are running the server locally)
return chai.request('http://localhost:4321')
.put('/dataset/rooms')
.attach("body", fs.readFileSync(file), file)
.then(function (res: restify.Response) {
//Log.trace('then:' + JSON.stringify(res));
expect(res.status).to.equal(204);
})
});
REST API in Practice: What, why and how v2
By Rodrigo Araújo
REST API in Practice: What, why and how v2
- 1,500