Coreapi только перечисляет список и метод чтения, даже когда пользователь зарегистрирован

Я создаю Django Rest Framework и хочу протестировать API с coreapi библиотека. Я могу создать объект, используя coreapi программно внутри скрипта Python, но в командной строке я не могу создать тот же объект и когда я перечисляю coreapi конечные точки Я получаю список только с конечными точками для чтения и перечисления, даже когда я добавляю действительные учетные данные.

Моя схема:

{
    "_type": "document",
    "_meta": {
        "url": "http://127.0.0.1:8000/api/schema/",
        "title": "NEP API"
    },
    "experiments": {

        "list": {
            "_type": "link",
            "url": "/api/experiments/",
            "action": "get",
            "fields": [
                {
                    "name": "page",
                    "location": "query",
                    "schema": {
                        "_type": "integer",
                        "title": "Page",
                        "description": "A page number within the paginated result set."
                    }
                }
            ]
        },
        "create": {
            "_type": "link",
            "url": "/api/experiments/",
            "action": "post",
            "encoding": "application/json",
            "fields": [
                {
                    "name": "title",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Title",
                        "description": ""
                    }
                },
                {
                    "name": "description",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Description",
                        "description": ""
                    }
                },
                {
                    "name": "data_acquisition_done",
                    "location": "form",
                    "schema": {
                        "_type": "boolean",
                        "title": "Data acquisition done",
                        "description": ""
                    }
                },
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "integer",
                        "title": "Nes id",
                        "description": ""
                    }
                },
                {
                    "name": "ethics_committee_file",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Project file approved by the ethics committee",
                        "description": ""
                    }
                },
                {
                    "name": "sent_date",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Sent date",
                        "description": ""
                    }
                }
            ]
        },
        "read": {
            "_type": "link",
            "url": "/api/experiments/{nes_id}/",
            "action": "get",
            "fields": [
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "path",
                    "schema": {
                        "_type": "string",
                        "title": "",
                        "description": ""
                    }
                }
            ]
        },
        "update": {
            "_type": "link",
            "url": "/api/experiments/{nes_id}/",
            "action": "put",
            "encoding": "application/json",
            "fields": [
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "path",
                    "schema": {
                        "_type": "string",
                        "title": "",
                        "description": ""
                    }
                },
                {
                    "name": "title",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Title",
                        "description": ""
                    }
                },
                {
                    "name": "description",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Description",
                        "description": ""
                    }
                },
                {
                    "name": "data_acquisition_done",
                    "location": "form",
                    "schema": {
                        "_type": "boolean",
                        "title": "Data acquisition done",
                        "description": ""
                    }
                },
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "integer",
                        "title": "Nes id",
                        "description": ""
                    }
                },
                {
                    "name": "ethics_committee_file",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Project file approved by the ethics committee",
                        "description": ""
                    }
                },
                {
                    "name": "sent_date",
                    "required": true,
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Sent date",
                        "description": ""
                    }
                }
            ]
        },
        "partial_update": {
            "_type": "link",
            "url": "/api/experiments/{nes_id}/",
            "action": "patch",
            "encoding": "application/json",
            "fields": [
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "path",
                    "schema": {
                        "_type": "string",
                        "title": "",
                        "description": ""
                    }
                },
                {
                    "name": "title",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Title",
                        "description": ""
                    }
                },
                {
                    "name": "description",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Description",
                        "description": ""
                    }
                },
                {
                    "name": "data_acquisition_done",
                    "location": "form",
                    "schema": {
                        "_type": "boolean",
                        "title": "Data acquisition done",
                        "description": ""
                    }
                },
                {
                    "name": "nes_id",
                    "location": "form",
                    "schema": {
                        "_type": "integer",
                        "title": "Nes id",
                        "description": ""
                    }
                },
                {
                    "name": "ethics_committee_file",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Project file approved by the ethics committee",
                        "description": ""
                    }
                },
                {
                    "name": "sent_date",
                    "location": "form",
                    "schema": {
                        "_type": "string",
                        "title": "Sent date",
                        "description": ""
                    }
                }
            ]
        },
        "delete": {
            "_type": "link",
            "url": "/api/experiments/{nes_id}/",
            "action": "delete",
            "fields": [
                {
                    "name": "nes_id",
                    "required": true,
                    "location": "path",
                    "schema": {
                        "_type": "string",
                        "title": "",
                        "description": ""
                    }
                }
            ]
        }
    },
}

Как видите, все методы перечислены здесь, и я не могу создать experiment объект с помощью coreapi программно внутри скрипта, например, работает (внутри скрипта python):

client.action(
        schema, ['experiments', 'create'],
        params={'title': 'An experimet', 'description': 'A description',
                'nes_id': 2, 'sent_date': '2017-01-01'}
    )

Но при использовании coreapi в командной строке я не могу создать один и тот же объект.

Получение схемы:

$ coreapi get http://127.0.0.1:8000/api/schema

отображать и точки, когда не зарегистрированы:

<NEP API "http://127.0.0.1:8000/api/schema/">
    experiments: {
        groups: {
            list(experiment_nes_id, [page])
        }
        studies: {
            list(experiment_nes_id, [page])
        }
        list([page])
        read(nes_id)
    }
    groups: {
        list([page])
    }
    protocol_components: {
        list([page])
        read(nes_id)
    }
    studies: {
        list([page])
    }

Затем я добавляю свои учетные данные:

$ coreapi credentials add 127.0.0.1 "lab1":"nep-lab1" --auth basic

Перезагрузите схему:

$ coreapi reload

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

<NEP API "http://127.0.0.1:8000/api/schema/">
    experiments: {
        groups: {
            list(experiment_nes_id, [page])
        }
        studies: {
            list(experiment_nes_id, [page])
        }
        list([page])
        read(nes_id)
    }
    groups: {
        list([page])
    }
    protocol_components: {
        list([page])
        read(nes_id)
    }
    studies: {
        list([page])
    }

Теперь я ожидаю, что появятся конечные точки, включая создание, обновление и т. Д., Но нет.

И когда я пытаюсь создать experiment объект работает:

$ coreapi action experiments create --param nes_id=5 --param title="A" --param description="B" --param sent_date="2001-01-01"

Я получаю, как и ожидалось:

Index ['experiments']['create'] did not reference a link. Key 'create' was not found.

url conf:

Я использую Маршрутизатор по умолчанию для генерации REST URI:

router.register(r'experiments', api.ExperimentViewSet,
                base_name='api_experiments')
router = DefaultRouter()

и в том числе в url conf:

url(r'^', include(router.urls)),

Извините за длинный текст. Я хотел включить столько информации, сколько мне показалось необходимым.

4 ответа

Такая же проблема возникала при работе над учебником (часть 7) на официальном сайте Django Rest Framework.

Нашел одно решение: вручную добавить заголовок Авторизация к запросам используя coreapi headers add HEADER VALUE, где VALUE это строка символов, которая генерируется при добавлении учетных данных пользователя. По какой-то причине мой coreapi не добавил этот заголовок автоматически для запроса, как я нашел с --debug вариант.

Вот пример:

Перед добавлением учетных данных я вижу только безопасные методы:

$ coreapi get http://127.0.0.1:8000/schema/
<Pastebin API "http://127.0.0.1:8000/schema/">
    snippets: {
        list([page])
        read(id)
        highlight(id)
    }
    users: {
        list([page])
        read(id)
    }

Затем я добавляю учетные данные администратора суперпользователя:

coreapi credentials add 127.0.0.1 "admin:password" --auth basic
Added credentials
127.0.0.1 "Basic BlahBlahBlah="

Похоже, что coreapi успешно добавил учетные данные, но когда я пытаюсь перезагрузить схему, я все равно получаю те же методы:

$ coreapi reload
<Pastebin API "http://127.0.0.1:8000/schema/">
    snippets: {
        list([page])
        read(id)
        highlight(id)
    }
    users: {
        list([page])
        read(id)
    }

Я обнаружил, что нет Authorization заголовок в GET-запросе со значением Basic BlahBlahBlah=:

$ coreapi reload --debug
> GET /schema/ HTTP/1.1
> Accept-Encoding: gzip, deflate
> Connection: keep-alive
> Accept: application/coreapi+json, application/vnd.coreapi+json, */*
> Host: 127.0.0.1
> User-Agent: coreapi

Что ж, давайте попробуем добавить этот заголовок к нашему запросу вручную:

$ coreapi headers add "Authorization" "Basic BlahBlahBlah="
Added header
Authorization: Basic BlahBlahBlah=

Попробуйте еще раз, чтобы получить схему:

$ coreapi get http://127.0.0.1:8000/schema/
<Pastebin API "http://127.0.0.1:8000/schema/">
    snippets: {
        list([page])
        create(code, [title], [linenos], [language], [style])
        read(id)
        update(id, code, [title], [linenos], [language], [style])
        partial_update(id, [title], [code], [linenos], [language], [style])
        delete(id)
        highlight(id)
    }
    users: {
        list([page])
        read(id)
    }

Теперь я вижу все другие методы, доступные только авторизованным пользователям. Если я выполню предыдущую команду с --debug вариант, там будет заголовок:

> GET /schema/ HTTP/1.1
> Accept-Encoding: gzip, deflate
> Connection: keep-alive
> Accept: application/coreapi+json, application/vnd.coreapi+json, */*
> Authorization: Basic BlahBlahBlah=
> Host: 127.0.0.1
> User-Agent: coreapi

Например, теперь я могу создать фрагмент кода:

$ coreapi action snippets create --param title="Example" --param code="print('hello, world')"
{
    "url": "http://127.0.0.1:8000/snippets/6/",
    "id": 6,
    "highlight": "http://127.0.0.1:8000/snippets/6/highlight/",
    "owner": "admin",
    "title": "Example",
    "code": "print('hello, world')",
    "linenos": false,
    "language": "python",
    "style": "friendly"
}

Но все же остается вопрос: почему coreapi не добавляет заголовок авторизации автоматически?

Я обнаружил точно такую ​​же проблему в учебнике по Django Rest Framework, так что это проблема с этими версиями:

$ pip list
...
coreapi (2.3.3)
coreapi-cli (1.0.6)
...

Проблема задокументирована здесь: https://github.com/core-api/coreapi-cli/issues/19. Соответствующая выдержка:

coreapi-cli использует устаревший аргумент учетных данных для HTTPTransport вместо auth. Как вы можете видеть из кода здесь, coreapi 2.3.1 принимает этот устаревший аргумент, но затем ничего не делает с ним. Вот почему эта библиотека больше не будет отправлять заголовки аутентификации.

Я могу подтвердить, что добавление заголовка исправило это для меня. В итоге:

coreapi clear
coreapi credentials add 127.0.0.1 admin:password --auth basic
coreapi credentials show
coreapi headers add "Authorization" "Basic ...=="
coreapi get http://127.0.0.1:8000/schema/ --debug

Скопируйте и вставьте строку из команды "credentials show" в команду "headers add".

Это известная ошибка в версии 2.3.x. Coreapi-Cli. Исправление в ближайшее время, смотрите:

Проблема отслеживается на Github

Обходной путь - согласно предыдущему ответу Сергея Дулевича.

Просто хотел отметить, что я не вижу этих проблем при непосредственном использовании клиента Python (при предоставлении учетных данных Basic Auth).

from coreapi import Client

client = Client(auth=HTTPBasicAuth('user', 'pass'))
document = client.get(args.endpoint)
data = client.action(document, ['catalog', 'create', ], params={
        'start': '2018-08-30T10:00:00Z',
        'end': '2018-08-30T11:00:00Z',
        'filename': 'my-filename',
    })

Это также случилось со мной после аутентификации на basic-auth с:

$ coreapi credentials add 127.0.0.1 <user>:'<pass>' --auth basic

Теперь вы найдете список REST un-SAFE методов, используя: coreapi action snippets list - проверьте эти методы:

    list([page])
    create(code, [title], [linenos], [language], [style])
    read(id)
    update(id, code, [title], [linenos], [language], [style])
    partial_update(id, [title], [code], [linenos], [language], [style])
    delete(id)
    read_0(id, format)
    read_1(id, format)
    update_0(id, format, code, [title], [linenos], [language], [style])
    partial_update_0(id, format, [title], [code], [linenos], [language], [style])
    delete_0(id, format)

Тогда, если я попытался создать такой ресурс, как:

$ coreapi action snippets create --param title="Example" --param code="print('hello, world from the CLI')"

это потерпит неудачу с "Index ['snippets']['create'] did not reference a link. Key 'create' was not found."

Я смог решить эту проблему, снова прочитав схему после шага аутентификации:

$ coreapi get http://127.0.0.1:8008/schema/

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

Попробуйте и посмотрите, работает ли он на вас.

Другие вопросы по тегам