architecture delphi from soap to rest json http

50
April 2014 RSI From SOAP to REST Arnaud Bouchez

Upload: arnaud-bouchez

Post on 25-May-2015

1.101 views

Category:

Software


14 download

DESCRIPTION

Introduces REST design, for building a Service Oriented Architecture (SOA) with JSON and HTTP, in the context of modern Delphi applications, AJAX clients and the Open Source Synopse mORMot framework.

TRANSCRIPT

Page 1: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

From SOAP to RESTArnaud Bouchez

Page 2: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

From SOAP to REST

SOAP REST JSON Security practice

From SOAP to REST

Page 3: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

Simple Object Access Protocol

SOAP XML WSDL Defines

Processing model  Extensibility model Underlying protocol binding Message construct

From SOAP to REST

Page 4: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

Simple Object Access Protocol

Standard Feature complete Time proof

Several implementations

(1.0/1.1/WCF/J2EE) Verbose and heavy (slow) Complex

From SOAP to REST

Page 5: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST

From SOAP to REST

Page 6: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REpresentational State Transfer Share the 5 basic fundamentals of the web:

Everything is a resource Every resource is identified

by a unique identifier Use simple and uniform interfaces Communication is done by representation Every request is stateless

And share the same author as HTTP(Roy Fielding)

From SOAP to REST

Page 7: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST is Resource-based

On Internet, data can be: web page, image, video, file, etc. It can also be dynamic output like

“get customers who are newly subscribed”

With REST, we start thinking in terms of resources rather than physical files or API

From SOAP to REST

Page 8: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST Unique Identifier

You access the resource via its URI http://www.mysite.com/pictures/logo.png

Image Resource

http://www.mysite.com/index.html Static Resource

http://www.mysite.com/Customer/1001 Dynamic Resource returning XML or JSON content

http://www.mysite.com/Customer/1001/Picture Dynamic Resource returning an image

From SOAP to REST

Page 9: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

Unique Identifier

Older web techniques, (aspx or ColdFusion), requested a resource by specifying parameters, e.g.http://www.mysite.com/Default.aspx?a=1;a=2&b=1&a=3

Several URIs may return the same data Evolving parameters

In REST, we add constraints to the URI In fact, every URI should uniquely

represent one item of the data collection

From SOAP to REST

Page 10: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST Unique Identifier Some URI samples:

Get Customer details with name “dupont”

http://www.mysite.com/Customer/dupont

Get Customer details with name “smith”

http://www.mysite.com/Customer/smith

Get orders placed by customer “dupont”

http://www.mysite.com/Customer/dupont/orders

From SOAP to REST

Page 11: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST Interfaces

Access those identified resourcesvia basic CRUD activity identified by a set of HTTP verbs GET Read PUT Update POST Create DELETE Delete

From SOAP to REST

Page 12: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST Interfaces

Combination of HTTP method and URI replace a list of English-based methods, like GetCustomer / InsertCustomer / UpdateOrder / RemoveOrder

From SOAP to REST

Page 13: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST Interfaces

From SOAP to REST

Page 14: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST is Stateless

Every request should be independent so that we can scale up (load balancing) so that modeling stays simple as HTTP/1.1 i.e. as an independent transaction

that is unrelated to any previous request Server-side is the only reference Need conflict resolution

(optimistic/pessimistic)

From SOAP to REST

Page 15: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

REST transfert by representation

What you are sending over the wire is in fact a representation of the actual resource data

As XML

As JSON

From SOAP to REST

<Customer> <ID>1234</ID> <Name>Dupond</Name> <Address>Tree street</Address> </Customer>

{"Customer":

{"ID":1234, "Name":"Dupond", "Address":"Tree street"}}

Page 16: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

JSON

JavaScript Object Notation (JSON) standard open and lightweight

text-based, human-readable formatfor representing simple data structures and associative arrays (called objects)

From SOAP to REST

Page 17: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

JSON types

Number 123.45 String “text” Boolean true/false Array [ ] Object { } Null null

+ non significant white spaces

From SOAP to REST

Page 18: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

JSON sample{ "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": 10021 }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" }; ]}

From SOAP to REST

Page 19: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

<Troll>XML</Troll> {"Troll":"JSON"}

JSON Truly human-readable Native AJAX / JavaScript format Compact (UTF-8 friendly) Simple to implement and use

XML Any complex (even custom) types SOAP standard Binary (CDATA) Validation (XSDL)

From SOAP to REST

Page 20: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

JSON/XML alternatives

Text INI TOML YAML

Binary BSON MessagePack Protocol Buffers WCF

From SOAP to REST

Page 21: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Security in Client-Server is usually implemented by: Process safety Authentication Authorization

From SOAP to REST

Page 22: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Process safety Code quality Testing Feedback, peer review Transmission encryption Do not reinvent the wheel

From SOAP to REST

Page 23: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Authentication Authentication (from Greek: "real" or "genuine",

from "author") is the act of confirming the truth of an attribute of a datum or entity. This might involve confirming the identity of a person or software program, tracing the origins of an artifact, or ensuring that a product is what its packaging and labeling claims to be. Authentication often involves verifying the validity of at least one form of identification.(Wikipedia)

From SOAP to REST

Page 24: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

RESTful Authentication HTTP basic auth over HTTPS

Not user-friendly (weird popup) Password is transmitted

Cookies and session management HTTP-based: not RESTful Man-In-the-Middle (MIM) and replay issues

Query Authentication with additional signature Each resource request is authenticated Signatures can be strong Can be stateless

From SOAP to REST

Page 25: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Query Authentication (one way to do it)For instance, a generic URI sample:GET /object?apiKey=Qwerty2010

should be transmitted as such: GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

The string being signed is "/object?apikey=Qwerty2010&timestamp=1261496500"

and the signature is the SHA-256 hash of that string using the private component of the API key.

From SOAP to REST

Page 26: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Authentication patterns

Password stored as hash N-way challenge Single sign-on Reinvent the wheel is unsafe

From SOAP to REST

Page 27: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

RESTful Security

Authorization

Define an access policy for the resources For an authenticated user May handle a guest user (public content) Via Access Control Lists (ACL),

capabilities or groups Following the principle of least privilege Part of a trust chain (e.g. AD token, LDAP)

From SOAP to REST

Page 28: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

From SOAP to REST

Page 29: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

RESTful Client-Server In-process

Stand-alone client, fast server-side access

Named pipes or GDI messages Stand-alone client, fast server-side access

HTTP/1.1 via kernel-mode http.sys API Part of the OS since Windows XP SP2 Kernel-mode execution, IOCP driven System-wide URI registration: share root and port Used by IIS and WCF Socket-based server is also available

From SOAP to REST

Page 30: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST design at class level

CRUD methods are inherited Follows Liskov substitution principle

TSQLRestServer

TSQLRest

TSQLRestClientURI

TSQLRestClient

Page 31: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST design at class level – Server side

Follows Open/Close principle

From SOAP to REST

TSQLRestServerDB

TSQLRestServer

TSQLRest

TSQLRestServerRemoteDB TSQLRestServerFullMemory

Page 32: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST design at class level – Server side TSQLRestServerDB for embedded SQLite3 code

For fast storage in a standard one-file database Virtual tables allow to access any external RDBMS

TSQLRestServerFullMemory for fast RAM storage Do not link the SQLite3 engine to the executable Rely on a efficient TObjectList class Persisted as JSON or compressed binary file

TSQLRestServerRemoteDB for proxy access

From SOAP to REST

Page 33: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST design at class level – Client side

Client classes are protocol-independent Local and remote access share the same

parent

From SOAP to REST

TSQLRestClientURINamedPipe

TSQLRestClientURI TSQLRestClient

TSQLRestClientURIMessage

TSQLRestClientURIDll

TSQLRestClientDBTSQLHttpClientWinINet

TSQLHttpClientWinGeneric

TSQLHttpClientGenericTSQLHttpClientWinHTTP

TSQLHttpClientWinSock

TSQLRest

Page 34: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

JSON and UTF-8 UTF-8 from the ground up

UTF-8 is Unicode Unicode even for Delphi < 2009 Dedicated RawUTF8 string type for business

logic

JSON used for transmission and internal storage for client-server ORM and SOA e.g. for cache on server or client side direct in-place parsing to avoid memory

allocationFrom SOAP to REST

Page 35: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Method-based services

Full access to the REST request Linked to mORMot’s resources (ORM tables) Defined as a published method Parameters and JSON marshalling Interface-based services are also available

From SOAP to REST

Page 36: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Defining a methodtype TSQLRestServerTest = class(TSQLRestServerFullMemory) (...) published procedure Sum(Ctxt: TSQLRestServerURIContext); end;

Implementing a methodprocedure TSQLRestServerTest.Sum(Ctxt: TSQLRestServerURIContext);begin with Ctxt do Results([Input['a']+Input['b']]);end;

From SOAP to REST

Page 37: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Automatic URI and JSON content marshalling For instance, the following request URI:

GET /root/Sum?a=3.12&b=4.2will let our server method return:

{"Result":7.32}

That is, a perfectly AJAX-friendly request With no restriction on the routing or

marshalling But not yet fully RESTful (where is the

resource?)From SOAP to REST

Page 38: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Resource-based method

URI to execute this RESTful method will be:GET root/People/1234/DataAsHex

From SOAP to REST

procedure TSQLRestServerTest.DataAsHex(Ctxt: TSQLRestServerURIContext); var aData: TSQLRawBlob; begin if (self=nil) or (Ctxt.Table<>TSQLRecordPeople) or (Ctxt.TableID<=0) then Ctxt.Error('Need a valid record and its ID') else if RetrieveBlob(TSQLRecordPeople,Ctxt.TableID,'Data',aData) then Ctxt.Results([SynCommons.BinToHex(aData)]) else Ctxt.Error('Impossible to retrieve the Data BLOB field'); end;

Page 39: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST routing defined by classes

From SOAP to REST

TSQLRestRoutingJSON_RPC

TSQLRestServerURIContext

TSQLRestRoutingREST

TSQLRestServerURIContext = class protected ... function URIDecodeREST: boolean; virtual; procedure URIDecodeSOAByMethod; virtual; procedure URIDecodeSOAByInterface; virtual; abstract; function Authenticate: boolean; virtual; procedure ExecuteSOAByMethod; virtual; procedure ExecuteSOAByInterface; virtual; abstract; procedure ExecuteORMGet; virtual; procedure ExecuteORMWrite; virtual; ...

Page 40: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

REST routing defined by classes

You can customize every aspect of the routingfor method-based services

JSON/RPC and REST are available by defaultfor interface-based services

Resource access via ORM is also customizable

From SOAP to REST

TSQLRestRoutingJSON_RPC

TSQLRestServerURIContext

TSQLRestRoutingREST

Page 41: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Authentication Modular and open: defined by classes Safe (timed challenge, SHA-256) Single sign-on via NTLM

From SOAP to REST

TSQLRestServerAuthenticationSSPI

TSQLRestServerAuthenticationSignedURI

TSQLRestServerAuthenticationURI

TSQLRestServerAuthenticationDefault

TSQLRestServerAuthentication

TSQLRestServerAuthenticationNone

Page 42: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s REST

Authorization Resource-based Customizable Users and Groups Can be tuned via code Integrated at framework core level

From SOAP to REST

ID : integerAccessRights : RawUTF8

Ident : RawUTF8SessionTimeout : integer

ID : integerData : TSQLRawBlob

DisplayName : RawUTF8GroupRights : TSQLAuthGroup

LogonName : RawUTF8PasswordHashHexa : RawUTF8

AuthGroup

Page 43: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

UTF-8 JSON from the ground up Optimized functions and classes

(TTextWriter) Bypass the RTL on purpose (e.g. Win64) SynCommons.pas unit shared by ORM, SynDB,

SOA Universal mean of transmission and storage Extended types (dates, BLOB) Dynamic arrays and variants support TDocVariant custom type for late-binding

From SOAP to REST

Page 44: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

Dynamic array wrapper TDynArray gives access

to any existing dynamic arrayvia high-level methodsCount / Add / Delete / Find …

TDynArrayHashed add hash-basedfast O(1) search of item values

External Count variable for much faster adding

Binary and JSON serialization

From SOAP to REST

Page 45: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

TDocVariant custom type Stores any transient value as document:

Object Array Any nested combination of the two

Low memory overhead Data allocation per blocks of variants Copy by reference can be enabled Instance lifetime managed by the compiler

Direct JSON support Late-binding magic

From SOAP to REST

Page 46: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

Create TDocVariant instances TDocVariant.New() _Obj() _ObjFast() _Arr() _ArrFast() _Json() _JsonFast() _JsonFmt() _JsonFastFmt()

_*() for per-value instances will copy the whole document content

_*Fast() for per-reference instances will copy a reference of the document content

From SOAP to REST

Page 47: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

TDocVariant custom type var V: variant; // stored as any variant ... TDocVariant.New(V); // or slightly slower V := TDocVariant.New; V.name := 'John'; // property accessed via late-binding V.year := 1972; // now V contains {"name":"john","year":1972}

var V1,V2: variant; ... V1 := _Obj(['name','John','year',1972]); V2 := _Obj(['name','John','doc',_Obj(['one',1,'two',2.5])]);

V1 := _Json('{"name":"John","year":1982}'); V2 := _Json('{name:"John",doc:["one",1,"two",2.5]}');

From SOAP to REST

Page 48: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

TDocVariant custom type writeln('name=',V1.name,' year=',V1.year); // will write 'name=John year=1972' writeln('name=',V2.name,' doc.one=',V2.doc.one,' doc.two=',doc.two); // will write 'name=John doc.one=1 doc.two=2.5

V1.name := 'Mark'; // overwrite a property value writeln(V1.name); // will write 'Mark' V1.age := 12; // add a property to the object writeln(V1.age); // will write '12' writeln(V1); // implicit conversion to string -> as JSON // will write '{"name":"Mark","year":1972,"age":12}' writeln(VariantSaveJSON(V1)); // serialize as RawUTF8 JSON

From SOAP to REST

Page 49: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

mORMot’s JSON

TDocVariant custom type Pseudo-methods:

_Json/_Count/_Kind for objects Add/Delete/Count/_ for arrays

var V: variant; ... V := _Json('{arr:[1,2]}'); writeln(V._Count); // will write 1 (one property in the V object) V.arr.Add(3); // will work, since V.arr is returned by reference (varByRef) writeln(V); // will write '{"arr":[1,2,3]}' V.arr.Delete(1); writeln(V); // will write '{"arr":[1,3]}‘

From SOAP to REST

Page 50: Architecture Delphi From SOAP to REST JSON HTTP

April 2014RSI

From SOAP to REST

Thanks to Bill Meyer for his review

Any feedback is welcome athttp://synopse.info