Web API 路徑設計哪家強

本文檔主要比較一下各家API的URL路徑設計,通過學習各家API的URL路徑設計,加深對 REST API 的理解,幫助我們設計出更符合 REST 風格的 API。

Google

  • API 文檔地址:https://developers.google.com/apis-explorer/#p/

YouTube Data API

  • API 文檔地址:YouTube Data API
  • API 前綴:https://www.googleapis.com/youtube/v3

播放列表 API

  • 創建播放列表:POST /playlists
  • 查詢播放列表集合:GET /playlists
  • 更新播放列表:PUT /playlists
  • 刪除播放列表:DELETE /playlists

視頻 API

  • 上傳視頻:POST /videos
  • 查詢列表:GET /videos
  • 更新視頻信息:PUT /videos
  • 刪除視頻:DELETE /videos
  • 為視頻評分:POST /videos/rate
  • 獲取視頻評分:GET /videos/getRating

Calendar API

  • API 文檔地址:Calendar API
  • API 前綴:https://www.googleapis.com/calendar/v3

日歷 API

  • 創建輔助日歷:POST /calendars
  • 查詢日歷:GET /calendars/{calendarId}
  • 更新/補丁日歷:PUT/PATCH /calendars/{calendarId}
  • 刪除服務日歷:DELETE /calendars/{calendarId}
  • 清除主日歷:POST /calendars/calendarId/clear

事件 API

  • 創建事件:POST /calendars/calendarId/events
  • 查詢日歷中的事件:GET /calendars/calendarId/events
  • 查詢單個事件:GET /calendars/calendarId/events/eventId
  • 更新事件:``PUT /calendars/calendarId/events/eventId`
  • 刪除事件:DELETE /calendars/calendarId/events/eventId
  • 移動事件:POST /calendars/calendarId/events/eventId/move

Gmail API

  • API 文檔地址:Gmail API
  • API 前綴:https://gmail.googleapis.com

標簽 API

  • 創建標簽:POST /gmail/v1/users/{userId}/labels
  • 查詢標簽列表:GET /gmail/v1/users/{userId}/labels
  • 獲取指定標簽:GET /gmail/v1/users/{userId}/labels/{id}
  • 更新標簽:PUT /gmail/v1/users/{userId}/labels/{id}
  • 刪除標簽:DELETE /gmail/v1/users/{userId}/labels/{id}

消息 API

  • 發送消息:POST /gmail/v1/users/{userId}/messages/send
  • 查詢消息列表:GET /gmail/v1/users/{userId}/messages
  • 獲取指定消息:GET /gmail/v1/users/{userId}/messages/{id}
  • 刪除消息:DELETE /gmail/v1/users/{userId}/messages/{id}
  • 修改郵件標簽:POST /gmail/v1/users/{userId}/messages/{id}/modify
  • 批量修改郵件標簽:POST /gmail/v1/users/{userId}/messages/batchModify
  • 批量刪除郵件:POST /gmail/v1/users/{userId}/messages/batchDelete

批量修改和批量刪除的操作 API 是 POST 方法,略違和。

觀察結果

  1. 結構基本為:/ product_line / version / {namespace} / resource / {resourceId} / action

    • product_line:產品線,區分不同產品,比如 gmail、calendar、adsense
    • version:版本,區分不同版本,比如 v1、v2
    • namespace:命名空間(可選)。可以用來幫助組織區分 API,做不同的訪問控制等處理。
    • resource:資源,比如 gmail 下的 messages、labels,使用名詞。
    • resourceId:資源ID(可選),比如 gmail 下的 messageId
    • action:動作,對資源進行的操作, 使用動詞。
  2. 基本使用同一個域名 www.googleapis.com,當然也有例外,比如 Gmail API 使用 https://gmail.googleapis.com

  3. 使用名詞表示資源,命名使用復數。

  4. 使用動詞或者動詞短語表示操作(action)。

  5. 對于多個單詞的標識符使用駝峰命名。

  6. YouTube API 和 Calendar API 對 resourceId 的傳參處理不一樣。YouTube API 是放在 URL query 或者 body中,而 Calendar API 是放在 URL path 中。(PS:我個人工作中更多的使用 Calendar API 的這種處理方式)

PayPal

  • API 文檔地址:PayPal API
  • API 前綴:https://api.paypal.com

API 示例

  • 查詢授權:GET /v2/payments/authorizations/{authorization_id}

  • 創建訂單:POST /v2/checkout/orders

  • 更新訂單:PATCH /v2/checkout/orders/{order_id}

  • 查詢訂單:GET /v2/checkout/orders/{order_id}

  • 創建發票:POST /v2/invoicing/invoices

  • 發送發票:POST /v2/invoicing/invoices/{invoice_id}/send

  • 查詢發票列表:GET /v2/invoicing/invoices

  • 查詢發票:GET /v2/invoicing/invoices/{invoice_id}

  • 刪除發票:DELETE /v2/invoicing/invoices/{invoice_id}

  • 刪除外部支付:DELETE /v2/invoicing/invoices/{invoice_id}/payments/{transaction_id}

  • 生成二維碼:POST /v2/invoicing/invoices/{invoice_id}/generate-qr-code

觀察結果

  • 域名: 生產 https://api.paypal.com;沙盒 https://api-m.sandbox.paypal.com
  • 結構:/ version / namespace / resource / {resourceId} / action
  • PayPal API 的結構相對比較干凈統一
  • 資源命名使用復數
  • 使用動詞或者動詞短語表示操作(action)
  • 使用中劃線 - 作為分隔符

AWS

  • API 文檔地址:AWS API

關于域名,AWS使用了一種完全不一樣的方案。不同的產品線和不同的地區(region)會有不一樣的域名。

S3 域名

參考文檔:S3 域名

  • 美國東部 (弗吉尼亞北部):s3.us-east-1.amazonaws.com
  • 亞太區域 (香港):s3.ap-east-1.amazonaws.com
  • 亞太區域 (東京):s3.ap-northeast-1.amazonaws.com

EC2 域名

參考文檔:EC2 域名

  • 美國東部 (弗吉尼亞北部):ec2.us-east-1.amazonaws.com
  • 亞太區域 (香港):ec2.ap-east-1.amazonaws.com

基本上來說,格式是:product_name.regions_name.amazonaws.com/?Action=Function

API 示例

  • 查詢實例: /ec2.us-east-1.amazonaws.com/?Action=DescribeInstances
  • 啟動實例:https://ec2.amazonaws.com/?Action=StartInstances
  • 創建 VPC: /ec2.us-east-1.amazonaws.com/?Action=CreateVpc
  • 創建 Volume: /ec2.us-east-1.amazonaws.com/?Action=CreateVolume

Github

  • API 文檔地址:Github API
  • API 域名:https://api.github.com

API 示例

  • 取所有 repo:GET /orgs/{org}/repos
  • 取特定用戶名的repo:/repos/{owner}/{repo}
  • 取某個倉庫所有的PR:GET /repos/{owner}/{repo}/pulls
  • 創建 PR:POST /repos/{owner}/{repo}/pulls
  • 查詢 PR:GET /repos/{owner}/{repo}/pulls/{pull_number}
  • 更新 PR:PATCH /repos/{owner}/{repo}/pulls/{pull_number}
  • Merge PR:PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge
  • 取自己的issue:GET /user/issues
  • 取某個repo下的issue:GET /repos/{owner}/{repo}/issues
  • 取用戶:GET /users/{username}
  • 取組織下的所有的項目:GET /orgs/{org}/projects

觀察結果

  1. 結構:/resource/ {id} / resource
  2. Github的API沒有版本號,也沒有namespace,直接就是 resource 開頭。
  3. URL 就是在不同的 resource 下進行組合和 join。

Dropbox

  • API 文檔地址:Dropbox API
  • API 域名:https://api.dropboxapi.com

API 示例

  • POST /2/file_properties/templates/add_for_user

  • POST /2/file_properties/templates/get_for_user

  • POST /2/file_properties/templates/remove_for_user

  • POST /2/file_properties/templates/update_for_user

  • POST /2/file_requests/create

  • POST /2/files/create_folder_v2

  • POST /2/users/get_account_batch

  • POST /2/paper/docs/list

觀察結果

  1. 結構:/version / resource / actions

  2. Dropbox 的 API 是在resource 上建各種函數。除了有個總版本,函數上還可以有版本,比如 /2/files/create_folder_v2

  3. 請求方法 POST 一把梭!

  4. 對于多個單詞的 action,使用了下劃線 _ 作為分隔符。關于下劃線,在最初的 RFC1738 中規定不合法,但是,RFC1738 被 RFC2396更新了,RFC 2396 允許使用下劃線為“unreserved character”,而2015年的時候 RFC 3986(URI現代標準) 更新了 RFC 2396,繼續將下劃線歸類為非保留字符,可以在以下組件中可以直接使用:

  • path
  • query
  • fragment

以下是 RFC 3986 中的相關描述:

Characters that are allowed in a URI but do not have a reserved
purpose are called unreserved. These include uppercase and lowercase
letters, decimal digits, hyphen, period, underscore, and tilde.

unreserved = ALPHA / DIGIT / “-” / “.” / “_” / “~”

Twitter

  • API 文檔地址:Twitter API
  • API 域名:api.twitter.com/(普通api) ads-api.twitter.com(廣告用)

API 示例

  • 獲取粉絲列表:GET /2/users/:id/followers

  • 獲取正在關注列表:GET /2/users/:id/following

  • 關注用戶:POST /2/users/:id/following

  • 取消關注:DELETE /2/users/:source_user_id/following/:target_user_id

  • 獲取用戶列表:GET /2/users/:id/list_memberships

  • 更新列表:PUT /2/lists/:id

  • 創建列表:POST /2/lists

  • 刪除列表:DELETE /2/lists/:id

觀察結果

  1. 結構:/version / resource /action
  2. Twitter 的 API 結構也很標準,版本號放在最前面。
  3. 對于 resource 的命名用復數
  4. 使用下劃線 _ 作為分隔符

Stripe

  • API 文檔地址:Stripe API
  • API 域名:https://api.stripe.com

API 示例

  • 獲取余額:GET /v1/balance

  • 獲取余額交易列表:GET /v1/balance_transactions

  • 獲取余額交易:GET /v1/balance_transactions/:id

  • 創建客戶:POST /v1/customers

  • 獲取客戶列表:GET /v1/customers

  • 更新客戶:POST /v1/customers/:id

  • 獲取客戶詳情:GET /v1/customers/:id

  • 刪除客戶:DELETE /v1/customers/:id

  • 搜索客戶:GET /v1/customers/search

  • 創建支付方式:POST /v1/payment_methods

  • 獲取支付方式詳情:GET /v1/payment_methods/:id

  • 獲取客戶支付方式:GET /v1/customers/:id/payment_methods/:id

  • 創建支付意圖:POST /v1/payment_intents

  • 獲取支付意圖詳情:GET /v1/payment_intents/:id

觀察結果

  • 結構:/version/resource/id/action
  • 其更新操作用了 POST 而不是 PUT 方法
  • 對于子資源的區分,使用下劃線 _ 作為分隔符。(PS:感覺使用 namespace + subresource 的形式區分子資源會更好一些,即 GET /v1/payment/methods/:idGET /v1/payment/intents 這樣。)
  • 所有 POST 請求,通過 Idempotency-Key 請求頭來實現冪等。
curl https://api.stripe.com/v1/customers \-u sk_test_Ou1w6LVt3zmVipDVJsvMeQsc: \-H "Idempotency-Key: KG5LxwFBepaKHyUD" \

Trello

  • API 文檔地址:Trello API
  • API 域名:https://api.trello.com

API 示例

  • 獲取 Action詳情:GET /1/actions/{id}

  • 獲取 Action 卡片:GET /1/actions/{id}/card

  • 獲取 Action 看板:GET /1/actions/{id}/board

  • 更新 Action 文本:PUT /1/actions/{id}/text

  • 創建 Action 的回應:POST /1/actions/{idAction}/reactions

  • 獲取 Action 的回應:GET /1/actions/{idAction}/reactions/{id}

  • 刪除 Action 的回應:DELETE /1/actions/{idAction}/reactions/{id}

  • 創建卡片:POST /1/cards

  • 獲取卡片詳情:GET /1/cards/{id}

  • 更新卡片:PUT /1/cards/{id}

  • 刪除卡片:DEL /1/cards/{id}

  • 獲取卡片特定屬性:GET /1/cards/{id}/{field}

  • 獲取卡片附件:GET /1/cards/{id}/attachments

  • 創建卡片附件:POST /1/cards/{id}/attachments

  • 獲取卡片附件:GET /1/cards/{id}/attachments/{idAttachment}

  • 刪除卡片附件:DEL /1/cards/{id}/attachments/{idAttachment}

觀察結果

  1. 結構:/version/resource/{id}/subResource/{subId}
  2. 非常標準的 Restful API 實現,中規中矩,I like it !

Tencent

微信公眾號

  • API 文檔地址:微信公眾號 API
  • 域名:
    • 主域名:api.weixin.qq.com
    • 災備域名:api2.weixin.qq.com
  • 區域域名:sh.api.weixin.qq.com, sz.api.weixin.qq.com, hk.api.weixin.qq.com

API 示例

  • 獲取用戶列表:GET /cgi-bin/user/get

  • 獲取用戶信息:GET /cgi-bin/user/info

  • 設置用戶備注:POST /cgi-bin/user/info/updateremark

  • 查詢卡劵:POST /cgi-bin/card/code/get

  • 核銷卡劵:POST /cgi-bin/card/code/consume

  • 新增永久素材:POST /cgi-bin/material/add_material

  • 獲取永久素材:POST /cgi-bin/material/get_material

  • 刪除永久素材:POST /cgi-bin/material/del_material

  • 獲取素材總數:GET /cgi-bin/material/get_materialcount

  • 獲取素材列表:POST /cgi-bin/material/batchget_material

微信支付

  • API 文檔地址:微信支付 API
  • 域名:api.mch.weixin.qq.com,備域名:api2.mch.weixin.qq.com

API 示例

  • app 下單:POST /v3/pay/transactions/app

  • h5 下單:POST /v3/pay/transactions/h5

  • 小程序下單:POST /v3/pay/transactions/jsapi

  • 查詢訂單:GET /v3/pay/transactions/out-trade-no/{out_trade_no}

  • 關閉訂單:POST /v3/pay/transactions/out-trade-no/{out_trade_no}/close

  • 申請退款:POST /v3/refund/domestic/refunds

  • 創建支付分訂單:POST /v3/payscore/serviceorder

  • 查詢支付分訂單:GET /v3/payscore/serviceorder/

  • 取消支付分訂單:POST /v3/payscore/serviceorder/{out_order_no}/cancel

  • 核銷用戶券:POST /v3/marketing/busifavor/coupons/use

騰訊開放平臺

  • API 文檔地址:騰訊開放平臺 API
  • 域名:graph.qq.com

API 示例

  • 獲取 QQ 用戶信息:GET /user/get_user_info

騰訊云

  • API 文檔地址:騰訊云 API
  • 域名:cvm.tencentcloudapi.com

API 實例

騰訊云的 API 文檔沒有 API 路徑,所有操作都是通過請求 body 或者 params 里的 Action 來區分。

  • 啟動實例:GET https://cvm.tencentcloudapi.com/?Action=StartInstances
  • 關閉實例:GET https://cvm.tencentcloudapi.com/?Action=StopInstances

觀察結果

  1. 有多個域名,用于不同的產品線。
  2. 微信、QQ 的 API 風格差不多基本都是 /resource/action 的方式
  3. 騰訊云的 API 沒有 URL,全部是直接請求域名即可。通過請求 body 或者 params 里的 Action 來區分。

總結

  • 大部分都符合 Restful API 的設計,圍繞 resource 和 action 來設計,增刪改查使用對應的 HTTP 方法。
  • 結構大部分使用 /version/resource/{id}/action 這種形式。
  • resource 命名使用復數;用動詞或者動詞短語表示操作(action)。
  • 對于多個單詞的標識符使用中劃線 - 或者下劃線 _ 作為分隔符,也有駝峰命名法。個人更喜歡中劃線 - 作為分隔符,無論在命令行還是瀏覽器里,更容易識別。
  • AWS 和 騰訊云的 API 設計比較特殊,沒有使用 URL 來區分不同的資源,而是使用 Action 字段區分,是一種 RPC 風格的設計。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84731.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84731.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84731.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微信小程序中的計算屬性庫-miniprogram-computed

miniprogram-computed 是一個用于微信小程序的擴展庫,它提供了計算屬性(computed)和監聽器(watch)的功能,類似于 Vue.js 中的計算屬性和監聽器。以下是使用 miniprogram-computed 的詳細步驟: …

【CSS-7】深入解析CSS偽類:從基礎到高級應用

CSS偽類是前端開發中不可或缺的強大工具,它們允許我們根據文檔樹之外的信息或簡單選擇器無法表達的狀態來樣式化元素。本文將全面探討CSS偽類的各種類型、使用場景和最佳實踐。 1. 偽類基礎概念 1.1 什么是偽類? 偽類(Pseudo-class&#x…

藍橋杯國賽訓練 day4

目錄 再創新高 藍橋大使 表演賽 次數差 再創新高 import java.math.*; import java.util.*;public class Main {static Scanner sc new Scanner(System.in);public static void main(String[] args) {int t 1; // tsc.nextInt();for(int i0;i<t;i) {solve();}} p…

java 高并發設計

文章目錄 目錄 文章目錄 前言 一、通用設計 一、動靜分離 二、數據庫獨立部署 三、問題 1.高并發通用設計方法 2.高并發系統的拆分順序 二、計算資源高并發 三、網絡資源高并發 超高性能場景&#xff08;10萬 QPS&#xff09; 中小規模場景&#xff08;5萬 QPS以下&a…

docker compose搭建elk 8.6.2

環境搭建 選用版本是比較新的版本 (ELK) 8.6.2 &#xff0c;elk的環境做的還是比較好的又windows和Linux多個版本&#xff0c;并且開箱即用。本地直接下載官方軟件也是可以的。最近在學習docker compose&#xff0c;就使用這個環境搭建一下。 前置條件 安裝好docker和 docke…

Springboot3+的id字符串轉化問題

以下是純后端實現 Long/BigInteger ID 轉為 JSON 字符串 的詳細配置方案&#xff0c;基于 Spring Boot 3 和 SpringDoc (OpenAPI) 最新實踐 ? 1. 添加依賴 確保你的 pom.xml&#xff08;或 Gradle&#xff09;中包含&#xff1a; <dependency><groupId>com.fast…

C#學習第30天: 匹配模式

模式匹配&#xff08;Pattern Matching&#xff09;是 C# 中一個強大且靈活的特性&#xff0c;允許開發者以更直觀的方式檢查數據結構&#xff0c;并根據特定模式執行操作。 隨著 C# 語言版本的發展&#xff0c;模式匹配的功能越來越豐富&#xff0c;為處理復雜數據提供了極大…

SQL進階之旅 Day 29:NoSQL結合使用策略

【SQL進階之旅 Day 29】NoSQL結合使用策略 文章簡述 隨著數據量的激增和業務場景的復雜化&#xff0c;傳統關系型數據庫在某些場景下已難以滿足高性能、高擴展性和靈活數據結構的需求。NoSQL&#xff08;非關系型數據庫&#xff09;以其高可擴展性、靈活的數據模型和分布式架構…

PostgreSQL 對 IPv6 的支持情況

PostgreSQL 對 IPv6 的支持情況 PostgreSQL 全面支持 IPv6 網絡協議&#xff0c;包括連接、存儲和操作 IPv6 地址。以下是詳細說明&#xff1a; 一、網絡連接支持 1. 監聽 IPv6 連接 在 postgresql.conf 中配置&#xff1a; listen_addresses 0.0.0.0,:: # 監聽所有IPv4…

模板字符串使用點擊事件【VUE3】

項目場景&#xff1a; 提示&#xff1a;這里簡述項目相關背景&#xff1a; 項目中使用模板字符串的時候很多&#xff0c;有些時候需要再模板字符串中使用點擊事件&#xff0c;那么在模板字符串中可以使用點擊事件么&#xff1f;如果這個點擊事件需要傳參呢&#xff1f; 答案…

AI——DeepSeek+LangChain+streamlit 實現智能汽車維修服務

效果圖 分析流程 代碼實現 廢話少說&#xff0c;直接上代碼 from langchain_core.language_models.llms import BaseLLM from langchain_core.outputs import Generation, LLMResult from pydantic.v1 import Field, validator from typing import Any, Dict, List, Optional…

《C++ 繼承》

目錄 繼承的定義 繼承類模板 派生類和基類之前的轉換 隱藏 派生類的默認成員函數 不能被繼承的類 繼承中的友元和靜態成員 繼承模型 繼承的定義 繼承的本質是一種復用。規定Person類為基類&#xff0c;Student類為派生類 。 繼承方式分為public繼承&#xff0c;prote…

金蝶K3 ERP 跨網段訪問服務器卡頓問題排查和解決方法

我一朋友公司反應&#xff0c;公司網絡卡頓&#xff0c;測試掉包嚴重&#xff0c;抓包wireshark測試&#xff0c;發現arp包有大量mac欺騙&#xff0c;因為公司有幾百臺電腦&#xff0c;所以建議更換了三層交換機&#xff0c;劃分了vlan&#xff0c;這樣有效的避免了網絡風暴等&…

無需安裝!在線數據庫工具 :實戰 SQL 語句經典案例

在數字化時代&#xff0c;SQL&#xff08;結構化查詢語言&#xff09;已成為數據從業者、開發人員乃至業務分析人員必備的核心技能。無論是處理日常數據報表&#xff0c;還是應對復雜的業務邏輯&#xff0c;SQL 都能高效實現數據的查詢、操作與分析。本文將通過經典的 SQL 練習…

如何在網頁里填寫 PDF下拉框

對于PDF 開發者或網頁開發者來說&#xff0c;讓用戶在網站上填寫 PDF 下拉框&#xff08;Combo Box&#xff09;是一個棘手的問題。因為 PDF 并不是一種原生的 Web 格式&#xff0c;瀏覽器通常不允許用戶與 PDF 下拉框進行交互。 那么&#xff0c;如何讓用戶在 HTML 中填寫 PD…

.Net 優秀框架 ABP全面詳解

文章目錄 第一部分&#xff1a;ABP框架概述與核心架構1.1 ABP框架簡介1.2 ABP框架架構解析1.2.1 表現層(Presentation Layer)1.2.2 分布式服務層(Distributed Service Layer)1.2.3 應用層(Application Layer)1.2.4 領域層(Domain Layer)1.2.5 基礎設施層(Infrastructure Layer)…

力扣-198.打家劫舍

題目描述 你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋。每間房內都藏有一定的現金&#xff0c;影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統&#xff0c;如果兩間相鄰的房屋在同一晚上被小偷闖入&#xff0c;系統會自動報警。 給定一個代表每個房屋…

windows 安裝vllm cuda版本

windows 安裝cuda版本 查看window cuda版本 nvidia-smi vllm 獲取鏡像,此版本需要cuda 版本12.8 或以上 docker pull vllm/vllm-openai:latest下載模型 git lfs installcd e:\ai mkdir vllm\models\qwen2cd vllm\models#通過git下載git clone https://www.modelscope.c…

Node.js特訓專欄-基礎篇:1. Node.js環境搭建與項目初始化詳細指南

我將為你詳細講解 Node.js 環境搭建與項目初始化的步驟&#xff0c;包含常見問題解決和最佳實踐&#xff0c;幫助你快速上手。 詳細步驟說明 1. 環境搭建 Windows用戶&#xff1a; 訪問Node.js官網(https://nodejs.org)下載LTS版本安裝包&#xff08;推薦長期支持版&#xf…

13.安卓逆向2-frida hook技術-HookJava構造方法

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…