Спецификации кода — некоторые мысли о спецификациях интерфейса

HTTP

задний план

Компания, в которой я работаю, является аутсорсинговой компанией, здесь нет фиксированного сочетания фронтенда и бэкенда, и все они следят за проектом, поэтому все бэкенд/фронтенд разработчики плохо общаются, и каждый человек имеет разное понимание интерфейса, что приводит к процессу разработки, совместная отладка интерфейса занимает много времени. Команда провела внутреннее совещание, чтобы обсудить вопрос стандартизации интерфейса, я как фронтенд высказал свое мнение, которое здесь для ознакомления.


Как нормализовать интерфейс

Потому что у всех разное понимание используемого языка, разная степень знакомства с протоколом HTTP, разная логика мышления и разный опыт разработки. Люди, у которых есть идеи по поводу спецификации интерфейса, должны высказать свое мнение и привести свои доводы. Пусть другие оценивают, обсуждают набор единых правил и, наконец, объединяют во внутренний стандарт. После формирования единого стандарта соответствующий персонал напишет примеры. Например, внешний интерфейс должен отвечать на запросы GET дляjQuery.ajax,fetch,axiosПодождите, пока библиотека запросов предоставит пример кода. Непосредственно обращайтесь к образцу кода для разработки в будущем.

Поскольку в каждом проекте есть много разных способов определения интерфейса, я выскажу свое мнение о спецификации интерфейса с точки зрения метода запроса, заголовка запроса, тела запроса, кода состояния ответа и тела ответа на основе прошлого опыта.

мое понимание стандарта

В наших разных проектах используются примерно два метода запроса:

  • ПОЛУЧИТЬ, ОТПРАВИТЬ
  • ПОЛУЧИТЬ, ПОСТАВИТЬ, ПОСТАВИТЬ, УДАЛИТЬ

Если используется первый, действие, которое необходимо выполнить, должно быть указано в URL-адресе POST, а второе указывать не нужно.

POST /api/user/add HTTP/1.1
POST /api/user/set HTTP/1.1
POST /api/user/delete HTTP/1.1

# 这里例子中约定PUT是新增,POST是修改
POST /api/user HTTP/1.1
PUT /api/user HTTP/1.1
DELETE /api/user HTTP/1.1

Что касается того, использовать ли первое или второе, я предпочитаю первое. Если используется последний, когда использовать POST и когда использовать PUT, я нашел некоторыематериал, но не понимаю.

URL-адрес интерфейса

URL-адрес интерфейса должен быть знаком с именем, и существуют определенные правила. Я мало что знаю об этом здесь, поэтому не буду вдаваться в подробности.

Соглашения о типах данных

Во внешнем запросе их быть не должно.undefined, потому что серверная часть не поддерживает (и не поддерживает json) этот тип данных. еслиContent-Typeзаmultipart/form-data, внешний интерфейс не должен передавать значение null, поскольку оно будет преобразовано в строку, а серверная часть не может определить, является ли это вводом пользователя или типом null.

Каждый проект должен договориться о том, что означают следующие данные по запросу.

  • Что представляет нулевой тип данных
  • что означает пустой тип строки

ПОЛУЧИТЬ запрос

эффект

Запросы GET должны считывать данные и не должны иметь никаких «побочных эффектов». Немного внимания здесьДлина URL ограничена, если длина URL-адреса запроса слишком велика, это приведет к непредсказуемым последствиям. Вы можете использовать POST/PUT для запроса.

Способ

Параметры запроса GET должны быть помещены в URL-адрес запроса, а не в тело запроса. Например, ниже приведен стандартный запрос GET для этого (ненужные поля заголовка HTTP были удалены):

GET /api/user?userId=12345 HTTP/1.1
Host: http://www.example.com

Запросы POST/PUT/DELETE

Эти три метода запроса имеют одинаковый формат параметра.В качестве примера ниже используется POST. Способов использования типа POST много, я видел всякие странные способы, а еще это самая длинная задержка, которая серьезно влияет на ход разработки. Здесь обсуждается только тот способ, который я считаю стандартным.

эффект

Запросы POST используются для добавления, изменения или удаления данных и, в редких случаях, для запроса данных.

Способ

Параметры POST-запроса должны быть помещены в тело запроса. Метод запроса POST имеетчетыре пути:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

Эти методы передаются в заголовке HTTP.Content-Typeполе заголовка для управления.

multipart/form-data

Те, которые мы используем больше всего сейчас, этоmultipart/form-data.

POST /api/user/set HTTP/1.1
Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0

------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userName"

张三
------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userId"

123456
------WebKitFormBoundary2KbanAZwv0mKceX0--

Этот метод не подходит для передачи сложных типов данных, таких как интерфейс, который необходимо изменять нескольким пользователям одновременно:

const userList = [
  {
    userID: 123,
    userName: '张三',
    isAdmin: true,
  }, {
    userID: 456,
    userName: '李四',
    isAdmin: false,
  },
];

Тогда вы можете сделать это только при запросе POST

POST /api/userlist/set HTTP/1.1
Host: http://www.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0

------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userID"

123,456
------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="userName"

张三,李四
------WebKitFormBoundary2KbanAZwv0mKceX0
Content-Disposition: form-data; name="isAdmin"

1,0
------WebKitFormBoundary2KbanAZwv0mKceX0--

важнееТип данных не поддерживается таким образом, входящие данные во всех форматах будут преобразованы в строковый тип. Бэкенды часто используют 1 для обозначения истины, и им необходимо разделить массив или объект.

application/json

Это способ, который я рекомендую использовать, который эффективно компенсируетmultipart/form-dataДефекты. Но почему-то наша команда сейчас практически не использует этот метод.application/jsonТак же есть недоработка, что не поддерживает закачку файлов (здесь есть специальные методы, которые не рекомендуются), если хотите закачать файлы, используйтеmultipart/form-data.

Ниже пример запроса

POST /user HTTP/1.1 
Host: http://www.example.com
Content-Type: application/json;charset=utf-8

[{"userID":123,"userName":"张三","isAdmin":true},{"userID":456,"userName":"李四","isAdmin":false}]

отклик

Я не знаю, какие коды состояния вернет сервер для различных обработок, поэтому я не буду обсуждать это здесь. Мы вернем логический код состоянияcodeс намекамиmsg, тело ответа выглядит так, как показано ниже.

{"code":200,"msg":"处理成功!","data":{}}

Добавьте некоторые ограничения на этом основании:

Рекомендуется, чтобы поле данных всегда имело тип объекта.

Его легко расширить, например, текущий интерфейс — это страница со списком пользователей, а данные используют массив. В интерфейсе версии v2 добавлен пейджинговый запрос, поэтому данные должны быть изменены на объектный тип.

Если поле сложного типа, значение null не допускается.

Сложные типы включают массивы и объекты. Для удобства чтения строка json здесь преобразуется в объект JS.

const resBody = {
  code: 200,
  msg: '处理成功',
  data: {
    list: [
      {
        userID: 123,
        userName: '张三',
      },
    ],
  },
};

вернуть, если нет данных

const resBody = {
  code: 200,
  msg: '处理成功',
  data: {
    list: null,
  },
};

Таким образом, когда внешний интерфейс проходит по списку, null вызовет ошибку кода, а тип данных поля всегда должен оставаться неизменным.Правильный метод возврата выглядит следующим образом.

const resBody = {
  code: 200,
  msg: '处理成功',
  data: {
    list: [],
  },
};

разное

Если у вас есть другие дополнения или исправления, приветствуйте 👏комментарии.

использованная литература


update:2019/06/27

Нетизены в комментариях упомянули Restful API, я слышал об этом раньше, но проигнорировал, когда писал статью, и не читал соответствующую документацию. Я думаю, что конечной целью стандартизации является использование спецификаций с открытым исходным кодом. Вместо создания набора внутренних стандартов,Так что отправная точка этой статьи неверна.

Чтобы найти нужные правила, следует использовать зрелую спецификацию.Предварительным условием для оценки доступности правил является то, перевешивают ли преимущества правил влияние правил на разработку.

PS: я рассмотрю Restful API и Google API Design, когда у меня будет время.