Dieser Artikel wurde maschinell übersetzt.

Vorhersage: Bewölkt

Mischen von Node.js in Ihre Windows-himmelblau-Lösung

Joseph Fultz

 

Joseph FultzNode.js hat viel Presse ab spät erhalten, und es ist hoch gepriesen für seine asynchronen I/O Modell, das den Haupt-Thread um andere Arbeit während des Wartens auf I/O Antworten zu tun gibt. Übergreifende Rechtsstaatlichkeit Node.js ist, dass e/A teuer ist, und es wird versucht, die Kosten zu verringern, indem zwingt ein asynchrones I/O-Modell. Ich habe nachgedacht, darüber, wie es in ein bereits vorhandenes Framework übernommen werden könnte. Wenn Sie von vorne anfangen, ist es relativ einfach, das Layout der Technologieauswahl und eine Entscheidung treffen, selbst wenn die Entscheidung ziemlich cool Faktor allein beruht. Jedoch, wenn das Ziel ist eine Technologie-Aktualisierung auf ein Teil einer Lösung durchführen, ist der Trick etwas Kommissionierung, die aktuelle, eine Zukunft hat, kommt nicht mit viel zusätzliche Kosten und wird gut mit der vorhandenen Lösungslandschaft passen.

Das ist genau das, was ich in diesem Artikel zeigen. Ich nehme eine vorhandene Lösung, die ermöglicht die Anzeige von Dokumenten im Speicher, aber erfordert eine gemeinsamen Zugriff Signatur zu downloaden. Diese Lösung werde ich eine einfache Benutzeroberfläche mit Node.js hinzufügen. Um mit dieser Implementierung, werde ich einige häufig verwendete Frameworks für Node.js nutzen. Die Lösung, daher beinhalten:

  • Node.js—the-Kern-engine
  • Schnelles — eine Model-View-Controller (MVC)-Stil-Rahmen
  • Jade – eine Wiedergabe und Templating Engine

Zusammen bieten diese drei Tools ein umfangreiches Framework, um die Benutzeroberfläche, ähnlich wie mit ASP.NET MVC 3 und Razor zu bauen.

Erste Schritte

Wenn Sie neu in Node.js, ist es wahrscheinlich am besten mit den Anleitungen von Microsoft zu starten windowsazure.com/develop/nodejs. Sie müssen auch das Node.js-SDK für Windows Azure installieren. Darüber hinaus wollen Sie wahrscheinlich verbringen ein wenig Zeit stochern Express (expressjs.com) und Jade (Jade-lang.com). Wenn Sie mit diesen Werkzeugen vertraut sind, finden Sie einige vertraute Konzepte und eine Mischung aus bekannten und unbekannten Syntax.

In diesem Szenario meine vorhandenen Dienste werden die Arbeit auf der Windows-Azure-Seite tun, und die Windows Azure gehostete Node.js-basierte Website rufen diese Dienste um eine Liste der Dokumente für den Zugang zu rendern. Im Allgemeinen ist es eine nützliche Methode, eine Schicht der Dereferenzierung zwischen dem Client und der Back-End-Services setzen. Dies trennt die Dienste von Schnittstellenänderungen, aber der reale Wert ist oft die zusätzliche funktionale Flexibilität und die Art und Weise Sie können einschließen und Ausschließen von Back-End-Dienst-Anbieter.

In die bestehende Lösung, wie in dargestellt Abbildung 1, das Ziel war, einen Benutzer den Zugriff zu geben, nur, wenn er authentifiziert wurde, eine Shared Access Signatur (SAS) erzeugt. Die Idee war, gewähren Sie Lesezugriff auf diejenigen, die authentifiziert und dann nachträglich gewähren volle Create, Read, Update, Delete (CRUD) Zugriff auf ein bestimmtes Dokument je nach Rolle und Mitgliedschaft Level. Hier konzentriere ich mich ausschließlich auf die Leseberechtigungen.

The Request Sequence
Abbildung 1 die Anfrage-Sequenz

Die Services erstellen

Ich werde eine Authentifizierung-Dienst eine ID zurückgegeben verspotten. Der nachfolgenden Service-Aufruf wird eine Liste der Dateien abrufen. Der Windows Azure Storage Container verwende ich ("Dokumente") hat die öffentlichen Berechtigungen eingeschränkt. Ich möchte eine Liste der Dokumente bereitstellen, auch wenn der Benutzer authentifiziert ist nicht, aber ich keinen nicht authentifizierten Benutzer, die Dateien öffnen zu können will. Meine beiden aufrufenden Signaturen für die API habe ich erstellt werden:

http://[Host]/admin/GetAccess?User=[user] & Pwd = [Passwort]

http://[Host]/admin/files?accessId=[authId]

Natürlich sollten Sie einen realistischeren Auth-Service, der SSL verwendet und nicht Querystring verwenden; Ich wird nicht decken, dieses Stück hier die Lösung.

Zuerst, ich brauche eine Methode zum Erstellen einer SAS (siehe Abbildung 2). Ich brauche diese Methode, kurz, wenn ich die Methode erstellen, die die Dokumentenliste aufbaut.

Abbildung 2-Methode zum Abrufen der gemeinsamen Zugriff-Signatur

public string GetSharedAccessSignature()
{
  string sas = "";          
  sas = (string) System.Web.HttpContext.Current.Cache.Get("sas");
  // If no SAS then get one
  if (sas == null)
  {
    // TODO: hardcoded container, move to config
    CloudBlobContainer container = 
      blobClient.GetContainerReference("documents");
    // Ask the container for SAS passing in the a newly initialized policy
    sas = container.GetSharedAccessSignature(new SharedAccessPolicy()
    {
      SharedAccessStartTime = DateTime.Now,
      SharedAccessExpiryTime = DateTime.Now.AddMinutes(MaxMinutes),
      Permissions = 
        SharedAccessPermissions.Read | SharedAccessPermissions.List
    });
    // Add to cache for reuse because this isn't a per-user SAS
    System.Web.HttpContext.Current.Cache.Add("sas", sas, null,
      DateTime.Now.AddMinutes(MaxMinutes), new TimeSpan(0,0,5,0,0),
      CacheItemPriority.High, null);
  }
  return sas
}

Zum größten Teil, ist dies ziemlich typisch Windows Azure Storage-Code bis zum Aufruf von GetSharedAccessSignature. Gibt es keine gemeinsame Richtlinie hier, also muss ich Informationen bezüglich wann starten oder nicht zulassen, dass Zugriff und den Typ der Berechtigungen übergeben. Alles, was ich über die SAS zur Verfügung stellen möchte ist die Fähigkeit zu lesen und Dateien auflisten. Auch, weil die SAS theoretisch von jedermann verwendet wird, authentifiziert ist, füge ich es in den Cache für die Wiederverwendung um Kollisionen zu vermeiden und Verringerung der Abwanderung in die Erzeugung von Zugriffstasten.

Die Service-Schnittstelle wird als eine WebMethod konfiguriert werden:

[OperationContract]
[WebGet(UriTemplate = "Files?accessId={accessId}")]
List<BlobInfo> GetFiles(string accessId);

Beachten Sie die Verwendung der benutzerdefinierten Klasse BlobInfo — wieder, ich benutze Dereferenzierung. Ich habe bestimmte Felder, die ich möchte zurückkommen und IListBlobItem nicht unbedingt vertreten. Also werde ich in eine Liste von mein Typ von IListBlobItems zurückgegebene Informationen marshallen, wie in Abbildung 3.

Abbildung 3-GetFiles-Einführung

public List<BlobInfo> GetFiles(string accessId)
{
  List<BlobInfo> blobs = new List<BlobInfo>();
  CloudBlobClient sasBlobClient = default(CloudBlobClient);
  CloudStorageAccount storageAccount =
    CloudStorageAccount.FromConfigurationSetting(
    "StorageAccountConnectionString");
  string sas = default(string);
  if(accessId.Length > 0)
  {
    // For the mock just make a simple check
    if(VerifyId(accessId))
    {
      sas = GetSharedAccessSignature();
      // Create the blob client directly, using the SAS
      sasBlobClient = new CloudBlobClient(storageAccount.BlobEndpoint,
        new StorageCredentialsSharedAccessSignature(sas));
    }
  }
  else
  {
    sasBlobClient = storageAccount.CreateCloudBlobClient();
  }
  CloudBlobContainer blobContainer =
    sasBlobClient.GetContainerReference("documents");
  foreach (IListBlobItem blob in blobContainer.ListBlobs())
  {
    BlobInfo info = new BlobInfo();
    info.Name = blob.Uri.LocalPath;
    info.Uri = blob.Uri.AbsoluteUri;
    info.Sas = sas;
    info.CombinedUri = blob.Uri.AbsoluteUri + sas;
    blobs.Add(info);
  }
  return blobs;
}

Es ist wichtig zu beachten bei Abbildung 3 , dass ich die SAS verwende, wenn der Benutzer authentifiziert ist, um eine Liste zurück, die die Richtlinie für den Container achtet.

Mit dem Representational State Transfer (REST)-Service vorhanden kann ich einen kurzen Test über ein Browser-Fenster ausführen. Durch die Einrichtung von der Service-Schnittstelle so, wird es einfach für mich zu verspotten Authentifizierung mit einen bekannten Wert, bis ich habe die for-Schleife, die Generierung von der Liste und die SAS korrekt ausgeführt werden. Sobald das erledigt ist, überprüft die VerifyId(string) einfach, wenn ich einen Schlüssel gleich die AccessId zwischengespeicherten Anmeldeinformationen verfügen. Abbildung 4 zeigt eine Liste ohne Authentifizierung zurückgegeben. Da die vom Dienst zurückgegebenen Liste authentifiziert war nicht, wird der SAS-Wert zu Null gesetzt. Also ich kann die Daten verwenden, um die Liste zu rendern, aber ich kann keinen funktionierenden Link für dem Benutzer geben, denn es keine SAS gibt.

An Unauthenticated List
Abbildung 4 eine nicht authentifizierte Liste

Abbildung 5 zeigt die authentifizierte Liste, die die SAS einschließt.

An Authenticated List with the SAS
Abbildung 5 eine authentifizierte Liste mit der SAS

Der Auftrag des Node.js-Client durch, was der Dienst von einem authentifizierten Anruf gibt Art wird und Rendern von Hyperlinks mit dem URI postfixed SAS. Um dabei zu helfen, habe ich ein CombinedUri-Element bereitgestellt, sodass der Client nur, dass ein Element zugreifen muss. Schließlich die XML ist, zwar toll, da ich in Node.js arbeite ist es sinnvoll, ändern Sie die Zuordnung für die Schnittstelle auf JSON zurück, sodass die Antwort direkt als Objekt verwendet werden kann:

[WebGet(UriTemplate = "Files?accessId={accessId}",
  ResponseFormat=WebMessageFormat.Json)]

Hier ist was die JSON-Ausgabe sieht aus wie:

[{"CombinedUri":"https:\/\/footlocker.blob.core.windows.net\/documents\/AzureKitchen-onesheet.docx?st=2012-03-05T05%3A22%3A22Z&se=2012-03-05T05%3A27%3A22Z&sr=c&sp=rl&sig=Fh41ZuV2y2z5ZPHi9OIyGMfFK%2F4zudLU0x5bg25iJas%3D","Name":"\/documents\/AzureKitchen-onesheet.docx","Sas":"?st=2012-03-05T05%3A22%3A22Z&se=2012-03-05T05%3A27%3A22Z&sr=c&sp=rl&sig=Fh41ZuV2y2z5ZPHi9OIyGMfFK%2F4zudLU0x5bg25iJas%3D","Uri":"https:\/\/footlocker.blob.core.windows.net\/documents\/AzureKitchen-onesheet.docx"}]

Wie bereits erwähnt, ist JSON was wir letztlich wollen hier, wie es direkt konsumierbare innerhalb Express und Jade.

Node.js UI

Ich habe bereits eingerichtet Node.js, Express und Jade, so bin ich bereit, die Benutzeroberfläche zu erstellen. Ich habe durch den Prozess der Bereitstellung von Node.js Rollen unternehmungslustig in Visual Studio gegangen, aber das ist eine ziemlich detaillierte und vollständig manueller Prozess. Also, da es keine Extras-Integration für die Node.js Teil davon gibt, ich verwende Sublime Text 2 zu tun meine bearbeiten und Debuggen Chrom (wie beschrieben auf Tomasz Janczuk Blog unter bit.ly/uvufEM).

Ich möchte ein paar Haushalt Artikel erwähnen. Für den Laien bieten die Rahmen, den, die ich beschäftigt bin, einige einfach zu bedienende Wrapper für bestimmte Funktionen, MVC und ein Vorlage-Rendering-Engine:

  • Restler für einfache REST Anrufe (glaube vereinfachte WebClient)
  • Express für das allgemeine MVC-Stil-Anwendungsframework
  • Jade für Vorlage-Rendering, ähnlich wie die Razor-Engine in ASP.NET MVC

Diese sind alle als Module in Node.js (wie DLLs in .net) und werden im Allgemeinen von GitHub über Knoten Paket Manager (NPM) installiert. Beispielsweise um Restler zu installieren, verwenden Sie den Befehl "Npm install Restler" von innerhalb des Projektordners. Dies geschieht manuell installieren eines Moduls und einen Verweis darauf in dem Projekt hinzufügen.

Ein letzte Bit an Informationen für die unbekannten. Sie werden bemerken viele anonyme Funktionen geschachtelt in anderen Funktionen. Meine beste Rat ist, nur den Code genug, die Verschachtelung zu sehen, wie Sie mit ihm zu arbeiten, bis Sie es natürlich analysieren ohne es neu formatieren umformatieren. Ich werde versuchen, Schachteln, meine Proben zur besseren Lesbarkeit sowie Screenshots vom erhabenen, die sind schön farbig und helfen mit Lesbarkeit verwenden.

Früher habe ich die Befehle New-AzureService und New-AzureWeb­Rolle eine app mit dem Namen AzureNodeExpress erstellen. Ich habe auch ein paar andere Änderungen. In server.js fügte ich Routen zur Index-Seite zu bekommen; die analoge ASP.NET ist die MapRoutes-Methode in MVC Projekte verwendet.

Server.js Änderungen

Ich muss viel wie using-Anweisungen in c#, Node.js, welche Bibliotheken sagen ich verwenden werde. In Node.js, werde ich diese Verweise festgelegt, durch die Zuweisung einer Variablen des Wert der Rückkehr von dem verlangen ('[Lib Name]') Funktion. Nachdem die Verweise festgelegt sind, ich tun ein wenig Konfiguration einige der Motor Variablen festzulegen (z. B. festlegen "Motor anzeigen" auf "jade"). Von besonderem Interesse sind die "Ansicht-Engine", Router, BodyParser, CookieParser und Sitzung.

Ich werde einige alltägliche Elemente überspringen, aber ich möchte meine Route einrichten. Für das Get-Verb auf meiner Index-Seite werde ich einfach die Ansicht direkt rendern:

app.get('/index',
  function(req, res){
    res.render('index.jade', {title: 'index'});
  }
);

Für das Post-Verb möchte ich jedoch den Umgang mit dem Index-Modell übergehen. Um das zu erreichen habe ich eine definierte Methode des Modells "binden":

app.post('/index', index.GetAccessKey.bind(index));

Mit dem routing an Stelle musst ich der Ansicht und dem Modell einrichten.

Die View—Index.jade

In gewisser Weise ich bin von Anfang bis zum Ende überspringen, indem Sie gehen vom Controller zu der Ansicht, bei der Arbeit in einem MVC-Stil möchte aber eine vereinfachte Ansicht gegen erste Arbeiten zu erstellen. Jade-Syntax ist im Grunde HTML ohne die Dekoration der Klammern. Meine gesamte Jade Vorlage erscheint Abbildung 6.

Abbildung 6 Jade Vorlage

html
head
  title Default
body
  h1 File List Home Page
  br
  label Welcome #{username}
  form(method='post', action='/index')
    label Username:
      input(name='username', type='text')
    br
    label Password:
      input(name='password', type='password')
    br
    button(type='submit') Login
  h2 Files   
  form
    table(border="1")
      tr
        td Name
        td Uri
        each doc in docList
          tr
            td #{doc.Name}
            td
              a(href=#{doc.CombinedUri}) #{doc.Name}

Erwähnenswert sind hier die Verwendung von {[Var]} # verweisen auf Variablen und die Tabellenvorlage mit der Schleife, die eine Art von abgekürzten Foreach. Ich habe willkürlich die Liste der Elemente benannt, die ich DocList durchlaufen möchten. Dies ist wichtig, weil in der index.js-Seite, wo ich Jade zum Rendern dieser Ansicht stellen, ich möchte den Wert für DocList übergeben. Dinge sind hier ziemlich einfach, denn ich bin nur einen Entwickler UI schaffen — einfach und schlicht.

Die Model—Index.js

Aufgebaut die Common Language Runtime-Infrastruktur in server.js und die endgültige Ansicht Vorlage im index.jade, bin ich mit dem Fleisch der Ausführung, Links die im index.js geschieht. Denken Sie daran, dass ich eine Bindung für app einrichten.Post zur Index-Seite. Die Bindung wird laden und den Prototyp ausführen habe ich in index.js erstellt. Um dies zu tun, ich füge Funktionen mit dem Index-Prototyp, wie in Abbildung 7. Ich bin im Grunde Erstellen einer benannte Funktion (z. B. GetAccessKey) und eine anonyme Funktion als dessen Ausführung Body zu definieren. In jede dieser Funktionen verwende ich das Restler-Modul, um die REST-Aufrufe zu vereinfachen, die ich vornehmen müssen.

Abbildung 7 Index.js Funktionen

Der erste Aufruf, sobald die Post, Bind passiert, GetAccessKey, die nimmt einfach den Benutzernamen und das Passwort, das ich über die Form-Post eingereicht ist, hängt sie an den URI im Rahmen der Querystring und Restler zum abzurufen, werden verwendet. Denken Sie daran, in Node.js alle Kommunikation asynchron erfolgt, das ist einer der Gründe, warum Sie die Verbreitung von hoch geschachtelte anonyme Funktionen sehen. Bleiben treu, dass Muster im Aufruf von rest.get, definiere ich eine anonyme Funktion, die ausgeführt wird, sobald die Anforderung abgeschlossen ist. Ohne den Fehlerbehandlungs-Code vereinfacht, die Zeile:

rest.get (uri).on('complete',
  function(result){
    accesskey = result;
this.ShowDocs (req, res);}
  )

Ich hoffe, dass Neuformatierung hilft ein Gefühl von dem, was geschieht. Sobald ich den Schlüssel von meinem Service bekommen, werde ich es auf den URI in der Methode die Dokumentenliste holen postfix. Jetzt erhalten die Dinge ein wenig anders als die üblichen. In der anonymen Funktion behandeln die Rückgabe des Aufrufs REST an die Dokumentenliste zu erhalten bitte ich Jade, die Ergebnisse für mich dargestellt werden:

res.render ('index', {title: "Doc List",
    layout: false,
    docList: result,
    username: req.BODY.username});

Ich bemerkte bereits in der Vorlage den Namen der Variablen "DocList." erstellt Ich brauche jetzt sicherstellen, dass ich die richtigen Namen verwende. Der Aufruf von res.render erzählt Express Rahmen "Index" Ressource gerendert und übergibt dann über eine Liste von Name-Wert-Paaren Doppelpunkt und Komma-getrennte Parameter in.

Runtime

Wenn ich versuche, um eine der Dateien zum download suchen, bin ich mit nichts dargestellt. Die Web-Seite ist nicht gefunden. Sie erwarten einen unberechtigten Fehler von Windows Azure Storage, aber wenn Sie versuchen, etwas zugreifen, die als privat gekennzeichnet ist, was zurückgegeben wird, dass die Ressource nicht vorhanden ist. Dies ist beabsichtigt und es ist wünschenswert, da etwas, das "Privat" sollte nicht an die Öffentlichkeit, auch im Konzept vorhanden. Wenn einen 401-Fehler zurückgegeben wurden, würde darauf, dass etwas wirklich da verletzen die Sicherheitsrichtlinien durch Private dargestellt.

Da ich den Speicherort gesichert haben, ist kein direkter Zugriff erlaubt. Sobald ich den Beispielcode ausführen, ist die Geschichte jedoch ein wenig anders. Ich veröffentlichen Sie die Anwendung mithilfe des Windows PowerShell Publish-AzureService-Befehls, wechseln Sie zu der Seite und meine Anmeldeinformationen eingeben; Ich bin dann mit einer Liste von Verknüpfungen zu den Dateien dargestellt (siehe Abbildung 8).

Links to the Files
Abbildung 8 Verknüpfungen zu den Dateien

Weil mein Dienst die Aufrufe des Speichers Makeln ist, konnte ich die Dateien aufgelistet, obwohl ich ihnen direkt die Liste nicht möglich. Auch, weil jeder Link mit der SAS, postfixed ist, wenn ich darauf klicke, werde ich aufgefordert zum Öffnen oder speichern das Zieldokument.

Zusammenfassung

Wenn als ein Weg, um Ihre Windows-Azure-Anwendung entwickeln sich neue oder verlaufenden Technologien interessiert sind, und du ein wahrer Gläubiger bist, was los ist in der Domäne Node.js, Windows Azure hat vorgesorgt – nicht nur mit hosting der Lösung, sondern auch auf die Entwicklung-Seite mit Optionen wie eine Clientbibliothek für Node.js, schlagen die REST-API direkt oder durch Dereferenzierung wie ich hier gezeigt. Entwicklung wäre sicherlich viel besser und einfacher, wenn Node.js richtige Werkzeugbestückung Unterstützung hatte, und ich sicher, dass wir schließlich eine Art von Integration mit Visual Studio sehen bin, wenn die Popularität von Node.js weiter zu wachsen.

Joseph Fultz ist Softwarearchitekt bei Hewlett-Packard Co. und Mitglied der HP.com Global IT-Gruppe. Zuvor war er als Software-Architekt für Microsoft und arbeitet mit seiner Spielklasse Enterprise und ISV Kunden, Architektur und Design-Lösungen zu definieren.

Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: Bruno Terkaly