关于API接口的那些事儿

什么是API?

您以前可能听说过“API”一词。但它到底是什么意思,为什么它很重要?

api

简单来说,API(代表“应用程序编程接口”)是不同计算机程序相互通信的一种方式。把它想象成一个密码,一个程序可以用来向另一个程序询问信息或要求它做某事。

例如,您是否曾经使用过允许您使用Facebook或Google帐户登录的网站或应用程序?当你这样做时,网站或应用程序正在使用API与Facebook或谷歌的系统进行通信,并询问你是否真的是你。如果所有内容都检查出来,网站或应用程序可以让你进入。

另一个例子是天气应用程序。您可以使用手机上的天气应用来查看您所在地区的天气预报。但该应用程序本身实际上并没有创建预报 - 它使用来自天气服务的API来获取信息。该应用程序向天气服务询问您所在地区的预报,天气服务以应用程序可以理解的方式发回信息。

有各种各样的 API 可以处理各种事情——社交媒体平台、在线商店、地图和导航等等。API 使不同的程序和服务能够协同工作,这就是为什么它们在技术世界中如此重要的原因。

构建 API 时的心态?

API 非常有用,因为它们允许他们专注于构建项目所需的特定功能,而不必担心从头开始创建所有内容。通过使用 API,开发人员可以节省时间和资源,并构建更强大和创新的软件。

API 还可以使开发人员更轻松地协同工作。如果一个开发人员构建了执行特定功能的 API,则其他开发人员可以在自己的项目中使用该 API。这可以带来更快的开发、更好的协作和更成功的软件整体。

例如,开发人员可能会使用 API 将天气数据与流量数据相结合,从而创建比任何一项服务单独提供的更强大、更有用的应用。

有哪些不同类型的 API?

有几种类型的 API,包括:

  • SOAP(简单对象访问协议)API:SOAP API 用于在 Web 服务的实现中交换结构化信息。SOAP 是一种使用 XML 作为在应用程序之间交换消息的格式的协议。

  • XML-RPC API:XML-RPC 是一种远程过程调用 (RPC) 协议,它使用 XML 对其调用进行编码,并使用 HTTP 作为传输机制。它用于构建 Web 服务,并允许客户端使用 HTTP 请求与服务器通信。

  • REST(具象状态传输)API:REST 是一种使用 HTTP 作为通信协议的架构风格。RESTful API 允许客户端使用 HTTP 请求访问和操作 Web 资源,例如 GET、POST、PUT 和 DELETE。

  • JSON-RPC APIs:JSON-RPC 是一种轻量级远程过程调用 (RPC) 协议,它使用 JSON 作为格式对其调用进行编码,并使用 HTTP 作为传输机制。它用于构建 Web 服务,并允许客户端使用 HTTP 请求与服务器通信。

  • GraphQL API:GraphQL 是由 Facebook 开发的 API 查询语言。它允许客户端仅请求和接收所需的数据,使其比传统的 REST API 更高效。

  • OpenAPI(以前称为 Swagger)API:OpenAPI 是用于构建 API 的规范,它允许对 API 进行机器可读的文档。它用于描述 RESTful Web 服务,并提供一种自动生成客户端库和服务器存根的方法。

REST API 是目前最流行的 API 类型,因为它们具有简单性、灵活性和易用性。

除了基于协议的不同类型的 API 之外,根据其使用情况和有权访问它们的人员,还有不同的 API 类别或分类。下面概述了基于访问权限的一些主要 API 类型:

  • 公共接口:任何人都可以访问公共 API,并可用于构建可供公众使用的应用程序。公共 API 的示例包括社交媒体 API、天气 API 和地图 API。公共 API 通常需要身份验证,但通常比其他类型的 API 更开放、更灵活。

  • 合作伙伴接口: 合作伙伴 API 可供特定业务合作伙伴或客户访问,通常用于集成两个单独的系统或应用程序。合作伙伴 API 的示例包括支付网关 API 和运输 API。合作伙伴 API 通常比公共 API 更安全、更受控制,但仍需要身份验证和合作伙伴之间的一定信任级别。

  • 内部接口:内部 API 在组织内用于实现不同部门或应用程序之间的通信。内部 API 的示例包括 HR API 和库存管理 API。内部 API 通常比合作伙伴和公共 API 更安全、更受控制,并且可能需要专业知识才能使用。

  • 复合接口:复合 API 是通过将多个 API 组合在一起来创建更复杂的新 API 来创建的。这样做通常是为了提供比通过单个 API 提供的更自定义或更具体的服务。与其他类型的 API 相比,复合 API 需要更高级的技术技能来创建和使用。

  • B2B 接口:B2B(企业对企业)API 用于企业对企业通信和集成。它们旨在促进两个独立业务之间的通信,通常比其他类型的 API 更安全、更可控。B2B API 要求两个业务之间具有一定程度的信任,并且可能需要专业知识才能使用。

了解这两种重要的数据格式(XML 和 JSON)

如果您曾经使用过网站或应用程序,您可能遇到过XML或JSON,这是开发人员用于在不同程序之间共享信息的两种流行数据格式。在本节中,我们将解释什么是 XML 和 JSON,以及它们的重要性。

XML

XML(代表“可扩展标记语言”)是一种以结构化格式存储和共享数据的方法。它通常用于网站内容、在线表单和其他类型的需要组织且易于阅读的数据。

在 XML 文档中,数据被组织成描述数据结构的“标记”和“元素”。例如,如果您要存储有关图书的信息,则可以使用“标题”、“作者”和“出版商”等标签来组织数据。

下面是 XML 文档的外观示例:

<book>
    <title>The Hitchhiker's Guide to the Galaxy</title>
    <author>Douglas Adams</author>
    <publisher>Pan Books</publisher>
</book>

JSON

JSON(代表“JavaScript Object Notation”)是存储和共享数据的另一种方式,通常用于Web开发。与XML一样,JSON是结构化的,但它使用不同的语法。

在 JSON 文档中,数据被组织成描述数据结构的“键值对”。例如,我们在 XML 示例中使用的相同书籍数据在 JSON 中可能如下所示:

{
    "title": "The Hitchhiker's Guide to the Galaxy",
    "author": "Douglas Adams",
    "publisher": "Pan Books"
}

JSON 相对于 XML 的一个优点是,在 Web 应用程序中解析(或读取)通常更快、更容易,因为它是一种更轻量级的格式。

REST API 工作原理说明

那么,REST API 是如何工作的呢?简单来说,REST API 是开发人员可用于发送请求和接收数据的 URL(或“终结点”)的集合。例如,如果要构建显示天气数据的应用,则可以使用 REST API 从天气服务获取该数据。

要使用 REST API,开发人员需要使用某些参数向 API 的端点发送 HTTP 请求。然后,API 以开发人员程序可以理解的指定格式(如 JSON 或 XML)发回响应。

REST API 的特征概述

REST API 的主要功能之一是它们是“无状态的”。这意味着每个请求都独立于任何其他请求,并且 API 不会跟踪请求之间的状态。这使得 REST API 非常灵活和可扩展,并且易于在 Web 应用程序中使用。

每个请求都是独立的

在无状态体系结构中,发送到服务器的每个请求都包含完成请求所需的所有信息。这意味着服务器不会在请求之间存储任何客户端上下文。例如,假设客户端向 REST API 发出请求以检索某些数据。请求将包括所有必要的参数,例如要检索的数据类型、要应用的任何筛选器以及响应的格式。服务器处理请求并以指定格式返回请求的数据。服务器不存储有关客户端的任何信息,例如其会话状态或身份验证信息。

不维护任何客户端会话

在无状态体系结构中,服务器不会在请求之间维护任何客户端会话。这意味着每个请求都是独立处理的,服务器不依赖于任何以前的请求来处理当前请求。例如,假设客户端发送请求以更新数据库中的某些数据。请求将包括所有必要的参数,例如要更新的数据和要应用的任何约束。服务器将处理请求并更新数据库中的数据。服务器不会保留有关客户端的任何状态,例如客户端之前更新了哪些数据。

可扩展性和可靠性

无状态原则使 REST API 具有高度可伸缩性和可靠性。由于每个请求都是独立的,因此服务器不需要在请求之间维护任何客户端状态或上下文。这意味着服务器可以独立并行处理每个请求,从而提高性能和可伸缩性。此外,由于每个请求都是独立的,因此如果一个请求失败,则不会影响其他请求的处理。这使得 REST API 更加可靠和容错。

更多 REST API 的特征

是它们使用一组标准的 HTTP 方法来描述可以对 API 的资源执行的操作。这些方法包括“GET”(检索数据)、“POST”(创建新数据)、“PUT”(更新现有数据)和“DELETE”(删除数据)。

下面是一个简单的 REST API 请求的示例,使用天气应用的示例:

GET https://api.weather.com/forecast?zip=90210&appid=YOUR_API_KEY

在此示例中,开发人员向 API 的终结点发送“GET”请求,以检索特定邮政编码的天气预报。API 将以开发人员指定的格式发回响应。

api

JavaScript 示例:

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));

python 示例:

import requests

response = requests.get('https://api.example.com/data')
data = response.json()
print(data)

在这些示例中,我们使用 GET 方法从 REST API 终结点检索数据。在 JavaScript 中,我们使用 fetch 函数发出请求,然后将响应解析为 JSON。在 Python 中,我们使用请求库来发出请求,然后将响应解析为 JSON。

使用 POST 方法创建新数据:

JavaScript 示例:

fetch('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'John', age: 25 })
})
  .then(response => response.json())
  .then(data => console.log(data));

Python 示例

import requests

response = requests.post('https://api.example.com/data', json={'name': 'John', 'age': 25})
data = response.json()
print(data)

在这些示例中,我们使用 POST 方法在 REST API 中创建新数据。在 JavaScript 中,我们再次使用 fetch 函数,但这次我们指定要使用 POST 方法并在请求正文中发送 JSON 数据。在 Python 中,我们使用请求库发出 POST 请求并在请求正文中发送 JSON 数据。

使用 PUT 方法更新现有数据:

JavaScript 示例:

fetch('https://api.example.com/data/123', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'John', age: 26 })
})
  .then(response => response.json())
  .then(data => console.log(data));

python put 示例:

import requests

response = requests.put('https://api.example.com/data/123', json={'name': 'John', 'age': 26})
data = response.json()
print(data)

在这些示例中,我们使用 PUT 方法来更新 REST API 中的现有数据。在 JavaScript 中,我们再次使用 fetch 函数,但这次我们指定要使用 PUT 方法并在请求正文中发送 JSON 数据。在 Python 中,我们使用请求库发出 PUT 请求并在请求正文中发送 JSON 数据。

使用 DELETE 方法删除数据:

JavaScript 示例:

fetch('https://api.example.com/data/123', {
  method: 'DELETE'
})
  .then(response => console.log('Data deleted'));

Pytho 示例:

import requests

response = requests.delete('https://api.example.com/data/123')
print('Data deleted')

在这些示例中,我们使用 DELETE 方法从 REST API 中删除数据。

在 JavaScript 中,我们再次使用 fetch 函数,但这次我们指定要使用 DELETE 方法。在 Python 中,我们使用请求库来发出 DELETE 请求。

请注意,在这两种情况下,我们都不希望收到包含数据的响应,因此我们只是将消息记录到控制台。

如何保护 REST API?

如果要构建 REST API,请务必确保它免受潜在攻击。

使用HTTPS

要保护 REST API,您可以做的最重要的事情之一就是使用 HTTPS。HTTPS 是一种加密通过互联网发送的数据的方式,使攻击者更难拦截和读取数据。要使用 HTTPS,您需要从受信任的证书颁发机构获取 SSL/TLS 证书。

下面是如何使用 Express 框架在 Node.js 应用程序中启用 HTTPS 的示例:

const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();

const options = {
  key: fs.readFileSync('/path/to/private.key'),
  cert: fs.readFileSync('/path/to/certificate.crt')
};

app.get('/', (req, res) => {
  res.send('Hello, world!');
});

https.createServer(options, app).listen(443);

实施身份验证和授权

保护 REST API 的另一个重要方面是实现身份验证和授权。身份验证是验证用户身份的过程,而授权是确定允许用户执行的操作的过程。

实现身份验证和授权的一种方法是使用令牌。当用户登录到您的应用程序时,您可以生成表示该用户会话的令牌。然后,可以将令牌与每个请求一起发送到 API,API 可以使用令牌来验证用户的身份和权限。

下面是如何使用 JSON Web 令牌 (JWT) 库在 Node.js 应用程序中实现基于令牌的身份验证的示例:

const jwt = require('jsonwebtoken');
const express = require('express');
const app = express();

app.post('/login', (req, res) => {
  // verify user credentials
  const user = { id: 1, name: 'John Doe' };
  const token = jwt.sign(user, 'secret');
  res.json({ token });
});

app.get('/protected', (req, res) => {
  // verify token
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.sendStatus(401);
  const token = authHeader.split(' ')[1];
  jwt.verify(token, 'secret', (err, user) => {
    if (err) return res.sendStatus(403);
    res.send(`Welcome, ${user.name}!`);
  });
});

app.listen(3000);

在此示例中,/login 终结点用于在用户登录时生成 JWT 令牌。然后,令牌与请求一起发送到 /protected 终结点,该终结点验证令牌并在用户获得授权时发送响应。

限制访问和使用速率限制

若要进一步保护 REST API,可以限制访问和使用速率限制。可以通过限制允许哪些 IP 地址或域访问 API 来实现访问限制。速率限制可用于防止用户在短时间内发出过多请求,这有助于防止 DDoS 攻击。

下面是如何使用表达式速率限制库在 Node.js 应用程序中实现速率限制的示例:

const rateLimit = require('express-rate-limit');
const express = require('express');
const app = express();

const limiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 100, // limit each
});

app.use(limiter);

app.get('/', (req, res) => {
  res.send('Hello, world!');
});

app.listen(3000);

在此示例中,表达式速率限制中间件用于将请求数限制为每分钟 100 个。如果用户超过此限制,他们将收到“429 请求过多”响应。

验证用户输入

最后,验证用户输入以防止 SQL 注入和跨站点脚本 (XSS) 等攻击非常重要。在数据库查询中使用用户输入或以 HTML 格式呈现用户输入之前,请务必对其进行清理和验证。

下面是如何使用验证程序.js库在 Node.js 应用程序中验证用户输入的示例:

const validator = require('validator');
const express = require('express');
const app = express();

app.post('/user', (req, res) => {
  const { name, email, password } = req.body;
  if (!validator.isEmail(email)) {
    return res.status(400).json({ message: 'Invalid email address' });
  }
  // create new user in database
  res.json({ message: 'User created' });
});

app.listen(3000);

在此示例中,验证程序.js库用于在数据库中创建新用户之前验证电子邮件地址。如果电子邮件地址无效,API 将返回 400 错误请求响应。

如何编写 API 文档?

构建 API 时,请务必提供清晰全面的文档,使开发人员能够轻松理解和使用您的 API。在本节中,我们将介绍 API 文档的一些最佳实践。

保持简单

API 文档的第一条规则是保持简单。开发人员希望能够快速了解您的 API 的工作原理以及如何使用它。使用清晰简洁的语言,避免使用技术术语或过于复杂的概念。

下面是天气 API 的简单明了的 API 文档示例:

/**
 * @api {get} /weather Request weather information
 * @apiName GetWeather
 * @apiGroup Weather
 *
 * @apiParam {String} location The name of the location you want the weather for (required).
 * @apiParam {String="metric","imperial"} [units="metric"] The units to display the weather in (optional).
 *
 * @apiSuccess {String} location The name of the location.
 * @apiSuccess {Number} temperature The temperature in the specified units.
 * @apiSuccess {String} conditions The current weather conditions.
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *       "location": "London",
 *       "temperature": 10,
 *       "conditions": "Cloudy"
 *     }
 */
 ```
下面是包含日历 API 示例的 API 文档示例:

/**

  • @api {get} /events Request events for a specified period
  • @apiName GetEvents
  • @apiGroup Calendar
  • @apiParam {String} start The start date of the events to retrieve, in ISO format (YYYY-MM-DD) (required).
  • @apiParam {String} end The end date of the events to retrieve, in ISO format (YYYY-MM-DD) (required).
  • @apiParam {String="public","private"} [type] The type of events to retrieve (optional).
  • @apiSuccess {Object[]} events An array of events.
  • @apiSuccess {Number} events.id The ID of the event.
  • @apiSuccess {String} events.title The title of the event.
  • @apiSuccess {String} events.start The start time of the event, in ISO format.
  • @apiSuccess {String} events.end The end time of the event, in ISO format.
  • @apiSuccess {String} events.location The location of the event.
  • @apiSuccessExample Success-Response:
  • HTTP/1.1 200 OK
  • [
  • {
  • "id": 123,
  • "title": "Company Meeting",
  • "start": "2022-03-15T10:00:00",
  • "end": "2022-03-15T11:00:00",
  • "location": "Office"
  • },
  • {
  • "id": 456,
  • "title": "Project Deadline",
  • "start": "2022-03-25T12:00:00",
  • "end": "2022-03-25T18:00:00",
  • "location": "Remote"
  • }
  • ]
    */

使用 Flask 构建 API 的示例,Flask 是用于构建 API 的流行 Web 框架。

假设我们正在为一个简单的电子商务应用程序构建 API,第一步是定义 API 要求。对于我们的电子商务应用程序,我们可能需要支持以下功能:

  • 检索所有产品的列表

  • 检索特定产品的详细信息

  • 创建新产品

  • 更新现有产品

  • 删除产品

定义 API 要求后,下一步将是选择编程语言和框架。在本例中,我们将使用 Python 和 Flask。

要开始构建 API,我们需要使用 pip 安装 Flask:

pip install flask

接下来,我们将创建一个新的 Flask 应用程序并定义 API 的端点。下面是此代码的外观示例:

from flask import Flask, jsonify, request

app = Flask(__name__)

# Define the product data
products = [
    {'id': 1, 'name': 'Product 1', 'price': 10.00},
    {'id': 2, 'name': 'Product 2', 'price': 20.00},
    {'id': 3, 'name': 'Product 3', 'price': 30.00}
]

# Define the endpoints
@app.route('/products', methods=['GET'])
def get_all_products():
    return jsonify({'products': products})

@app.route('/products/<int:id>', methods=['GET'])
def get_product(id):
    for product in products:
        if product['id'] == id:
            return jsonify({'product': product})
    return jsonify({'message': 'Product not found'})

@app.route('/products', methods=['POST'])
def create_product():
    product = request.get_json()
    products.append(product)
    return jsonify({'message': 'Product created successfully'})

@app.route('/products/<int:id>', methods=['PUT'])
def update_product(id):
    for product in products:
        if product['id'] == id:
            product['name'] = request.json['name']
            product['price'] = request.json['price']
            return jsonify({'message': 'Product updated successfully'})
    return jsonify({'message': 'Product not found'})

@app.route('/products/<int:id>', methods=['DELETE'])
def delete_product(id):
    for product in products:
        if product['id'] == id:
            products.remove(product)
            return jsonify({'message': 'Product deleted successfully'})
    return jsonify({'message': 'Product not found'})

在此示例中,我们为 API 定义了五个终结点:
/products、
/products/<int:id>、
/products、
/products/<int:id> 和 /products/<int:id>。

这些终结点对应于我们之前定义的功能。

为了测试 API,我们可以使用像 Postman 这样的工具向 API 发送请求并验证响应。例如,要检索所有产品的列表,我们可以向 /products 端点发送 GET 请求。下面是一个示例,说明这在 Postman 中的外观:

http://localhost:5000/products

来自 API 的响应将是:

{
    "products": [
        {
            "id": 1,
            "name": "Product 1",
            "price": 10.0
        },
        {
            "id": 2,
            "name": "Product 2",
            "price": 20.0
        },
        {
            "id": 3,
            "name": "Product 3",
            "price": 30.0
        }
    ]
}

API 按预期工作后,下一步就是记录 API。这可能涉及创建描述 API 功能的 API 文档,以及创建如何使用 API 的示例。对于我们的电子商务 API,文档可能如下所示:

电子商务 API 提供以下功能:

GET /products:检索所有产品的列表

GET /products/{id}:检索特定产品的详细信息

POST /products :发布/产品:创建新产品

PUT /products/{id}:更新现有产品

DELETE /products/{id}:删除产品

所有请求和响应都应采用 JSON 格式。

若要检索所有产品的列表,请向 /products 发送 GET 请求。响应将是一个包含产品数组的 JSON 对象:

{
    "products": [
        {
            "id": 1,
            "name": "Product 1",
            "price": 10.0
        },
        {
            "id": 2,
            "name": "Product 2",
            "price": 20.0
        },
        {
            "id": 3,
            "name": "Product 3",
            "price": 30.0
        }
    ]
}

检索特定产品的详细信息
要检索特定产品的详细信息,请向 /products/{id} 发送 GET 请求,其中 {id} 是产品的 ID。响应将是一个包含产品详细信息的 JSON 对象:

{
    "product": {
        "id": 1,
        "name": "Product 1",
        "price": 10.0
    }
}

创建新产品
要创建新产品,请使用包含产品详细信息的 JSON 对象向 /products 发送 POST 请求:

{
    "id": 4,
    "name": "Product 4",
    "price": 40.0
}

#Response:
{
    "message": "Product created successfully"
}

更新现有产品
要更新现有产品,请向 /products/{id} 发送 PUT 请求,其中 {id} 是产品的 ID,其中包含包含产品更新详细信息的 JSON 对象:

{
    "name": "New Product Name",
    "price": 15.0
}

#Response:
{
    "message": "Product updated successfully"
}

删除产品
要删除产品,请向 /products/{id} 发送 DELETE 请求,其中 {id} 是产品的 ID:

#Response:
{
    "message": "Product deleted successfully"
}

API 文档可以让其他开发人员更轻松地使用您的 API,并确保 API 易于理解。

结论

API 已成为现代软件开发的重要组成部分,使应用程序能够相互通信和共享数据。在本文中,我们探讨了 API 的基础知识,包括它们是什么、它们是如何工作的,以及为什么它们对开发人员很重要。

我们首先定义了 API 并检查了它们的核心原则,包括无状态和统一接口。

接下来,我们探讨了与构建和使用 API 相关的一些常见挑战,例如安全性和文档。我们讨论了保护 API 的最佳实践,包括身份验证的使用,并研究了良好文档在帮助其他开发人员理解和使用您的 API 方面的重要性。

最后,我们将我们的知识付诸实践,通过使用 Flask Web 框架构建一个简单的电子商务 API,并使用示例和示例代码记录 API。按照本文中的步骤操作,您现在应该对 API 有深入的了解,并能够在自己的项目中开始使用和构建简单的 API。

上一篇
下一篇