久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MEAN怎么安裝配置

178次閱讀
沒有評論

共計 11859 個字符,預計需要花費 30 分鐘才能閱讀完成。

本篇內容介紹了“MEAN 怎么安裝配置”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

首先定義一些小型配置庫。文件名:test/config/test_config.js

module.exports = { url :  http://localhost:8000/api/v1.0}

服務器運行端口是 localhost 8000,對于初始的測試來說非常適合。之后,如果改變產品系統的位置或者端口號,只需要簡單地修改這個文件就可以。為了良好地測試,首先應該建立 1 個好的測試環境,這點可以通過下面的代碼保證。首先,連接到數據庫。

文件名:est/setup_tests.js。

function connectDB(callback) { mongoClient.connect(dbConfig.testDBURL, function(err, db) { assert.equal(null, err);
 reader_test_db = db;
 console.log( Connected correctly to server 
 callback(0);
 });
}

下一步,drop user collection,這么做可以了解數據庫狀態。

function dropUserCollection(callback) {
 console.log( dropUserCollection 
 user = reader_test_db.collection( user 
 if (undefined != user) { user.drop(function(err, reply) {
 console.log( user collection dropped 
 callback(0);
 });
 } else { callback(0);
 }
 },

下一步,drop user feed entry collection。

function dropUserFeedEntryCollection(callback) {
 console.log( dropUserFeedEntryCollection 
 user_feed_entry = reader_test_db.collection( user_feed_entry 
 if (undefined != user_feed_entry) { user_feed_entry.drop(function(err, reply) {
 console.log( user_feed_entry collection dropped 
 callback(0);
 });
 } else { callback(0);
 }
}

下一步,連接到 Stormpath,隨后刪點所有測試應用程序中的用戶。

function getApplication(callback) {
 console.log( getApplication 
 client.getApplications({
 name: SP_APP_NAME
 }, function(err, applications) { console.log(applications);
 if (err) {
 log( Error in getApplications 
 throw err;
 }
 app = applications.items[0];
 callback(0);
 });
function deleteTestAccounts(callback) {
 app.getAccounts({
 email: TU_EMAIL_REGEX
 }, function(err, accounts) { if (err) throw err;
 accounts.items.forEach(function deleteAccount(account) { account.delete(function deleteError(err) { if (err) throw err;
 });
 });
 callback(0);
 });
}

下一步,關閉數據庫。

function closeDB(callback) { reader_test_db.close();
}

最終,調用 async.series 來保證所有函數都按次序運行。

async.series([connectDB, dropUserCollection, dropUserFeedEntryCollection, dropUserFeedEntryCollection, getApplication, deleteTestAccounts, closeDB]);

Frisby 在初期就被建立,這里將使用它定義測試用例,如下:

文件名:test/createaccountserror_spec.js

TU1_FN =  Test 
TU1_LN =  User1 
TU1_EMAIL =  testuser1@example.com 
TU1_PW =  testUser123 
TU_EMAIL_REGEX =  testuser* 
SP_APP_NAME =  Reader Test 
var frisby = require( frisby 
var tc = require(./config/test_config

下面代碼將從 enroll route 開始。這個用例故意丟掉了 first name 字段,因此獲得 1 個 400 與 1 個 JSON error(顯示 first name 未定義)返回,下面就 toss that frisby:

frisby.create(POST missing firstName)
.post(tc.url +  /user/enroll ,
 {  lastName  : TU1_LN,
  email  : TU1_EMAIL,
  password  : TU1_PW })
.expectStatus(400)
.expectHeader(Content-Type ,  application/json; charset=utf-8)
.expectJSON({error  :  Undefined First Name})
.toss()

下面用例將測試不包含小寫字母,這同樣會導致 Stormpath 返回錯誤,以及返回 400 狀態。

下面將測試一個無效郵箱地址。因此,期望返回的是未發現 @ 標志,以及 emali 地址缺少域名,同時也會獲得 1 個 400 狀態。

文件名:test/createaccountsspec.js

frisby.create(POST invalid email address)
.post(tc.url +  /user/enroll ,
 {  firstName  : TU1_FN,
  lastName  : TU1_LN,
  email  :  invalid.email ,
  password  :  testUser  })
.expectStatus(400)
.expectHeader(Content-Type ,  application/json; charset=utf-8)
.expectJSONTypes({error  : String})
.toss()

下面著眼一些可以運行的例子,首先需要定義 3 個用戶。

文件名:test/createaccountsspec.js

TEST_USERS = [{ fn  :  Test ,  ln  :  User1 ,
  email  :  testuser1@example.com ,  pwd  :  testUser123 },
 { fn  :  Test ,  ln  :  User2 ,
  email  :  testuser2@example.com ,  pwd  :  testUser123 },
 { fn  :  Test ,  ln  :  User3 ,
  email  :  testuser3@example.com ,  pwd  :  testUser123 }]
SP_APP_NAME =  Reader Test 
var frisby = require( frisby 
var tc = require(./config/test_config

下面用例將發送 1 個包含上文已定義 3 個用戶的數組,當然期望獲得代表成功的 201 狀態。返回的 JSON document 將展示已建立的用戶對象,因此這里可以檢查測試數據匹配與否。

TEST_USERS.forEach(function createUser(user, index, array) { frisby.create( POST enroll user   + user.email)
 .post(tc.url +  /user/enroll ,
 {  firstName  : user.fn,
  lastName  : user.ln,
  email  : user.email,
  password  : user.pwd })
 .expectStatus(201)
 .expectHeader(Content-Type ,  application/json; charset=utf-8)
 .expectJSON({  firstName  : user.fn,
  lastName  : user.ln,
  email  : user.email })
 .toss()});

下一步將測試重復用戶。下例將驗證這個用戶注冊的 email 地址已經被使用。

frisby.create(POST enroll duplicate user )
 .post(tc.url +  /user/enroll ,
 {  firstName  : TEST_USERS[0].fn,
  lastName  : TEST_USERS[0].ln,
  email  : TEST_USERS[0].email,
  password  : TEST_USERS[0].pwd })
.expectStatus(400)
.expectHeader(Content-Type ,  application/json; charset=utf-8)
.expectJSON({error  :  Account with that email already exists. Please choose another email.})
.toss()

這里存在一個重要問題,無法知道 Stormpath 會優先返回哪個 API key。因此,這里需要建立一個動態文件。隨后可以使用這個對文件來驗證測試用例——用戶身份驗證組件。

文件名稱:/tmp/readerTestCreds.js

TEST_USERS = 
[{ _id : 54ad6c3ae764de42070b27b1 ,
 email : testuser1@example.com ,
 firstName : Test ,
 lastName : User1 ,
 sp_api_key_id :”API KEY ID ,
 sp_api_key_secret :”API KEY SECRET”{ _id : 54ad6c3be764de42070b27b2”,
  email : testuser2@example.com ,
  firstName : Test ,
  lastName : User2”,
  sp_api_key_id :”API KEY ID ,
  sp_api_key_secret :”API KEY SECRET”module.exports = TEST_USERS;

為了建立上面這個臨時文件,這里需要連接 MongoDB 從而檢索用戶信息。代碼如下:

文件名:tests/writeCreds.js

TU_EMAIL_REGEX = new RegExp( ^testuser* 
SP_APP_NAME =  Reader Test 
TEST_CREDS_TMP_FILE =  /tmp/readerTestCreds.js 
var async = require( async 
var dbConfig = require( ./config/db.js 
var mongodb = require( mongodb 
assert = require( assert 
var mongoClient = mongodb.MongoClient
var reader_test_db = null;
var users_array = null;
function connectDB(callback) { mongoClient.connect(dbConfig.testDBURL, function(err, db) {assert.equal(null, err);
 reader_test_db = db;
 callback(null);
 });
 }
 function lookupUserKeys(callback) {
 console.log( lookupUserKeys 
 user_coll = reader_test_db.collection( user 
 user_coll.find({email : TU_EMAIL_REGEX}).toArray(function(err, users) {
  users_array = users;
  callback(null);
 });
 }
function writeCreds(callback) {
  var fs = require( fs 
 fs.writeFileSync(TEST_CREDS_TMP_FILE,  TEST_USERS =  
 fs.appendFileSync(TEST_CREDS_TMP_FILE, JSON.stringify(users_array));
  fs.appendFileSync(TEST_CREDS_TMP_FILE,   module.exports = TEST_USERS; 
  callback(0);
 }
 function closeDB(callback) {  reader_test_db.close();
 }
 async.series([connectDB, lookupUserKeys, writeCreds, closeDB]);

著眼下面代碼,上文建立的臨時文件在第一行就會被使用。同時,有多個 feeds 被建立,比如 Dilbert 和 the Eater Blog。

文件名:tests/feed_spec.js

TEST_USERS = require( /tmp/readerTestCreds.js 
var frisby = require( frisby 
var tc = require( ./config/test_config 
var async = require( async 
var dbConfig = require( ./config/db.js 
var dilbertFeedURL =  http://feeds.feedburner.com/DilbertDailyStrip 
var nycEaterFeedURL =  http://feeds.feedburner.com/eater/nyc

首先,一些用戶會被建立,當然他們并沒有訂閱任何 feeds。下面代碼將測試 feeds 的訂閱。請注意,這里同樣需要進行身份驗證,通過使用 .auth 和 Stormpath API keys 完成。

function addEmptyFeedListTest(callback) { var user = TEST_USERS[0];
 frisby.create(GET empty feed list for user   + user.email)
 .get(tc.url +  /feeds)
 .auth(user.sp_api_key_id, user.sp_api_key_secret)
 .expectStatus(200)
 .expectHeader(Content-Type ,  application/json; charset=utf-8)
 .expectJSON({feeds : []})
 .toss()
 callback(null);
}

下面用例將為第一個測試用戶訂閱 Dilbert feed。

這個用例將嘗試為用戶 feed 重復訂閱。

function subDuplicateFeed(callback) {var user = TEST_USERS[0];
frisby.create(PUT Add duplicate feed sub for user   + user.email)
 .put(tc.url +  /feeds/subscribe ,
 {feedURL  : dilbertFeedURL})
 .auth(user.sp_api_key_id, user.sp_api_key_secret)
 .expectStatus(201)
 .expectHeader(Content-Type ,  application/json; charset=utf-8)
 .expectJSONLength(user.subs , 1)
 .toss()
callback(null);
}

下一步,將為測試用戶添加一個新的 feed,返回的結果應該是用戶當下已經訂閱了 2 個 feed。

function subSecondFeed(callback) {var user = TEST_USERS[0];
frisby.create(PUT Add second feed sub for user   + user.email)
 .put(tc.url +  /feeds/subscribe ,
 {feedURL  : nycEaterFeedURL})
 .auth(user.sp_api_key_id, user.sp_api_key_secret)
 .expectStatus(201)
 .expectHeader(Content-Type ,  application/json; charset=utf-8)
 .expectJSONLength(user.subs , 2)
 .toss()
callback(null);
 }

下一步,將使用第 2 個測試用戶來訂閱 1 個 feed。

function subOneFeedSecondUser(callback) { var user = TEST_USERS[1];
frisby.create(PUT Add one feed sub for second user   + user.email)
 .put(tc.url +  /feeds/subscribe ,
 {feedURL  : nycEaterFeedURL})
 .auth(user.sp_api_key_id, user.sp_api_key_secret)
 .expectStatus(201)
 .expectHeader(Content-Type ,  application/json; charset=utf-8)
 .expectJSONLength(user.subs , 1)
 .toss()
callback(null);
async.series([addEmptyFeedListTest, subOneFeed, subDuplicateFeed, subSecondFeed, subOneFeedSecondUser]);

##REST API

在開始編寫 REST API 代碼之前,首先需要定義一些實用工具庫。首先,需求定義應用程序如何連接到數據庫。將這個信息寫入一個獨立的文件允許應用程序靈活地添加新數據庫 URL,以應對開發或者生產系統。

文件名:config/db.js

如果期望打開數據庫驗證,這里需要將信息存入 1 個文件,如下文代碼所示。出于多個原因,這個文件不應該被置入源代碼控制。

文件名稱:config/security.js

module.exports = { stormpath_secret_key : ‘YOUR STORMPATH APPLICATION KEY’;}

Stormpath API 和 Secret keys 應該被保存到屬性文件,如下文代碼所示,同事還需要嚴加注意。

文件名:config/stormpath_apikey.properties

apiKey.id = YOUR STORMPATH API KEY ID
apiKey.secret = YOUR STORMPATH API KEY SECRET

##Express.js 簡述

在 Express.js 中會建立應用程序(APP)。這個應用程序會監聽制定的端口來響應 HTTP 請求。當請求涌入,它們會被傳輸到 1 個中間件鏈。中間件鏈中的每個 link 都會被給予 1 個請求和 1 個響應對象用以存儲結果。link 分為兩種類型,工作或者傳遞到下一個 link。這里會通過 app.use() 來添加新的中間件。主中間件被稱為「router(路由器)」,它會監聽 URL,并將 URL/ 動作傳遞到 1 個指定的處理函數。## 建立應用程序

現在開始聚焦應用程序代碼,鑒于可以在獨立文件中為不同的 routes 嵌入處理器,所以應用程序的體積非常小。

文件名:server.js

在 chain 中末尾定義中間件來處理壞 URLs。

現在,應用程序就會監聽 8000 端口。

在控制臺將消息打印給用戶。

console.log(Magic happens on port   + port);
exports = module.exports = app;

## 定義 Mongoose 數據模型

這里會使用 Mongoose 將 Node.js 上的對象映射成 MongoDB 文檔。如上文所述,這里將建立 4 個 collections:

Feed collection。

Feed entry collection。

User collection。

User feed-entry-mapping collection。

下一步,將為 4 個 collections 定義 schema。首先,從 user schema 開始。注意,這里同樣可以格式化數據,比如講字母都轉換成小寫,使用 trim 消除首 / 末空格。

文件名:app/routes.js

var userSchema = new mongoose.Schema({
 active: Boolean,
 email: { type: String, trim: true, lowercase: true },
 firstName: { type: String, trim: true },
 lastName: { type: String, trim: true },
 sp_api_key_id: { type: String, trim: true },
 sp_api_key_secret: { type: String, trim: true },
 subs: { type: [mongoose.Schema.Types.ObjectId], default: [] },
 created: { type: Date, default: Date.now },
 lastLogin: { type: Date, default: Date.now },
 },
 { collection:  user  }
);

下面代碼將告訴 Mongoose 需要哪些索引。當索引不存在于 MongoDB 數據庫中時,Mongoose 將會負責索引的建立。唯一性約束保障將去除重復出現的可能。「email : 1」將以升序的方式維護地址,而「email : -1」則是降序。

在其他 3 個 collections 上重復這個步驟。

var UserModel = mongoose.model(  User , userSchema );
var feedSchema = new mongoose.Schema({ feedURL: { type: String, trim:true },
 link: { type: String, trim:true },
 description: { type: String, trim:true },
 state: { type: String, trim:true, lowercase:true, default:  new  },
 createdDate: { type: Date, default: Date.now },
 modifiedDate: { type: Date, default: Date.now },
 },
 { collection:  feed  }
feedSchema.index({feedURL : 1}, {unique:true});
feedSchema.index({link : 1}, {unique:true, sparse:true});
var FeedModel = mongoose.model(  Feed , feedSchema );
var feedEntrySchema = new mongoose.Schema({ description: { type: String, trim:true },
 title: { type: String, trim:true },
 summary: { type: String, trim:true },
 entryID: { type: String, trim:true },
 publishedDate: { type: Date },
 link: { type: String, trim:true },
 feedID: { type: mongoose.Schema.Types.ObjectId },
 state: { type: String, trim:true, lowercase:true, default:  new  },
 created: { type: Date, default: Date.now },
 },
 { collection:  feedEntry  }
feedEntrySchema.index({entryID : 1});
feedEntrySchema.index({feedID : 1});
var FeedEntryModel = mongoose.model(  FeedEntry , feedEntrySchema );
var userFeedEntrySchema = new mongoose.Schema({ userID: { type: mongoose.Schema.Types.ObjectId },
 feedEntryID: { type: mongoose.Schema.Types.ObjectId },
 feedID: { type: mongoose.Schema.Types.ObjectId },
 read : { type: Boolean, default: false },
 },
 { collection:  userFeedEntry  }
 );

下面是復合索引實例,每個索引都以升序維護。

userFeedEntrySchema.index({userID : 1, feedID : 1, feedEntryID : 1, read : 1});
var UserFeedEntryModel = mongoose.model(UserFeedEntry , userFeedEntrySchema );

每個用于 GET、POST、PUT 和 DELETE 的請求需要擁有 1 個正確的內容類型,也就是 application/json。然后下一個 link 會被調用。

下一步需要為每個 URL/verb 定義處理器。參考資料部分附上了所有代碼,下面只是代碼片段。在這些代碼中,Stormpath 帶來的便捷一覽無余。此外,這里定義的是 /api/v1.0,舉個例子,這里客戶端可以調用的是 /api/v1.0/user/enroll。如果使用 /api/v2.0,/api/v2.0 則可以被使用,當然向下兼容。

要啟動服務器和運行測試,這里需要遵循幾個步驟。

保證 MongoDB 實例運行,mongod。

安裝 Node 庫,npm install。

開啟 REST API 服務器,node server.js。

運行測試用例:node setup_tests.js;jasmine-node create_accounts_error_spec.js;jasmine-node create_accounts_spec.js;node write_creds.js;jasmine-node feed_spec.js。

“MEAN 怎么安裝配置”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-16發表,共計11859字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 通道| 鞍山市| 乌鲁木齐市| 梁平县| 湘阴县| 双峰县| 平和县| 响水县| 宿松县| 锦屏县| 晋城| 水富县| 杭锦后旗| 开远市| 宜兰县| 南陵县| 中山市| 斗六市| 德惠市| 开远市| 宣威市| 萨迦县| 永仁县| 马尔康县| 中宁县| 吴桥县| 沾化县| 深圳市| 宁津县| 黑河市| 道真| 娱乐| 达州市| 长泰县| 文化| 长丰县| 双鸭山市| 建湖县| 米泉市| 雷波县| 靖江市|