11分钟阅读

如何创建安全节点.js graphql api

Marcos对REST架构,敏捷开发和Javascript充满热情。他有8年以上的经验,重点关注Web应用程序。

在本文中,我们的目标是提供有关如何创建安全节点图谱的快速指南。

可能想到的一些问题可能是:

  • 使用GraphQL API的目的是什么?
  • 什么是GraphQL API?
  • 什么是GraphQL查询?
  • GraphQL. 有什么好处?
  • graphql比休息更好吗?
  • 为什么我们使用node.js?

所有这些都是有效的问题,但在回答他们之前,我们应该谨此简要概述目前的网络开发状态:

  • 您今天发现的每个解决方案都使用某种应用程序编程接口(API)。
  • 即使您只使用社交网络,例如Facebook或Instagram,您仍然连接到消耗API的前端。
  • 如果您很好奇,您会发现几乎所有在线娱乐服务都使用不同类型的API,包括Netflix,Spotify和YouTube等服务。

在几乎所有场景中,您都会发现您不需要详细了解的API,例如,您不需要知道它们是如何构建的,并且您不需要使用它们过去的相同技术能够将其集成到您自己的系统中。提供的API允许您提供一种方法,以便在普通标准之间进行服务,即服务和客户端可以进行通信,而无需依赖于特定的技术堆栈。

通过结构良好的API,可以具有可提供多种客户端和前端应用的固体,可维护和可扩展的API。

那说,什么 GraphQL. API?

GraphQL. 是API的查询语言,用于在Facebook中的内部使用,并在2015年出版。它支持阅读,写作和实时更新。它也是开源,它通常与休息和其他架构相比。这是基于:

  • GraphQL. 查询 - 这允许客户端读取和操作应如何接收数据。
  • GraphQL. 突变 - 这是如何在服务器上编写数据。它是关于如何将数据写入系统的GraphQL公约。

虽然本文应该展示如何构建和使用GraphQL API的简单但实际的情景,但我们不会提供详细的GraphQL介绍。原因很简单,因为GraphQL团队提供全面的文档并列出了他们的几种最佳实践 GraphQL. 简介.

什么是GraphQL查询?

如前所述,查询是客户端可以从API读取和操纵数据的方式。您可以传递对象的类型,然后选择要返回的那种字段。一个简单的查询就是如下:

query{
  users{
    firstName,
    lastName
  }
}

In this query, we are trying to reach all users from our users’ schema but only receiving firstName and lastName. The result of this query would be like, for example:

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

客户使用非常简单。

使用GraphQL API的目的是什么?

创建API的目的是能够将软件作为可以被其他外部服务集成的服务。即使您的应用程序由单端申请消耗,您也可以将此前端视为外部服务,为此,当通过API提供两者之间的通信时,您将能够在不同的项目中工作。

如果您在一支大型团队中工作,它可以分手以创建前端和后端团队,允许两者都使用相同的技术并使他们的工作更轻松。在构建API时,重要的是选择更好的项目,以及让您更接近所需的解决方案。

在本文中,我们将专注于构建使用GraphQL的API的骨架。

graphql比休息更好吗?

它可能有点警察,但我无法帮助它: 那要看 .

GraphQL. 是一种适合几种场景的方法。休息是一种架构方法,也可以在几种情况下被证明。如今,有很多文章解释了为什么一个人比另一个人更好,或者为什么你应该只使用休息而不是GraphQL。此外,您可以在内部使用GraphQL并将API的端点视为基于REST的架构。

最好的指导是要知道每种方法的好处,分析您正在创建的解决方案,评估您的团队与解决方案的舒适程度,并评估您是否能够指导您的团队学习和起来在接近选择之前快速快速。

本文更多的是更实用的指导而不是GraphQL和休息的主观比较。如果您想阅读两者的详细比较,我建议您查看我们的另一个文章, GraphQL. 与REST - GraphQL教程.

在今天的文章中,我们将专注于使用Node.js创建GraphQL API.

为什么我们使用node.js?

GraphQL. 您可以使用几种不同的库。出于本文的目的,由于他们广泛使用,我们决定使用JavaScript与Node.js使用JavaScript。 node.js允许开发人员 使用熟悉的前端语法进行服务器端开发。

与我们的方法与基于REST的API相比,类似于另一个顶级工程博客文章所示的方法也很有用: 在Node.js中创建一个安全的REST API。本文还展示了Node.js的使用 表示 开发骨架REST API,允许您比较这两种方法之间的一些差异。 Node.js还设计具有可扩展的网络应用,全球社区和您可以找到的几个开源库 NPM网站 .

这次,我们将展示如何使用GraphQL,Node.js和Express构建骨架API!

在GraphQL教程上的手

如前所述,我们将为GraphQL API构建一个骨架想法,并且您需要在继续之前了解Node.js和Express的基础知识。可提供为该GraphQL示例制作的项目的源代码 这里 .

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

  • 用户, 我们将处理一个基本的Crud。
  • 产品, 为此,我们将有一点细节以显示更多的GraphQL的力量。

用户将包含以下结构:

  • ID
  • 电子邮件
  • 密码
  • permissionlevel.

产品将包含以下结构:

  • ID
  • 名称
  • 描述
  • 价格

至于编码标准,我们将使用此项目的类型。在源文件中,您将能够配置所有内容以开始使用TypeScript进行编码。

让我们的代码!

首先,请确保安装了最新的Node.js版本。在出版时,当前版本为10.15.3 nodejs.org. .

初始化项目

Let’s start in a new folder that we can name node-graphql. There, we can open a terminal or a Git CLI console and start the magic using the following command: npm init.

配置我们的依赖关系和打字

To speed up the process, replacing your package.json with the following at our Git repository should contain all necessary dependencies:

{
  " 名称 ": "node-graphql",
  "version": "1.0.0",
  " 描述 ": "",
  "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"
  }
}

With the updated package.json, just hit the terminal again and use: npm install. It will install all dependencies needed to run this GraphQL API within Node.js and Express.

The next piece is to configure our TypeScript mode. We need a file called tsconfig.json in our root folder with the following:

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

The logic of the code for this configuration will be present at the app folder. There we can create an app.ts file and for basic testing add the following code there:

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

By our configuration, we now can run NPM开始 and wait for a build and be able to test that everything is working properly. In your terminal console, you should see our “Hello GraphQL Node API tutorial.” In the back scene, the configuration basically compiles the TypeScript code into pure JavaScript and then executes our build in the build folder.

现在让我们为GraphQL API配置一个基本骨架。要启动我们的项目,我们将增加三个基本进口:

  • 表示
  • 表示 -graphql.
  • GraphQL-Tools.

让我们在一起开始将它整合在一起:

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

现在我们应该能够开始代码一下。下一步是在Express和Basic 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}!`));

我们在做什么是:

  • 为我们的快递服务器应用启用端口3000。
  • 定义我们想要用作快速示例的查询和突变。
  • 定义查询和突变是如何工作的。

好的,但是出现了什么样的typedefs和solarvers,以及与查询和突变有关?

  • typedefs. - 我们可以从查询和突变所期望的模式的定义。
  • 腐败师 - 而不是对字段或所需参数的期望,在这里,我们定义了查询和突变应该如何工作的函数和行为。
  • 疑问 - 我们要从服务器读取的“得到”。
  • 突变 - 我们的请求将影响我们在自己服务器上的任何数据。

现在,让我们跑 NPM开始 再次看看我们在那里。我们希望该应用程序将使用以下消息运行:节点GraphQL API侦听端口3000!

我们现在可以尝试通过以下服务器查询和测试GraphQL API: http:// localhost:3000 / graphql

 GraphQL. 教程:服务器测试

很棒,现在我们可以写下我们的第一个非常自身的查询被定义为“你好”。

 GraphQL. 教程:首先查询

Note that the way we defined it at the typedefs. , the page can help us to build the query.

这很棒,但我们如何改变价值?突变!

现在,让我们看看当我们使用突变更改内存值时会发生什么:

 GraphQL. 教程:突变的脱位

现在我们可以使用GraphQL Node.js API进行基本的CRUD操作。让我们现在使用我们的代码提前。

产品

对于产品,我们将使用称为产品的模块。作为简化本文的努力,我们将使用内存中的数据库仅用于演示。我们将定义一个模型和服务来管理产品。

我们的模型将如下:

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

    }

}

用户

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

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

    }

}

作为提醒,源代码可用于此功能 关联 .

Now we can play and test our code. Let’s run NPM开始 . We will have the server running at port 3000. We can now access GraphQL for testing at http:// localhost:3000 / graphql.

让我们尝试一个突变将项目添加到我们的产品列表中:

node.js graphql突变发出

To test if it worked, we will now use a query for products, but receiving only ID , 名称 , and 价格 :

query{
  products{
    id,
    name,
    price
  }
}

The response will be:
{
  "data": {
    "products": [
          {
        " ID ": 100,
        " 名称 ": "My amazing product",
        " 价格 ": 400
      }
    ]
  }
}

那就是它;该产品按预期工作。现在我们可以播放并打开我们周围的字段。您可以尝试添加描述:

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

现在我们可以具备我们的产品的描述。让我们现在尝试用户。

mutation{
  user(id:200,
  firstName:"Marcos",
  lastName:"Silva",
  password:"amaz1ingP4ss",
  permissionLevel:9,
  email:"[email protected]") {
    id
  }
}

并且查询将是:

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

响应,如:

{
  "data": {
    "users": [
      {
        " ID ": 200,
        "firstName": "Marcos",
        "lastName": "Silva",
        " 密码 ": "kpj6Mq0tGChGbZ+BT9Nw6RMCLReZEPPyBCaUS3X23lZwCCp1Ogb94/oqJlya0xOBdgEbUwqRSuZRjZGhCzLdeQ==",
        " 电子邮件 ": "[email protected]"
      }
    ]
  }
}

现在我们的GraphQL骨架准备好了!这里有很多步骤朝着有用的全功能API,但现在设置了基本核心。

总结和最终思想

即使是切割边缘缩短,这篇文章非常重要,关于GraphQL Node.js API的开发的很多基本信息。

让我们回顾我们覆盖的东西:

  • 使用Express和GraphQL使用Node.js来构建GraphQL API;
  • 基本GraphQL使用;
  • 查询和突变的基本用法;
  • 为您的项目创建模块的基本方法;
  • 测试我们的GraphQL API;

要更专注于事物的开发方面,我们避免了几个重要的项目,可以简要概述如下:

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

请记住,我们在这个git中拥有完整的源代码 关联 。随意使用,叉,打开问题,制作拉请求,并与之玩!请注意,本文中的所有标准和建议都不在石头上雕刻。

这只是可用于开始设计自己的GraphQL API的许多方法之一。另外,请务必更详细地阅读和探索GraphQL,了解它要提供的内容以及如何使您的API更好。

理解基础知识

是GraphQL一种语言吗?

GraphQL. 被定义为客户端API和服务器端运行时的查询语言以执行这些查询。也就是说,GraphQL并不是一种语言,但它有自己的语法,可以在几种编程语言中开发,例如Node.js.

GraphQL. 有什么好处?

GraphQL. 简化了客户端使用,以便对请求进行筛选并过滤客户实际需要消耗的内容,避免从服务器端传递到客户端的额外数据。它是休息的替代品,但也可以与休息一起使用。

node.js究竟是什么?

node.js. 是一个跨平台JavaScript运行时环境,允许我们使用JavaScript语法开发后端服务器。当软件工程师能够使用JavaScript代码时,可以提高开发速度,后端(Node.js)和前端(类似角度或反应)。

node.js快速吗?

node.js. 已被证明过去几年非常稳定和快速。它适用于多任务,并在Chrome使用的V8引擎上工作。