小編給大家分享一下創(chuàng)建安全Node.js GraphQL API的方法是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)專注于企業(yè)成都全網(wǎng)營銷、網(wǎng)站重做改版、徐水網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5建站、商城網(wǎng)站開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為徐水等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
本文的目標是提供關(guān)于如何創(chuàng)建安全的 Node.js GraphQL API 的快速指南。
你可能會想到一些問題:
這些問題都是有意義的,但在回答之前,我們應(yīng)該深入了解當前 Web 開發(fā)的狀態(tài):
你會發(fā)現(xiàn)幾乎在每種情況下都會有一個不需要你去詳細了解的API,例如你不需要知道它們是怎樣構(gòu)建的,并且不需要使用與他們相同的技術(shù)就能夠?qū)⑵浼傻侥阕约旱南到y(tǒng)中。API允許你提供一種可以在服務(wù)器和客戶端通信之間進行通用標準通信的方式,而不必依賴于特定的技術(shù)棧。
通過結(jié)構(gòu)良好的API,可以擁有可靠、可維護且可擴展的API,可以為多種客戶端和前端應(yīng)用提供服務(wù)。
GraphQL 是一種 API 所使用的查詢語言,由Facebook開發(fā)并用于其內(nèi)部項目,并于2015年公開發(fā)布。它支持讀取、寫入和實時更新等操作。同時它也是開源的,通常會與REST和其他架構(gòu)放在一起進行比較。簡而言之,它基于:
雖然本文應(yīng)該展示一個關(guān)于如何構(gòu)建和使用GraphQL API的簡單但真實的場景,但我們不會去詳細介紹GraphQL。因為GraphQL團隊提供了全面的文檔,并在Introduction to GraphQL中列出了幾個最佳實踐。
如上所述,查詢是客戶端從API讀取和操作數(shù)據(jù)的一種方式。你可以傳遞對象的類型,并選擇要接收的字段類型。下面是一個簡單的查詢:
query{ users{ firstName, lastName } }
我們嘗試從用戶庫中查詢所有用戶,但只接收firstName
和lastName
。此查詢的結(jié)果將類似于:
{ "data": { "users": [ { "firstName": "Marcos", "lastName": "Silva" }, { "firstName": "Paulo", "lastName": "Silva" } ] } }
客戶端的使用非常簡單。
創(chuàng)建API的目的是使自己的軟件具有可以被其他外部服務(wù)集成的能力。即使你的程序被單個前端程序所使用,也可以將此前端視為外部服務(wù),為此,當通過API為兩者之間提供通信時,你能夠在不同的項目中工作。
如果你在一個大型團隊中工作,可以將其拆分為創(chuàng)建前端和后端團隊,從而允許他們使用相同的技術(shù),并使他們的工作更輕松。
在本文中,我們將重點介紹怎樣構(gòu)建使用GraphQL API的框架。
GraphQL是一種適合多種情況的方法。 REST是一種體系結(jié)構(gòu)方法。如今,有大量的文章可以解釋為什么一個比另一個好,或者為什么你應(yīng)該只使用REST而不是GraphQL。另外你可以通過多種方式在內(nèi)部使用GraphQL,并將API的端點維護為基于REST的架構(gòu)。
你應(yīng)該做的是了解每種方法的好處,分析自己正在創(chuàng)建的解決方案,評估你的團隊使用解決方案的舒適程度,并評估你是否能夠指導你的團隊快速掌握這些技術(shù)。
本文更偏重于實用指南,而不是GraphQL和REST的主觀比較。如果你想查看這兩者的詳細比較,我建議你查看我們的另一篇文章,為什么GraphQL是API的未來。
在今天的文章中,我們將專注于怎樣用Node.js創(chuàng)建GraphQL API。
GraphQL有好幾個不同的支持庫可供使用。出于本文的目的,我們決定使用Node.js環(huán)境下的庫,因為它的應(yīng)用非常廣泛,并且Node.js允許開發(fā)人員使用他們熟悉的前端語法進行服務(wù)器端開發(fā)。
我們將為自己的 GraphQL API 設(shè)計一個構(gòu)思的框架,在開始之前,你需要了解Node.js和Express的基礎(chǔ)知識。這個GraphQL示例項目的源代碼可以在這里找到(https://github.com/makinhs/no...)。
我們將會處理兩種類型的資源:
Users 包含以下字段:
Products 包含以下字段:
至于編碼標準,我們將在這個項目中使用TypeScript。
首先,要確保安裝了最新的Node.js版本。在本文發(fā)布時,在Nodejs.org上當前版本為10.15.3。
讓我們創(chuàng)建一個名為node-graphql
的新文件夾,并在終端或Git CLI控制臺下使用以下命令:npm init
。
為了節(jié)約時間,在我們的Git存儲庫中找到以下代碼去替換你的package.json
應(yīng)該包含的依賴項:
{ "name": "node-graphql", "version": "1.0.0", "description": "", "main": "dist/index.js", "scripts": { "tsc": "tsc", "start": "npm run tsc && node ./build/app.js" }, "author": "", "license": "ISC", "dependencies": { "@types/express": "^4.16.1", "@types/express-graphql": "^0.6.2", "@types/graphql": "^14.0.7", "express": "^4.16.4", "express-graphql": "^0.7.1", "graphql": "^14.1.1", "graphql-tools": "^4.0.4" }, "devDependencies": { "tslint": "^5.14.0", "typescript": "^3.3.4000" } }
更新package.json
后,在終端中執(zhí)行:npm install
。
接著是配置我們的TypeScript模式。在根文件夾中創(chuàng)建一個名為tsconfig.json
的文件,其中包含以下內(nèi)容:
{ "compilerOptions": { "target": "ES2016", "module": "commonjs", "outDir": "./build", "strict": true, "esModuleInterop": true } }
這個配置的代碼邏輯將會出現(xiàn)在app文件夾中。在那里我們可以創(chuàng)建一個app.ts
文件,在里面添加以下代碼用于基本測試:
console.log('Hello Graphql Node API tutorial');
通過前面的配置,現(xiàn)在我們可以運行 npm start
進行構(gòu)建和測試了。在終端控制臺中,你應(yīng)該能夠看到輸出的字符串“Hello Graphql Node API tutorial”。在后臺場景中,我們的配置會將 TypeScript 代碼編譯為純 JavaScript,然后在build
文件夾中執(zhí)行構(gòu)建。
現(xiàn)在為GraphQL API配置一個基本框架。為了開始我們的項目,將添加三個基本的導入:
把它們放在一起:
import express from 'express'; import graphqlHTTP from 'express-graphql'; import {makeExecutableSchema} from 'graphql-tools';
現(xiàn)在應(yīng)該能夠開始編碼了。下一步是在Express中處理我們的程序和基本的GraphQL配置,例如:
import express from 'express'; import graphqlHTTP from 'express-graphql'; import {makeExecutableSchema} from 'graphql-tools'; const app: express.Application = express(); const port = 3000; let typeDefs: any = [` type Query { hello: String } type Mutation { hello(message: String) : String } `]; let helloMessage: String = 'World!'; let resolvers = { Query: { hello: () => helloMessage }, Mutation: { hello: (_: any, helloData: any) => { helloMessage = helloData.message; return helloMessage; } } }; app.use( '/graphql', graphqlHTTP({ schema: makeExecutableSchema({typeDefs, resolvers}), graphiql: true }) ); app.listen(port, () => console.log(`Node Graphql API listening on port ${port}!`));
我們正在做的是:
好的,但是typeDefs和resolvers中發(fā)生了什么,它們與查詢和修改的關(guān)系又是怎樣的呢?
現(xiàn)在讓我們再次運行npm start,看看我們能得到些什么。我們希望該程序運行后產(chǎn)生這種效果:Graphql API 偵聽3000端口。
我們現(xiàn)在可以試著通過訪問 http://localhost:3000/graphql 查詢和測試GraphQL API:
好了,現(xiàn)在可以編寫第一個自己的查詢了,先定義為“hello”。
請注意,我們在typeDefs
中定義它的方式,頁面可以幫助我們構(gòu)建查詢。
這很好,但我們怎樣才能改變值呢?當然是mutation!
現(xiàn)在,讓我們看看當我們用mutation對值進行改變時會發(fā)生什么:
現(xiàn)在我們可以用GraphQL Node.js API進行基本的CRUD操作了。接下來開始使用這些代碼。
對于Products,我們將使用名為products的模塊。為了是本文不那么啰嗦,我們將用內(nèi)存數(shù)據(jù)庫進行演示。先定義一個模型和服務(wù)來管理Products。
我們的模型將基于以下內(nèi)容:
export class Product { private id: Number = 0; private name: String = ''; private description: String = ''; private price: Number = 0; constructor(productId: Number, productName: String, productDescription: String, price: Number) { this.id = productId; this.name = productName; this.description = productDescription; this.price = price; } }
與GraphQL通信的服務(wù)定義為:
export class ProductsService { public products: any = []; configTypeDefs() { let typeDefs = ` type Product { name: String, description: String, id: Int, price: Int } `; typeDefs += ` extend type Query { products: [Product] } `; typeDefs += ` extend type Mutation { product(name:String, id:Int, description: String, price: Int): Product! }`; return typeDefs; } configResolvers(resolvers: any) { resolvers.Query.products = () => { return this.products; }; resolvers.Mutation.product = (_: any, product: any) => { this.products.push(product); return product; }; } }
對于users,我們將遵循與products模塊相同的結(jié)構(gòu)。我們將為用戶提供模型和服務(wù)。該模型將定義為:
export class User { private id: Number = 0; private firstName: String = ''; private lastName: String = ''; private email: String = ''; private password: String = ''; private permissionLevel: Number = 1; constructor(id: Number, firstName: String, lastName: String, email: String, password: String, permissionLevel: Number) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.email = email; this.password = password; this.permissionLevel = permissionLevel; } }
同時,我們的服務(wù)將會是這樣:
const crypto = require('crypto'); export class UsersService { public users: any = []; configTypeDefs() { let typeDefs = ` type User { firstName: String, lastName: String, id: Int, password: String, permissionLevel: Int, email: String } `; typeDefs += ` extend type Query { users: [User] } `; typeDefs += ` extend type Mutation { user(firstName:String, lastName: String, password: String, permissionLevel: Int, email: String, id:Int): User! }`; return typeDefs; } configResolvers(resolvers: any) { resolvers.Query.users = () => { return this.users; }; resolvers.Mutation.user = (_: any, user: any) => { let salt = crypto.randomBytes(16).toString('base64'); let hash = crypto.createHmac('sha512', salt).update(user.password).digest("base64"); user.password = hash; this.users.push(user); return user; }; } }
提醒一下,源代碼可以在 https://github.com/makinhs/no... 找到。
現(xiàn)在運行并測試我們的代碼。運行npm start
,將在端口3000上運行服務(wù)器。我們現(xiàn)在可以通過訪問http://localhost:3000/graphql來測試自己的GraphQL
嘗試一個mutation,將一個項目添加到我們的product列表中:
為了測試它是否有效,我們現(xiàn)在使用查詢,但只接收id
,name
和price
:
query{ products{ id, name, price } } 將會返回: { "data": { "products": [ { "id": 100, "name": "My amazing product", "price": 400 } ] } }
很好,按照預期工作了。現(xiàn)在可以根據(jù)需要獲取字段了。你可以試著添加一些描述:
query{ products{ id, name, description, price } }
現(xiàn)在我們可以對product進行描述。接下來試試user吧。
mutation{ user(id:200, firstName:"Marcos", lastName:"Silva", password:"amaz1ingP4ss", permissionLevel:9, email:"marcos.henrique@toptal.com") { id } }
查詢?nèi)缦拢?/p>
query{ users{ id, firstName, lastName, password, email } }
返回內(nèi)容如下:
{ "data": { "users": [ { "id": 200, "firstName": "Marcos", "lastName": "Silva", "password": "kpj6Mq0tGChGbZ+BT9Nw6RMCLReZEPPyBCaUS3X23lZwCCp1Ogb94/ oqJlya0xOBdgEbUwqRSuZRjZGhCzLdeQ==", "email": "marcos.henrique@toptal.com" } ] } }
以上是創(chuàng)建安全Node.js GraphQL API的方法是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!