WebServices

Inhaltsübersicht

  • WebServices Grundlagen
    • Service Oriented Architecture
    • W3C WebService Standards
      • WSDL
      • SOAP
    • OASIS WebService Committees
    • XML-RPC
    • JSON-RPC
  • WebService Bibliothek Ladon
    • JSON-WSP
    • Beispiel
  • Telegram
    • Telegram Clients
    • Protocol MTProto
    • Bots
      • Bots Developer Links
      • Bots Python Bibliotheken
      • Bots Beispiele
  • Nylas
    • Nylas Protocol
    • Nylas Cloud
    • Nylas API

Leistungsnachweis "WebServices"

Überlegen sie sich eine Idee für einen Telegram Bot und setzen ihn über die Telegram Bot Python Libraries (Telepot, AioTelegramBot, twx.botapi) um. Wenn sie eine sehr kreative und interessante Idee haben, dann wäre es denkbar, an dem Telegram Bot Prize Wettbewerb teilzunehmen !

Falls sie keine eigene Idee haben: Entwickeln sie einen einfachen (oder auch einen wissenschaftlichen) Taschenrechner als Telegram Bot.

Erstellen sie Bilder ihres Bot und eine entsprechende Beschreibung in einem IPython Notebook und geben dieses zusammen mit dem gesamten lauffähigen Code als Archiv ab.

Webservices Grundlagen

Service Oriented Architecture

OASIS (Organization for the Advancement of Structured Information Standards) ist ein Nonprofit Consortium, welches die Entwicklung, Konvergenz und Adaption von offenen Standards für die globale Informationsgesellschaft weitertreibt.

Im OASIS Standard Reference Model for Service Oriented Architecture 1.0 vom 12. Oktober 2006 wird

Service Oriented Architecture definiert als Paradigma für die Organisation und Nutzung verteilter Funktionalitäten, die unterschiedlichen Besitzern untersteht.

W3C Webservice Standards

In [1]:
from IPython.display import IFrame, HTML, Markdown
IFrame('https://www.w3.org/2002/ws/#documents', width='100%', height=400)
Out[1]:

WSDL - Web Services Description Language

In dem WSDL Primer ist ein Beispiel einer WSDL Beschreibung für die Reservierung einer Hotelbuchung aufgeführt.

This document describes the GreatH Web service. Additional application-level requirements for use of this service -- beyond what WSDL 2.0 is able to describe -- are available at http://greath.example.com/2004/reservation-documentation.html

SOAP - Webservices Protocol

In dem SOAP Primer ist ein Beispiel einer SOAP Nachricht für die Reservierung einer Reise aufgeführt.

uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d 2001-11-29T13:20:00.000-05:00 Åke Jógvan Øyvind New York Los Angeles 2001-12-14 late afternoon aisle Los Angeles New York 2001-12-20 mid-morning none

Die obigen W3C Recommendations (siehe W3C WebService Activity Group) führten letztendlich zu einer Reihe von Committees und damit Standards bei OASIS (siehe OASIS WebServices Committees)

OASIS WebService Standards

In [2]:
from IPython.display import IFrame
IFrame('http://www.oasis-open.org/committees/tc_cat.php?cat=ws', width='100%', height=1080)
Out[2]:

XML-RPC

XML-RPC benutzt HTTP als Nachrichtenaustausch-Protokoll und XML als Format für die Datenrepräsentation und ist für sehr viele Programmiersprachen implementiert

XML-RPC Request

HTTP-Header:

  • A User-Agent and Host must be specified.
  • The Content-Type is text/xml.
  • The Content-Length must be specified and must be correct.

HTTP Body:

<!ELEMENT methodCall (methodName, params?) > <!ELEMENT methodNamel (#PCDATA) > <!ELEMENT params (param) > <!ELEMENT param (value) > <!ELEMENT value (i4|int|boolean|string|double|datetime.iso8601|base64|struct|array) > <!ELEMENT struct (member) > <!ELEMENT member (name,value) > <!ELEMENT array (data) > <!ELEMENT data (value*) >

XML-RPC Response

HTTP-Header:

  • Return: 200 OK
  • The Content-Type is text/xml.
  • The Content-Length must be specified and must be correct.

HTTP Body:

<!ELEMENT methodResponse (params|fault) > <!ELEMENT params (param) > <!ELEMENT param (value) > <!ELEMENT value (i4|int|boolean|string|double|datetime.iso8601|base64|struct|array) > <!ELEMENT struct (member) > <!ELEMENT member (name,value) > <!ELEMENT array (data) > <!ELEMENT data (value) >

XML-RPC Beispiel

Request
POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: localhost
Content-Type: text/xml 
Content-length: 207

<?xml version="1.0"?>
<methodCall> 
 <methodName>sample.sumAndDifference</methodName> 
 <params> 
  <param>
   <value><int>2</int></value>
  </param>
  <param>
   <value><int>5</int></value>
  </param>
 </params>
</methodCall>
Response
POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: localhost
Content-Type: text/xml 
Content-length: 263

<?xml version='1.0'?>
<methodResponse>
 <params>
  <param>
   <value>
    <struct>
     <member>
      <name>sum</name>
       <value><int>7</int></value>
     </member>
     <member>
      <name>difference</name>
       <value><int>-3</int></value>
     </member>
    </struct>
   </value>
  </param>
 </params>
</methodResponse>

XML-RPC Python Implementierung

In [ ]:
%%writefile xmlrpcserver.py
from xmlrpc.server import SimpleXMLRPCServer

class MyFuncs:
    def div(self, x, y) : return x // y

class example:
    def sumAndDifference(self, x, y):
        return {'sum':x+y,'difference':x-y}

sample = example()

server = SimpleXMLRPCServer(("localhost", 8088))
server.register_function(pow)
server.register_function(lambda x,y: x+y, 'add')
server.register_function(sample.sumAndDifference, 'sample.sumAndDifference')
server.register_introspection_functions()
server.register_instance(MyFuncs())
server.serve_forever()
In [ ]:
%%writefile xmlrpcclient.py
# simple test program (from the XML-RPC specification)
from xmlrpc.client import ServerProxy
import sys

server = ServerProxy("http://localhost:8088") # local server

print(server)

if len(sys.argv) >= 2:
  f = int(sys.argv[1])
  s = int(sys.argv[2])
else:
  f = 2
  s = 5
try:
    # Dieser Teil ist nur auf dem PythonServer installiert
    print("+-"*20)
    print("all remote Methods:")
    for m in server.system.listMethods():
      print(m)
    print("+-"*20)
    print("result of add(%i,%i):" % (f,s))
    print(server.add(f,s))
    print("result of pow(%i,%i):" % (f,s))
    print(server.pow(f,s))
    print("result of div(%i,%i):" % (f,s))
    print(server.div(f,s))
    print("+-"*20)
except:
    pass
    
try:
    print("result of sample.sumAndDifference(%i,%i):" % (f,s))
    result = server.sample.sumAndDifference(f,s)
    print(result)
    print("Sum:", result['sum'])
    print("Difference:", result['difference'])
except StandardError as v:
    print("ERROR", v)

JSON-RPC

JSON-RPC ist eine leichtgewichtiges Remote Procedure Call Protokoll mit dem Ziel einer einfachen Schnittstelle. Daher sind auch viele Implementationen von JSON-RPC entwickelt worden.

Webservice Bibliothek Ladon

Ladon ist ein Framework sowohl für Python als auch PHP zur Veröffentlichung von Methoden für unterschiedliche Internet Service Protokolle:

  • SOAP 1.0
  • SOAP 1.1
  • XML-RPC
  • JSON-RPC
  • JSON-WSP

Sobald eine Methode ladonized ist, ist sie automatisch über alle Interfaces der entsprechenden Ladon Installation bekannt. Ladon's Interface Implementationen sind in einer modularen Art und Weise erstellt, sodass eine Erweiterung der Ladon Protokoll Unterstützung einfach wird.

Ladon Python Dokumentation

JSON-WSP

JSON-WSP (JSON-WebServiceProtocol) wurde im wesentlichen von JSON-RPC beeinflusst und wegen der fehlenden Beschreibungssprache (analog WSDL (s.o.)) von dem Autor von Ladon entwickelt. Allerdings ist JSON-WSP im Gegensatz zu den Implementationen von JSON-RPC nur in Ladon implementiert.

Beispiel Calculator

In [ ]:
%%writefile Calculator.py
from ladon.ladonizer import ladonize

class Calculator(object):
  """
  This service does the math, and serves as example for new potential Ladon users.
  """
  @ladonize(int,int,rtype=int)
  def add(self,a,b):
    """
    Add two integers together and return the result

    @param a: 1st integer
    @param b: 2nd integer
    @rtype: The result of the addition
    """
    return a+b

SOAP

In [ ]:
%%html
<wsdl:definitions name="Calculator" targetNamespace="urn:Calculator">
 <wsdl:types>
  <xsd:schema targetNamespace="urn:Calculator">
   <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
  </xsd:schema>
 </wsdl:types>
 <wsdl:message name="add">
  <wsdl:part name="a" type="xsd:long"/>
  <wsdl:part name="b" type="xsd:long"/>
 </wsdl:message>
 <wsdl:message name="addResponse">
  <wsdl:part name="result" type="xsd:long"/>
 </wsdl:message>
 <wsdl:portType name="CalculatorPortType">
  <wsdl:operation name="add">
   <wsdl:documentation>Add two integers together and return the result</wsdl:documentation>
   <wsdl:input message="tns:add"/>
   <wsdl:output message="tns:addResponse"/>
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:binding name="Calculator" type="tns:CalculatorPortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name="add">
   <soap:operation soapAction="http://localhost:8080/Calculator/soap11/add" style="rpc"/>
   <wsdl:input>
    <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:Calculator" use="encoded"/>
   </wsdl:input>
   <wsdl:output>
    <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:Calculator" use="encoded"/>
   </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="Calculator">
  <wsdl:documentation>Ladon generated service definition</wsdl:documentation>
  <wsdl:port binding="tns:Calculator" name="Calculator">
   <soap:address location="http://localhost:8080/Calculator/soap11"/>
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>

XML-RPC

In [ ]:
%%html
<service name="Calculator" ns="" url="http://localhost:8080/Calculator/xmlrpc">
 <types/>
 <methods>
  <method name="add" result="int">
   <param type="int">a</param>
   <param type="int">b</param>
  </method>
 </methods>
</service>

JSON-RPC

In [ ]:
%%javascript
var json = {
  "servicename": "Calculator", 
  "types": {}, 
  "type": "jsonrpc/description", 
  "url": "http://localhost:8080/Calculator/jsonrpc10", 
  "methods": 
  {
    "add": 
    {
      "doc_lines": 
      [
        "Add two integers together and return the result", 
        ""
      ],
      "params": 
      {
        "a": 
        {
          "doc_lines": 
          [
            "1st integer"
          ],
          "optional": false, 
          "type": "number", 
          "def_order": 1
        },
        "b": 
        {
          "doc_lines": 
          [
            "2nd integer"
          ],
          "optional": false, 
          "type": "number", 
          "def_order": 2
        }
      }, 
      "ret_info": 
      {
        "doc_lines": 
        [
          "The result of the addition"
        ], 
        "type": "number"
      }
    }
  },
  "version": "1.0"
}

JSON-WSP

In [ ]:
%%javascript
var json = {
  "servicename": "Calculator", 
  "types": {}, 
  "type": "jsonwsp/description", 
  "url": "http://localhost:8080/Calculator/jsonwsp", 
  "methods": 
  {
    "add": 
    {
      "doc_lines": [], 
      "params": 
      {
        "a": 
        {
          "doc_lines": [], 
          "optional": false, 
          "type": "number", 
          "def_order": 1
        }, 
        "b": 
        {
          "doc_lines": [], 
          "optional": false, 
          "type": "number", 
          "def_order": 2
        }
      }, 
      "ret_info": 
      {
        "doc_lines": [], 
        "type": "number"
      }
    }
  }, 
  "version": "1.1"
}
In [ ]:
%%writefile clienttest.py
# -*- coding: utf-8 -*-

from ladon.clients.jsonwsp import JSONWSPClient
import pprint,os

base_url = 'http://localhost:8080'

def print_result(jsonwsp_resp):
    if jsonwsp_resp.status == 200:
        if 'result' in jsonwsp_resp.response_dict:
            pprint.pprint(jsonwsp_resp.response_dict['result'],indent=2)
        else:
            pprint.pprint(jsonwsp_resp.response_dict)
    else:
        print("A problem occured while communicating with the service:\n")
        print(jsonwsp_resp.response_body)

def testCalculator():

    global base_url
    print("\n\nTesting Calculator:\n")
    # Load the Calculator description
    
    calc_client = JSONWSPClient(base_url + '/Calculator/jsonwsp/description')

    # Add the numbers 23 and 45
    jsonwsp_resp = calc_client.add(a=23,b=45)
    print_result(jsonwsp_resp)

Telegram

Telegram ist eine WhatsApp-Alternative für die eine offizielle Telegram API zur Verfügung steht. Das zwischen Client und Server verwendete Protokoll MTProto steht ebenfalls offen zur Verfügung.

Telegram läuft mit der Synchronisation über einen eigenen Telegram-Server auf unterschiedlichsten Geräten (Smartphones, Tablets, PC's) gleichermaßen ab.

Es läuft zwischen Client und Server generell eine verschlüsselte Kommunikation ab, allerdings werden auf dem Server die Messages nicht verschlüsselt abgespeichert (siehe Schematic Presentation of Messages). Eine verschlüsselte Ende-zu-Ende-Kommunikation (Secret Chats) wird ebenfalls angeboten, die aber dann nicht auf dem Server gespeichert wird. Nachrichten über diesen Secret Chat können auch zeitgesteuert automatisch selbst zerstört werden.

Protokoll MTProto

Das Telegram Protokoll MTProto verwendet als Basis der Übertragung eine Type Language, in der alle Typen und Funktionen durch ihre CRC32 Repräsentationen umgesetzt werden um damit Remote Procedure Calls sehr effizient übertragen zu können.

Telegram Clients

Auf der Webseite Applications stehen diverse Clients für unterschiedlichste Betriebssysteme zur Verfügung. Für einige steht auch der Source Code auf GitHub.

Für Linux, Mac (und entsprechende Windows Portables wie cygwin, wubi, coLinux oder in Zukunft auch Windows Subsystem for Linux (WSL)) gibt es auch einen Client als Command Line Interface, den Telegram Messenger CLI mit Python Bindings.

Bots

Neben der offiziellen Telegram API existiert noch eine weitere API, die Telegram Bots API zur Anbindung von Bots an das Telegram System.

Telegram Bots sind spezielle Accounts, die keine Telefonnummer zur Einrichtung des Accounts benötigen. Diese Accounts dienen als Schnittstelle für Programme die irgendwo auf irgendwelchen Servern laufen.

Bots Python Bibliotheken

Bots Beispiele

Nylas

Naylas N1 ist eine erweiterbare Open Source E-Mail App mit vielen Features u.a. Schlummertaste, verbesserte Kontakte, Themes, automatische Zuordnung, später Versenden, schnelle Antworten, Plugins, Mail Zusammenführung, etc.

Nylas API

Die Nylas Platform stellt eine moderne API zur Verfügung, die mit derzeitigen E-Mail Providern zusammenarbeitet. Dies erlaubt eine einfache und schnelle Integration einer App mit den E-Mail-, Kontakt- oder Kalender-Daten eines Benutzers und eliminiert dadurch die Verwendung alter und nicht einfach zu bedienender Protokoile woe IMAP oder MIME.

Die API basiert auf der REST (Representational State Transfer) Technologie, die einfache und vorhersehbare URIs für den Zugang und Veränderung von Objekten zur Verfügung stellt. Requests unterstützen die Standard HTTP Methoden wie GET, PUT, POST, und DELETE und Standard Status Codes. Response Bodies sind immer UTF-8 encodierte JSON Objecte, solange es nicht explizit anderweitig beschrieben ist.

Es exisitieren bereits verschiedene Bibliotheken, u.a. eine Nylas Python Bibliothek

Nylas Cloud

Die Nylas Cloud steht für die folgenden Eigenschaften:

  • Einfache APIs für E-Mail, Kontakte und Kalender.
  • Integration in Minuten anstelle von Monaten. Nylas Cloud fokussiert die Features auf die Usability für Nutzer und nicht auf die Infrastruktur.
  • Erstellt von Entwicklern für Entwickler.
  • Nylas bringt E-Mail in das 21. Jahrhundert mit API's die die Komplexität von Microsoft Exchange, IMAP, SMTP und MIME abstrahiert und vereinfacht.
  • Skaliert von Megabytes zu Petabytes.
  • Für einzelne Mailbox-Nutzer bis hin zu Hunderttausenden. Nylas Cloud skaliert für alle Anwendungen.