Web-API-as-a-Service

Web-APIs mit Azure-API-Apps betreiben
Kommentare

Azure-API-Apps erlauben auf einfache Weise den Betrieb von Web-APIs unter Azure. Sie ermöglichen das Veröffentlichen von Metadaten zum Generieren von Client-Proxies sowie eine einfache Verknüpfung mit externen Identity-Providern.

Die vor einigen Monaten eingeführten Azure App Services stellen eine Sammlung von Diensten für die Entwicklung und den Betrieb von webbasierten und mobilen Apps dar. Zu diesen Services gehören die bereits seit längerer Zeit bekannten Azure Web Sites, die sich nun Web-Apps nennen, sowie Azure Mobile Apps. Allerdings hat das Azure-Team im Zuge dessen auch zwei neue Dienste bereitgestellt: API-Apps unterstützen bei der Entwicklung von Web-API,s und Logic-Apps bieten Workflows für Integrationslösungen. Dieser Artikel wirft einen Blick auf ersteren. Als dieser Artikel verfasst wurde, lagen die API-Apps noch in einer Preview-Version vor, daher können sich bis zur Veröffentlichung der finalen Version Änderungen ergeben.

Möglichkeiten von API-Apps

Zur Erstellung von API-Apps können Entwickler derzeit auf Java, Node.js sowie .NET zurückgreifen. Im hier betrachteten Fall kommt ASP.NET Web API zum Einsatz. Metadaten über die Services werden dabei mittels Swagger veröffentlicht. Dabei handelt es sich um einen weit verbreiteten Standard zur Beschreibung von HTTP-basierten Services. Basierend auf diesen Metadaten besteht die Möglichkeit zur Generierung von Proxies am Client. Diese Proxies nennt man auch schlicht Client-SDK oder SDK. Mittlerweile stehen für alle verbreiteten Plattformen Codegeneratoren zur Verfügung, die diese Aufgabe übernehmen. Das Azure SDK erweitert Visual Studio um entsprechende Optionen.

Nach dem Deployment in der Cloud kann der Entwickler die API-App im Azure-Portal konfigurieren. Dazu zählt auch das Hinzufügen von Regeln für die Authentifizierung und Autorisierung. Ähnlich wie von den Azure Mobile Services bekannt, können dazu auf einfache Weise verschiedene Identity-Provider, wie Google, Facebook oder Azure Active Directory, eingebunden werden. Daneben hat der Entwickler Zugriff auf die üblichen von Cloud-Umgebungen erwarteten Möglichkeiten, wie zum Beispiel dem Überwachen der Serviceauslastung oder dem Skalieren der Lösung.

Erstellen von API-Apps

Zum Erstellen einer neuen API-App nutzt der Entwickler in Visual Studio die Projektvorlage für ASP.NET. Anschließend wählt er die vom Azure SDK eingerichtete Option Azure API App (Preview). Das Ergebnis dieses Unterfangens ist das Grundgerüst einer Anwendung, die auf ASP.NET Web API basiert. Im Gegensatz zur Projektvorlage für ASP.NET Web API referenziert die hier betrachtete unter anderem das NuGet-Paket Swashbuckle. Dabei handelt es sich um eine verbreitete Communityimplementierung zur Nutzung von Swagger. Zur Erzeugung einer formalen Swagger-konformen API-Beschreibung greift Swashbuckle auf die Metadaten, die ASP.NET Web API über die gehosteten Services bereitstellt, zurück.

Die Konfiguration von Swagger erfolgt über die von der Projektvorlage im Ordner App_Start eingerichtete Datei SwaggerConfig, die die gleichnamige Klasse beherbergt. Diese Datei beinhaltet viele mögliche Einstellungen in auskommentierter Form. Für einen ersten Test bietet es sich an, den Kommentar vor dem Aufruf der Methode EnableSwaggerUi zu entfernen. Dies veranlasst Swashbuckle unter dem URL /swagger eine interaktive API-Dokumentation zu präsentieren, die es aus dem Swagger-Dokument generiert. Abbildung 1 zeigt einen Auszug aus einer solchen Dokumentation, die nicht nur Auskunft über die unterstützten Parameter und Datenformate gibt, sondern auch die Möglichkeit bietet, die betrachtete Aktion zum Testen anzustoßen.

Abb. 1: Auszug aus interaktiver Swagger-Doku

Abb. 1: Auszug aus interaktiver Swagger-Doku

URL-Konflikte lösen

Bei der Nutzung von Swagger ist zu beachten, dass pro HTTP-Verb und URL lediglich eine einzige serverseitige Methode erlaubt ist. Die von ASP.NET Web API gebotene Möglichkeit zur Auswahl einer Methode unter Berücksichtigung der übersendeten URL-Parameter kann der Entwickler aus diesem Grund nicht nutzen.

Um solche Kollisionen zu vermeiden, kann der Entwickler auf eigene Routen zurückgreifen, die den einzelnen Methoden eindeutige URLs verleihen. Ein Beispiel dafür findet sich in Listing 1. Hier würde die von der Projektvorlage standardmäßig eingerichtete Route api/{controller}/id sowohl die Methode GetAll als auch die Methode GetBySterne mit GET-Anfragen an den URL api/hotel assoziieren. Aus diesem Grund definiert das betrachtete Beispiel mittels Attribut-Routing für letztere Methode einen eigenen URL (api/hotel/bySterne/{minSterne}). Die Methode GetById ist von diesem Konflikt nicht betroffen, da hierfür die Standardroute ein eigenes URL-Segment mit einer ID vorsieht (api/hotel vs. api/hotel/4711).

Listing 1
[RoutePrefix("api/hotel")]
public class HotelController : ApiController
{
    private static List hotels;

    public HotelController()
    {
        if (hotels == null)
        {
            hotels = new List();
            [...]
        }
    }

    // GET api/hotel
    public List GetAll()
    {
        return hotels;
    }

    // GET api/hotel/{id}
    public Hotel GetById(int id)
    {
        return hotels.Where(h => h.Id == id).FirstOrDefault();
    }

    [Route("bySterne/{minSterne}")]
    public List GetBySterne(int minSterne)
    {
        return hotels.Where(h => h.Sterne >= minSterne).ToList();
    }

    public void PostHotel(Hotel hotel)
    {
        hotels.Add(hotel);
    }

}

Alternativ dazu bietet die Swashbuckle-Konfiguration in der Datei SwaggerConfig mit der Methode ResolveConflictingActions eine Möglichkeit, solche Konflikte programmatisch zu beheben: c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); Diese Methode erhält einen Lambda-Ausdruck, der konkurrierende Methodenbeschreibungen entgegennimmt und eine stattdessen für das Swagger-Dokument zu nutzende Methodenbeschreibung retourniert. Im betrachteten Fall liefert dieser Lambdaausdruck die erste der konkurrierenden Methodenbeschreibungen zurück. Alternativ dazu könnte die Auswahl der Methode jedoch auf komplexere Weise erfolgen. Statt einer der konkurrierenden Methodenbeschreibungen könnte der Entwickler die einzelnen Kandidaten auch zu einer einzigen Methodenbeschreibung für die Dokumentation zusammenfügen.

Deployment

Die Bereitstellung einer Azure-API-App kann, wie bei Azure-Diensten üblich, über den Bereitstellungsassistenten von Visual Studio erfolgen (Rechtsklick auf Projekt im Solution Explorer | Publish). Das Azure SDK fügt diesem Assistenten hierfür ein neues Veröffentlichungsziel, Microsoft Azure API Apps (Preview), hinzu. Das Erzeugen einer App kann im Zuge des Deployments mit diesem Assistenten erfolgen. Alternativ dazu kann der Entwickler eine App auch im neuen Azure-Portal anlegen und diese als Ziel der Bereitstellung auswählen.

Neben dem Bereitstellungsassistenten stehen die von Azure Web Sites gewohnten Deploymentverfahren zur Verfügung, darunter die Nutzung von GibHub-Repositories, Dropbox oder ein Deployment per Skripting.

Die Namen der im Azure-Portal eingerichteten API-Apps dürfen lediglich aus alphanumerischen Zeichen und Punkten bestehen. Während das Azure-Portal darauf mit einer Fehlermeldung hinweist, ist dies beim Anlegen einer API-App im Zuge einer Bereitstellung aus Visual Studio heraus aktuell nicht der Fall. Das Resultat ist ein Scheitern des Bereitstellungsvorgangs.

Clientprojekt und Proxy

Zum Generieren eines Proxys in einem Clientprojekt nutzt der Entwickler die vom Azure SDK eingerichtete Anweisung Add | Azure Api App Client im Kontextmenü des Solution Explorers (Abb. 2). Der auf diese Weise aufgerufene Dialog bietet die Möglichkeit, entweder eine API-App aus einem Azure-Konto auszuwählen oder eine Swagger-Datei direkt anzugeben. Letztere Option kann der Entwickler somit auch für Web-APIs, die nicht via Azure gehostet werden, nutzen.

Abb. 2: Proxy via Visual Studio generieren

Abb. 2: Proxy via Visual Studio generieren

Nach dem Bereitstellen der geforderten Informationen generiert Visual Studio einen Proxy. Listing 2 veranschaulicht die Funktionsweise von Proxys anhand der Methode GetAll des in Listing 1 gezeigten HotelControllers. Der Name des Proxys entspricht dem Namen der API-App. Er weist pro beschriebenem Web-API eine Eigenschaft auf. Über diese Eigenschaft lassen sich die angebotenen Methoden aufrufen.

Listing 2
var client = new Steyerhotels();
var hotels = client.Hotel.GetAll();

foreach (var hotel in hotels)
{
    Console.WriteLine(hotel.Name);
}

Neben den synchronen Proxy-Methoden liegen auch asynchrone Gegenstücke vor. Wer die gesamte empfangene HTTP-Nachricht lesen möchte, greift auf Methoden mit der Endung WithOperationResponseAsync zurück. Diese liefern eine Instanz von HttpOperationResponse<T>, die die HTTP-Nachricht über eine Eigenschaft Response des Typs HttpResponseMessage<T> repräsentiert (Listing 3).

Listing 3
var client = new Steyerhotels();
var result = client.Hotel.GetAllWithOperationResponseAsync().Result;
Console.WriteLine(result.Response.StatusCode);
var hotels = result.Body;

foreach (var hotel in hotels)
{
  Console.WriteLine(hotel.Name);
}

Um ausgehende Nachrichten zu beeinflussen, bietet der Proxy über eine Eigenschaft HttpClient die HttpClient-Instanz, die er auch zum Zugriff auf das Web-API heranzieht. Diese Instanz kann zum Beispiel genutzt werden, um standardmäßig zu übersendende Kopfzeilen festzulegen.

Security

Nach der Bereitstellung kann der Entwickler eine API-App im neuen Azure-Portal mit wenigen Klicks absichern. Im Zuge dessen kommen Identity-Provider, wie Google, Facebook oder Azure Active Directory zum Einsatz. Um die Kommunikation mit diesen Providern kümmert sich ein der API-App vorgeschaltetes Gateway. Es leitet unautorisierte Aufrufe an den Identity-Provider weiter. Nachdem sich der Benutzer dort angemeldet hat, erhält das Gateway ein Securitytoken, das er gegen ein eigenes Token, so genanntes Zumo-Token, tauscht. Zumo ist eine Azure-interne Bezeichnung für Azure Mobile Services. Dies zeigt, dass man hier auf einen bereits länger existierenden Mechanismus aus der Welt der Mobile-Services zurückgreift. Mit diesem Zumo-Token kann sich der Client in weiterer Folge bei jedem Zugriff gegenüber der API-App zu erkennen geben.

Um die Securityoptionen für eine API-App zu konfigurieren, wählt der Entwickler im neuen Azure-Portal die Option Settings | Application Settings (Abb. 2). Anschließend kann er für die App ein Access-Level vergeben. Zur Auswahl stehen Public (anonymous), Public (authenticated) und Internal. Erstere Option gewährt jedem Zugriff; die zweite Option sieht vor, dass nur angemeldete Benutzer auf das API zugreifen dürfen. Entscheidet sich der Benutzer für die dritte Option, dürfen nur Azure-interne Dienste auf das API zugreifen.

Abb. 3: Security in Api-App konfigurieren

Abb. 3: Security in Api-App konfigurieren

Zu den Einstellungen für das Gateway gelangt der Entwickler durch Klick auf den Gatewaynamen (Abb. 2) in den Einstellungen der API-App. In den Einstellungen (Settings) des Gateways (Abb. 3) wählt der Entwickler unter Identity einen oder mehrere zu nutzende Identity-Provider aus. Im gezeigten Fall kommt Azure Active Directory zum Einsatz. Für die Kommunikation mit dem Identity-Provider gibt das Gateway einen App-URL sowie einen Reply-URL vor. Der App-URL ist der URL, unter dem das API erreichbar ist. Der Reply-URL ist der URL, an dem der Identity-Provider den Benutzer samt Securitytoken nach erfolgter Anmeldung umleiten soll. An dieser Stelle tauscht das Gateway das erhaltene Token gegen ein Zumo-Token. Sowohl der App-URL als auch der Reply-URL sind beim Identity-Provider einzutragen. Die vom Identity-Provider erhaltene Client-ID sowie der Name des Identity-Providers ist anschließend im betrachteten Dialog zu erfassen. Details hierzu finden sich in der Dokumentation.

Abb. 4: Security in API-App-Gateway konfigurieren

Abb. 4: Security in API-App-Gateway konfigurieren

Um zur Laufzeit an ein Token zu kommen, muss die Anwendung den Benutzer zum festgelegten App-URL senden. Nach erfolgter Anmeldung erzeugt die API-App ein Cookie x-zumo-auth, das das Zumo-Token beinhaltet. Übersendet der Aufrufer dieses Cookie bei weiteren API-Zugriffen, erfolgt damit die Authentifizierung.

Das Zumo-Token findet sich jedoch nach der Anmeldung beim Identity-Provider auch im Hash-Fragment des URL. Eine native Anwendung muss somit nur den URL parsen, um an das Token zu kommen. Dazu würde sie zunächst den App-URL in einem Browser-Control öffnen, was zur Folge hat, dass das Browser-Control zur Loginseite des Identity-Providers umgeleitet wird. Nach erfolgter Anmeldung muss die native Anwendung das Token aus dem URL des Browser-Controls entnehmen. Anschließend kann die native Anwendung das Zumo-Token zum Zugriff auf das API nutzen. Dazu inkludiert sie es in einem benutzerdefinierten HTTP-Header x-zumo-auth. Ein Beispiel, das dieses Vorgehen veranschaulicht, findet sich auf GitHub.

Nach dem Einbinden von Azure Active Directory als Identity-Provider war es dem Autor nicht möglich, sich mit einem Microsoft-Konto bei der API-App anzumelden. Eine Anmeldung mit einem direkt unter Azure Active Directory eingerichteten Benutzerkonto hat jedoch funktioniert.

Fazit

Azure-API-Apps vereinfachen den Betrieb von Web-APIs unter Windows Azure, indem sie den Entwickler bei immer wiederkehrenden Aufgaben unterstützen. Dazu gehören das Bereitstellen von Metadaten, das Generieren von Client-Proxies sowie das Verknüpfen mit Loginprovidern.

Auch wenn man derzeit nicht mit Azure arbeitet, sollte man Azure-API-Apps auf dem Radar haben. Der Grund dafür liegt in der Cloud-First-Strategie von Microsoft: Neuerungen werden demnach zunächst in der Cloud bereitgestellt und falls sie sich bewähren, später auch On-Premise. Eine Beobachtung von Neuerungen in Azure zeigt somit auch mögliche Neuerungen auf, die es künftig On-Premise geben wird.

Darüber hinaus schließt die Möglichkeit zum Generieren von Client-Proxies eine Lücke bei der Arbeit mit Web-APIs. Da sich diese Option nicht auf API-Apps beschränkt, sondern für sämtliche Web-APIs mit Swagger-Unterstützung möglich ist, profitiert jeder Web-API-Entwickler schon heute davon.

 

Aufmachernbild: Robot with application programming interface sign via Shutterstock.com / Urheberrecht: Kirill__M

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -