ホームページ >ウェブフロントエンド >jsチュートリアル >安全な Node.js GraphQL API を作成するためのクイック ガイド

安全な Node.js GraphQL API を作成するためのクイック ガイド

青灯夜游
青灯夜游転載
2020-08-28 10:32:392292ブラウズ

安全な Node.js GraphQL API を作成するためのクイック ガイド

この記事の目的は、安全な Node.js GraphQL API を作成する方法に関するクイック ガイドを提供することです。 [ビデオチュートリアルの推奨: node js チュートリアル ]

いくつかの質問があるかもしれません:

  • GraphQL API を使用する目的は何ですか?
  • GraphQL API とは何ですか?
  • GraphQL クエリとは何ですか?
  • GraphQL の利点は何ですか?
  • GraphQL は REST よりも優れていますか?
  • Node.js を使用する理由

これらの質問はすべて意味のあるものですが、答える前に、Web 開発の現状をより深く理解する必要があります。

  • 現在、ほぼすべてのソリューションが使用されています。アプリケーション プログラミング インターフェイス (API) のこと。
  • ソーシャル ネットワーク (Facebook や Instagram など) のみを使用する場合でも、API を使用したフロントエンドを使用することになります。
  • もし興味があれば、Netflix、Spotify、YouTube など、ほぼすべてのオンライン エンターテイメント サービスがさまざまなタイプの API を使用していることがわかります。

ほとんどの場合、詳細に知る必要のない API が存在することがわかります。たとえば、API がどのように構築されているかを知る必要はありません。彼らと同じテクノロジーを使用する必要はありません。それを独自のシステムに統合できます。 API を使用すると、特定のテクノロジー スタックに依存せずに、サーバーとクライアントの通信の間で共通の標準に基づいて通信する方法を提供できます。

適切に構造化された API を使用すると、さまざまなクライアント アプリケーションやフロントエンド アプリケーションに対応できる、信頼性が高く、保守可能で、スケーラブルな API を実現できます。

GraphQL API とは何ですか?

GraphQL は API で使用されるクエリ言語で、Facebook によって開発され、内部プロジェクトに使用され、2015 年に一般公開されました。読み取り、書き込み、リアルタイム更新などの操作をサポートします。これはオープンソースでもあり、REST や他のアーキテクチャとよく比較されます。つまり、これは次のことに基づいています。

  • GraphQL クエリ - クライアントがデータの受信方法を読み取り、制御できるようにします。
  • GraphQL の変更 - サーバーにデータを書き込む方法について説明します。システムにデータを書き込む方法に関する GraphQL の規則。

この記事では、GraphQL API を構築して使用する方法の単純だが現実的なシナリオを示しますが、GraphQL については詳しく説明しません。なぜなら、GraphQL チームは包括的なドキュメントを提供し、GraphQL の紹介でいくつかのベスト プラクティスをリストしているからです。

GraphQL クエリとは何ですか?

上で述べたように、クエリはクライアントが API からデータを読み取り、操作する方法です。オブジェクトのタイプを渡し、受け取るフィールドのタイプを選択できます。これは簡単なクエリです:

query{
  users{
    firstName,
    lastName
  }
}

ユーザー データベースからすべてのユーザーをクエリしようとしますが、受信するのは firstNamelastName だけです。このクエリの結果は次のようになります:

{
  "data": {
    "users": [
      {
        "firstName": "Marcos",
        "lastName": "Silva"
      },
      {
        "firstName": "Paulo",
        "lastName": "Silva"
      }
    ]
  }
}

クライアントの使い方は非常に簡単です。

GraphQL API を使用する目的は何ですか?

API を作成する目的は、ソフトウェアを他の外部サービスと統合できるようにすることです。プログラムが単一のフロントエンド プログラムによって使用されている場合でも、このフロントエンドを外部サービスとして扱うことができ、API を介して 2 つの間の通信を提供しながら、さまざまなプロジェクトで作業することができます。

大規模なチームで作業している場合は、フロントエンド チームとバックエンド チームを作成することに分けて、チームが同じテクノロジーを使用できるようにして、仕事を容易にすることができます。

この記事では、GraphQL API を使用するフレームワークの構築方法に焦点を当てます。

GraphQL は REST よりも優れていますか?

GraphQL は、多くの状況に適したアプローチです。 REST はアーキテクチャ上のアプローチです。現在、一方が他方よりも優れている理由、または GraphQL ではなく REST を使用する必要がある理由を説明する記事が大量にあります。さらに、GraphQL をさまざまな方法で内部的に使用し、API エンドポイントを REST ベースのアーキテクチャとして維持できます。

あなたがすべきことは、それぞれのアプローチの利点を理解し、作成しているソリューションを分析し、そのソリューションを使用するチームの快適さのレベルを評価し、これらのテクノロジーをすぐに習得できるようにチームを指導できるかどうかを評価することです。

この記事は、GraphQL と REST の主観的な比較ではなく、実践的なガイダンスに重点を置いています。 2 つの間の詳細な比較を確認したい場合は、別の記事「なぜ GraphQL が API の未来であるのか 」を参照することをお勧めします。

今日の記事では、Node.js を使用して GraphQL API を作成する方法に焦点を当てます。

Node.js を使用する理由

GraphQL には、いくつかの異なるサポート ライブラリが利用可能です。この記事の目的として、このライブラリは広く使用されており、Node.js を使用すると開発者が使い慣れたフロントエンド構文をサーバーサイド開発に使用できるため、このライブラリを Node.js 環境で使用することにしました。

掌握GraphQL

我们将为自己的 GraphQL API 设计一个构思的框架,在开始之前,你需要了解Node.js和Express的基础知识。这个GraphQL示例项目的源代码可以在这里找到(https://github.com/makinhs/no...)。

我们将会处理两种类型的资源:

  • Users ,处理基本的CRUD。
  • Products, 我们对它的介绍会详细一点,以展示GraphQL更多的功能。

Users 包含以下字段:

  • id
  • firstname
  • lastname
  • email
  • password
  • permissionLevel

Products 包含以下字段:

  • id
  • name
  • description
  • price

至于编码标准,我们将在这个项目中使用TypeScript。

让我们开始编码!

首先,要确保安装了最新的Node.js版本。在本文发布时,在Nodejs.org上当前版本为10.15.3。

初始化项目

让我们创建一个名为node-graphql的新文件夹,并在终端或Git CLI控制台下使用以下命令:npm init

配置依赖项和TypeScript

为了节约时间,在我们的Git存储库中找到以下代码去替换你的package.json应该包含的依赖项:

{
  "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后,在终端中执行:npm install

接着是配置我们的TypeScript模式。在根文件夹中创建一个名为tsconfig.json的文件,其中包含以下内容:

{
  "compilerOptions": {
    "target": "ES2016",
    "module": "commonjs",
    "outDir": "./build",
    "strict": true,
    "esModuleInterop": true
  }
}

这个配置的代码逻辑将会出现在app文件夹中。在那里我们可以创建一个app.ts文件,在里面添加以下代码用于基本测试:

console.log('Hello Graphql Node API tutorial');

通过前面的配置,现在我们可以运行 npm start 进行构建和测试了。在终端控制台中,你应该能够看到输出的字符串“Hello Graphql Node API tutorial”。在后台场景中,我们的配置会将 TypeScript 代码编译为纯 JavaScript,然后在build文件夹中执行构建。

现在为GraphQL API配置一个基本框架。为了开始我们的项目,将添加三个基本的导入:

  • Express
  • Express-graphql
  • Graphql-tools

把它们放在一起:

import express from 'express';
import graphqlHTTP from 'express-graphql';
import {makeExecutableSchema} from 'graphql-tools';

现在应该能够开始编码了。下一步是在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}!`));

我们正在做的是:

  • 为Express服务器启用端口3000。
  • 定义我们想要用作快速示例的查询和修改。
  • 定义查询和修改的工作方式。

好的,但是typeDefs和resolvers中发生了什么,它们与查询和修改的关系又是怎样的呢?

  • typeDefs - 我们可以从查询和修改中获得的模式的定义。
  • Resolvers - 在这里我们定义了查询和修改的功能和行为,而不是想要的字段或参数。
  • Queries - 我们想要从服务器读取的“获取方式”。
  • Mutations - 我们的请求将会影响在自己的服务器上的数据。

现在让我们再次运行npm start,看看我们能得到些什么。我们希望该程序运行后产生这种效果:Graphql API 侦听3000端口。

我们现在可以试着通过访问 http://localhost:3000/graphql 查询和测试GraphQL API:

安全な Node.js GraphQL API を作成するためのクイック ガイド

好了,现在可以编写第一个自己的查询了,先定义为“hello”。

安全な Node.js GraphQL API を作成するためのクイック ガイド

请注意,我们在typeDefs中定义它的方式,页面可以帮助我们构建查询。

这很好,但我们怎样才能改变值呢?当然是mutation!

现在,让我们看看当我们用mutation对值进行改变时会发生什么:

安全な Node.js GraphQL API を作成するためのクイック ガイド

现在我们可以用GraphQL Node.js API进行基本的CRUD操作了。接下来开始使用这些代码。

Products

对于Products,我们将使用名为products的模块。为了是本文不那么啰嗦,我们将用内存数据库进行演示。先定义一个模型和服务来管理Products。

我们的模型将基于以下内容:

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通信的服务定义为:

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

对于users,我们将遵循与products模块相同的结构。我们将为用户提供模型和服务。该模型将定义为:

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

}

同时,我们的服务将会是这样:

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... 找到。

现在运行并测试我们的代码。运行npm start,将在端口3000上运行服务器。我们现在可以通过访问http://localhost:3000/graphql来测试自己的GraphQL

尝试一个mutation,将一个项目添加到我们的product列表中:

安全な Node.js GraphQL API を作成するためのクイック ガイド

为了测试它是否有效,我们现在使用查询,但只接收idnameprice

query{
  products{
    id,
    name,
    price
  }
}

将会返回:
{
  "data": {
    "products": [
          {
        "id": 100,
        "name": "My amazing product",
        "price": 400
      }
    ]
  }
}

很好,按照预期工作了。现在可以根据需要获取字段了。你可以试着添加一些描述:

query{
  products{
    id,
    name,
    description,
    price
  }
}

现在我们可以对product进行描述。接下来试试user吧。

mutation{
  user(id:200,
  firstName:"Marcos",
  lastName:"Silva",
  password:"amaz1ingP4ss",
  permissionLevel:9,
  email:"marcos.henrique@toptal.com") {
    id
  }
}

查询如下:

query{
  users{
    id,
    firstName,
    lastName,
    password,
    email
  }
}

返回内容如下:

{
"data": {
  "users": [
    {
     "id": 200,
     "firstName": "Marcos",
     "lastName": "Silva",
     "password": "kpj6Mq0tGChGbZ+BT9Nw6RMCLReZEPPyBCaUS3X23lZwCCp1Ogb94/
                           oqJlya0xOBdgEbUwqRSuZRjZGhCzLdeQ==",
     "email": "marcos.henrique@toptal.com"
     }
   ]
}
}

到此为止,我们的GraphQL骨架完成!虽然离实现一个有用的、功能齐全的API还需要很多步骤,但现在已经设置好了基本的核心功能。

总结和最后的想法

让我们回顾一下本文的内容:

  • 在Node.js下可以通过Express和GraphQL库来构建GraphQL API;
  • 基本的GraphQL使用;
  • 查询和修改的基本用法;
  • 为项目创建模块的基本方法;
  • 测试我们的GraphQL API;

为了集中精力关注GraphQL API本身,我们忽略了几个重要的步骤,可简要总结如下:

  • 新项目的验证;
  • 使用通用的错误服务正确处理异常;
  • 验证用户可以在每个请求中使用的字段;
  • 添加JWT拦截器以保护API;
  • 使用更有效的方法处理密码哈希;
  • 添加单元和集成测试;

请记住,我们在Git (https://github.com/makinhs/node-graphql-tutorial)上有完整的源代码。可以随意使用、fork、提问、pull 并运行它!请注意,本文中提出的所有标准和建议并不是一成不变的。

这只是设计GraphQL API的众多方法之一。此外,请务必更详细地阅读和探索GraphQL文档,以了解它提供的内容以及怎样使你的API更好。

英文地址原文:https://www.toptal.com/graphql/graphql-nodejs-api

更多编程相关知识,可访问:编程教学!!

以上が安全な Node.js GraphQL API を作成するためのクイック ガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。