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/
Это должно действовать как обновление схемы, а затем позволяет создавать ресурс, используя точно такой же код сверху.
Попробуйте и посмотрите, работает ли он на вас.