本文章是由機器翻譯。

預測: 多雲

進入您的 Windows 混合 Node.js 天藍色的解決方案

Joseph Fultz

 

Joseph Fultz
Node.js 已被很多的記者到很晚,和高度被吹捧為其非同步 I/O 模型,釋放做其他工作,同時等待 I/O 回應的主執行緒。Node.js 的首要規則是 I/O 的開銷,它會嘗試通過迫使非同步 I/O 模型減少開支。我一直在思考如何可能會被納入現有的框架。如果你從零開始,是相對容易的技術選擇的佈局和作出的決定,即使決定很大程度基於酷因數孤獨。但是,如果目標是要在一個解決方案中的一部分執行技術更新,訣竅採摘是當前、 有未來、 不會有很多額外的成本和與現有的解決方案景觀合身的東西。

這正是要在此列中顯示。我會帶一個現有的解決方案,它允許查看的文檔中存儲,但需要一個共用的訪問簽名下載它們。這套解決方案將會添加一個簡單的使用者介面,使用 Node.js。為了説明執行,我會利用一些常用的框架為 Node.js。該解決方案,因此,將包括:

  • Node.js—the 核心引擎
  • 表達 — — 模型-視圖-控制器 (MVC) 的樣式框架
  • 玉 — — 一個渲染和範本化引擎

在一起這三個工具將提供豐富的框架,從它生成使用者介面,就像使用 ASP.NET MVC 3 和剃刀一樣。

使用者入門

如果你是新到 Node.js,也許最好開始與從微軟公司在可用的預排 windowsazure.com/develop/nodejs。您還需要安裝的 Windows Azure Node.js SDK。此外,您可能需要花一點時間閒逛快遞 (expressjs.com)、 玉器 (玉 lang.com)。如果你是新的這些工具,你會發現一些熟悉的概念和熟悉又陌生的語法混合使用。

對於這種情況下,我現有的服務將會做這項工作在 Windows Azure 方面,與 Windows Azure 主辦基於 Node.js 的網站將會調用這些服務要呈現的訪問文檔的清單。一般情況下,它是間接的有用的做法,放在用戶端和後端服務之間層。這株的服務介面的任何更改,但真正的價值往往是在額外功能的靈活性和的方式,您可以包括和排除後端服務提供者。

在現有解決方案中,作為代表圖 1,目的是給使用者的存取權限,只是如果他被驗證,這是生成共用訪問簽名 (SAS)。這個想法是授予讀存取權限進行身份驗證的那些然後再後來授予完全創建、 讀取、 更新、 刪除 (CRUD) 訪問特定文檔基於角色和成員資格級別。在這裡我會只專注的讀取權限。

The Request Sequence
圖 1 請求序列

創建服務

將類比驗證服務返回一個 id。後續服務呼叫將檢索的檔的清單。我使用的 ("文檔") 的 Windows Azure 存儲容器具有受限制的公共許可權。我想,即使使用者沒有通過身份驗證,但我不想未經身份驗證的使用者能夠打開的檔提供的文檔的清單。我已經創建了 api 的兩個調用簽名如下:

HTTP://[host]/admin/GetAccess?user=[user] & pwd = [密碼]
 HTTP://[host]/admin/files?accessId=[authId

當然,你會更切合實際的身份驗證服務,並不使用查詢字串,並不會使用 SSL ; 我將不會覆蓋那片這裡的解決方案。

第一,我需要一種方法來創建 SAS (請參見圖 2)。 我需要這種方法創建的生成文檔清單中的方法時,不久。

圖 2 用於獲取的共用的訪問,簽名的方法

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
}

在最大程度上,這是相當典型的 Windows Azure 存儲代碼直到對 GetSharedAccessSignature 的調用。 沒有一個共用的訪問策略在這裡,所以我需要傳遞關於何時開始或停止允許訪問和許可權的類型資訊。 所有我想要提供通過 SAS 是讀取和列出檔的能力。 此外,SAS 理論上將使用的任何人進行身份驗證,因為我它向緩存中添加重用避免碰撞,減少客戶流失中生成的便捷鍵。

服務介面將被配置為 WebMethod:

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

請注意,使用 BlobInfo 的自訂類 — — 同樣的我使用的間接定址。 我想要返回的特定欄位和 IListBlobItem 並不一定代表他們。 所以,我就會封成我喜歡的類型的清單從 IListBlobItems 返回的資訊中所示圖 3

圖 3 GetFiles 執行

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;
}

值得注意的是在圖 3 我使用 SAS 如果對使用者進行驗證,返回一個清單,尊重在容器上的訪問策略。

在地方的代表性狀態傳輸 (REST) 服務可以通過瀏覽器視窗運行快速測試。 通過這種方式設置服務介面,變得容易,我通過使用一個知名的值,直到我有類比驗證 for 迴圈生成清單和 SAS 正常運行。 一旦完成,VerifyId(string) 僅檢查以查看是否緩存,並將 accessId 的關鍵等於一個憑據。 圖 4 顯示不經過身份驗證的情況下返回的清單。 因為服務返回的清單並不通過身份驗證,SAS 值設置為零。 因此,我可以使用資料呈現清單中,但我不能給一個工作連結給使用者,因為有沒有 SAS。

An Unauthenticated List
圖 4 未經身份驗證的清單

圖 5 顯示的經過身份驗證的清單,並包括 SAS。

An Authenticated List with the SAS
圖 5 SAS 已通過身份驗證的清單

它將 Node.js 用戶端通過服務從經過身份驗證的調用將返回排序的工作並與 uri postfixed 的 SAS 呈現超連結。 為了説明的我已經在這樣,用戶端需要訪問只有一個元素提供 CombinedUri 元。 最後,雖然 XML 是偉大的因為我在 Node.js 工作,很有意義改變的歸因要返回 JSON,這樣的服務回應可以直接消耗作為物件的介面:

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

這裡是什麼 JSON 輸出看起來就像:

[{"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"}]

如上所述,JSON 是我們最終想在這裡,因為它是快遞和玉內直接消耗的。

Node.js UI

我已設置了 Node.js、 快遞和玉,所以我準備好創建使用者介面。 我已經經歷了起床 Node.js 角色的部署和在 Visual Studio 中運行的進程,但這是一個相當詳細和完全手動的過程。 所以,因為有了這樣的 Node.js 部分沒有工具集成,我會用崇高的文本 2 來做我的編輯和鉻調試 (門將 Janczuk 博客上所述 bit.ly/uvufEM)。

我應該提及幾個內務管理專案。 對於新手來說,我用人的框架提供了某些功能,MVC 和範本渲染引擎周圍一些便於使用包裝:

  • (想簡化的 WebClient) 的簡單休息電話 Restler
  • 表示一般的 MVC 樣式應用程式框架
  • 範本渲染,類似于使用 ASP.NET MVC 中的剃刀引擎玉

這些都是在 Node.js (如.net 中的 Dll) 中的所有考慮的模組,通常從 GitHub 通過節點套裝軟體管理器 (故宮) 安裝。 例如,若要安裝 Restler,使用命令"故宮安裝 restler"從在專案資料夾內。 這需要手動安裝的模組,並在專案中添加對它的引用的地方。

最後一位的陌生的資訊。 你會發現很多嵌套在其他函數中的匿名函數。 我最好的建議是,只是重新格式化代碼足夠看到嵌套,因為您使用它直到您自然解析它而無需重新設置它的格式。 我會嘗試巢我以提高可讀性的樣本,以及使用從崇高,很好地彩色,有助於與可讀性的螢幕截圖。

我使用過的命令新 AzureService 和新 AzureWeb­創建一個名為 AzureNodeExpress 的應用程式的角色。 我也做了幾個其他修改。 在 server.js 中添加路由到索引頁 ; 類比 ASP.NET 是 MVC 專案中使用的 MapRoutes 方法。

Server.js 修改

很像在 C# 中使用的語句,我需要告訴我將利用哪些庫的 Node.js。 在 Node.js,我就會通過為變數賦值的傳回值來設置這些引用要求 ('[lib 名稱]') 函數。 一旦設置的引用,則我做一點配置設置的部分引擎變數 (例如,將設置"查看發動機"為"玉")。 特別感興趣的是"視圖引擎"路由器、 bodyParser、 cookieParser 和會話。

我跳過一些更多的世俗的元素,但我想我的路由設置。 為獲取謂詞索引頁上我會簡單地呈現視圖直接:

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

然而,為郵政的謂詞我想要的指數模型經過處理。 要實現這一目標有以"綁定"的模型定義的方法:

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

在地方的路由需要設置視圖和模型。

View—Index.jade

在某種意義上,我我跳繩從開頭到結尾到視圖中,從控制器走,但在 MVC 樣式中工作時,我想創建一個簡化的視圖,以針對第一次工作。 玉語法基本上是沒有方括弧內的裝飾的 HTML。 我整個的玉範本所示圖 6

圖 6 玉範本

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}

請注意這裡是 # {[var]} 來引用變數和表範本與在迴圈中,這是一種縮寫 foreach 的使用。 我已經任意命名想要遍歷文檔清單的專案的清單。 這是重要的因為在 index.js 頁面中請問玉來呈現這種觀點,我需要在值中傳遞的文檔清單。 事情是非常基本在這裡,因為我只我創建使用者介面開發人員 — — 樸素的。

Model—Index.js

具有設置於運行庫的基礎設施,server.js 和 index.jade 中的最後視圖範本,我感覺與執行,這發生在 index.js 中的肉。 請記住我設置為應用程式的綁定。投遞到索引頁。 綁定將載入並運行原型已經創建的 index.js。 要做到這一點,我會向中添加函數索引原型中,如中所示圖 7。 實質上,我是創建一個命名的函數 (例如,GetAccessKey),作為其執行機構定義匿名函數。 在每個函數中我將使用 Restler 模組簡化需要做出的其餘部分調用。

圖 7 Index.js 函數

第一個調用綁定發生的後一旦到 GetAccessKey,只是採用的使用者名和密碼提交通過表單發佈,將其追加到該 URI 作為查詢字串的一部分,並使用 Restler 來執行 Get 操作。 請記住,在 Node.js 的所有通信都發生了以非同步方式,這是你會看到的高度嵌套的匿名函數擴散的原因之一。 我在忠實于這種模式對 rest.get 的調用中,定義請求完成後執行的匿名函數。 沒有錯誤處理代碼,在行被簡化為:

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

我們希望重新格式化將有助於提供更好的理解正在進行。 一旦從我的服務已經關鍵,我將尾碼它到方法中的 URI,要讀取文檔清單。 現在事情從通常會稍有不同。 在匿名函數中處理其他調用以獲取文檔清單的回報,我問玉呈現結果對我來說:

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

我前面提到的在範本中創建的變數名稱"文檔清單"。現在,我需要確保我使用的正確的名稱。 對 res.render 的調用告訴快遞框架要呈現的"指數"資源,然後將參數傳遞通過冒號和逗號分隔名稱: 值對的清單。

Runtime

如果我嘗試通過流覽找到要下載的檔之一,什麼也不給我。 找不到該 Web 頁。 你可能期望從 Windows Azure 存儲,未經授權的錯誤,但如果您嘗試訪問標記為私人性質的東西,什麼返回是該資源不存在。 這是由設計,和它是可取的因為這是"私人"的東西不應該存在向公眾,甚至在概念。 如果 401 錯誤,而是返回,它將表明什麼是真的存在的違反安全性原則由私人代表。

因為我已經安全的存儲位置,允許沒有直接存取。 然而,一旦我運行示例代碼,這個故事是稍有不同。 我發佈應用程式使用 Windows PowerShell 發佈-AzureService 命令,流覽到該頁面,輸入我的憑據 ; 再給我拿到檔的連結的清單 (請參見圖 8)。

Links to the Files
圖 8 到檔的連結

我的服務中間商對存儲的調用,因為我是能夠列出的檔,即使我不能直接將其列出。 此外,因為每個連結 postfixed sas,當我點擊它我我提示打開或保存的目的文件。

總結

如果你感興趣的新的或趨勢的技術作為一種方式進化的應用程式的 Windows Azure,你是一個真正的信徒在 Node.js 域中發生了什麼,Windows Azure 已經滿足您的要求 — — 不只與主機託管解決方案,但也帶有選項 (例如用戶端庫的 Node.js 在發展方面,擊中其它 API 直接或間接通過示在這裡。 發展肯定會很多更好、 更方便地如果 Node.js 已經適當工具的支援,並相信我們最終會看到某種形式的與 Visual Studio 集成,如果 Node.js 的流行繼續增長。

Joseph Fultz 是在惠普公司,作為 HP.com 全球 IT 組的一部分工作的軟體設計師。他以前是微軟,使用其頂級企業和 ISV 客戶定義的體系結構和設計解決方案的軟體設計師。

由於以下技術專家,檢討這篇文章: Bruno Terkaly