Зачастую бывает так, что в поля, в которых не была предусмотрена валидация данных, вносят данные как бог на душу положит. И в результате получается не пойми что. Данная функция пытается нормализовать номера телефонов.
Такая ошибка чаще всего означает что вы пытаетесь изменить запись регистра, изменяя измерение. А так нельзя. Если нужно изменить измерение — запись нужно предварительно удалить, а затем записать вновь
Может поможет страждущим как и я. Двое суток гугла и янденкса ;(
Во время отладки скрипта на FastApi возникла ситуация, что сервис должен обращаться сам к себе, ну типа небольшая рекруссия. Соответсвенно чтоб трюк сработал, нужно чтобы было запущено несколько инстансов uvicorn одновременно. Ну ноу проблем, запускаю:
1
uvicorn main:app--reload--port8000--workers10
И нифига. Запускается только один инстанс. И так и сяк, и гул и яндекс.
Наутро доходит попробовать убрать —reload (ну т.е. перезапускать инстанс автоматически при изменении кода — очень полезная штука во время отладки). И…..заработало! Баг?
Однако вместо ожидаемой передачи заголовка, curl в упор возвращает ровно ничего:
Гугл помог выяснить, что ключевое слово Authorization зарезервированно для использования в Header. На https://stackoverflow.com было подсказано и направление куда копать. А именно, использовать обертку Security:
Долгое время был любителем по изобретать велосипед, и городил собственные реализации API для внешних систем. Да получалось. Да работало. Но если честно, всегда был в этих API бардак. Документации толковой не было, примеров соответственно тоже. Ну правда работал с этими API собственно практически один я, это и спасало от тухлых помидоров 😉
Решил попробовать таки в следующем своем проекте воспользоваться сторонними решениями для документирования и написания API. Выбор пал на FastApi для python. Собственно дальше просто «рыба» с основными фишками которую можно использовать далее расширяя.
Разберем файл main.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import uvicorn
from fastapi import FastAPI
from app.routers import hash
tags_metadata=[
{"name":"use-hash","description":"Создание хэша по логину, паролю и секрету (если есть)"},
{"name":"delete","description":"Удаление хэга по его *ID*.",},
]
app=FastAPI(title="OCPI API documentation",description="Инструментарий для работы по протоколу OCPI",
Что происходит в этом скрипте? Сначала инициализируется ядро FastApi:
1
2
3
app=FastAPI(title="OCPI API documentation",description="Инструментарий для работы по протоколу OCPI",
version="0.0.2",openapi_tags=tags_metadata,)
Т.е. обявляем название API, описание и присваиваем разделы которые будут отображаться в документации http://127.0.0.1:8000/docs
Далее подключаем роутинг из файла /app/routers/hash.py:
1
app.include_router(hash.router,prefix="/v1")
Этих роутингов естественно может быть не ограниченное количество
Для того чтобы FastApi мог сформировать документацию, необходимо её чуть подготовить. За это отвечают «схемы». Например создадим схему /app/schemas/hash.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding: utf-8 -*-
from typing import Optional
from pydantic import BaseModel,Field
classhash_out(BaseModel):
""" Что Выходит """
hash:str=Field(...,title="Хэш созданый на основе логина пароля",example="iauwhfpseurh e")
Что у нас тут? А вот что: мы объявляем, что FastAPI должен перенаправлять весь вход по методу POST с URL /hash (на самом деле /v1/hash, т.к. роутин объявили с префиксом v1) в функцию async def hash. В качестве исходящих значений, в response_model указываем схему hash_out заданную в схемах выше. Так -же установим тэг tags=[«use-hash»], для того чтоб функция API была красиво подписана. В качестве входящих параметров функции hash, указываем соответственно модель с классом hash_in
Если хочется «перехватывать» не только POST запросы, но и GET, то вызов чуть изменится:
Т.е. мы изменили вызов на get и в функцию добавили Depends(), т.к. входящие параметры попадают не в виде в данном случае JSON, а в качестве параметров вида: /v1/hash?login=aaa&passowd=bbb, т.е. их нужно конвертировать предварительно в JSON
А что делать, если помимо входящих параметров из POST запроса (ну или GET/PUT/DELETE и т.д), необходимо еще и обработать пришедшие заголовки Headers? Для этого изменим объявление функции, добавив помимо модели, еще и заголовки:
Т.е. нам придется использовать не обычно используемый response_model, для указания класса со схемой ответа, а response, который позволяет указать шаблон при определенном коде ответа. В результате общий файл роута hash.py получается такой:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- coding: utf-8 -*-
"""Different helper-functions to work with users."""
import json
import fastapi
from fastapi import APIRouter,Depends,Request,Header,Response