2016-08-16 2 views
0

Я реализую REST API в Python, используя Flask. Мне нужно получить параметры для выполнения запроса и возврата ресурсов. Чтобы быть выровненными с принципами REST, я собираюсь использовать запрос GET для этой операции.Как получить данные GETted json в Flask

Учитывая, что может быть много параметров, я хочу, чтобы отправить их через conf.json файл, например:

{"parameter": "xxx"} 

Я выполнить запрос через curl:

$ завиток - H "Content-Type: application/json" --data @ conf.json -G http://localhost:8080/resources/

Запрос перенаправляется ИДКТК на маршрут с этими операциями:

@resources.route('/resources/', methods=['GET']) 
def discover(): 
if request.get_json(): 
    json_data=request.get_json() 
    return jsonify(json_data) 

что я получаю обратно:

<head> 
<title>Error response</title> 
</head> 
<body> 
<h1>Error response</h1> 
<p>Error code 400. 
<p>Message: Bad request syntax ('GET /resources/?{"parameter": "xxx"} HTTP/1.1'). 
<p>Error code explanation: 400 = Bad request syntax or unsupported method. </body> 

Кто-нибудь знает, как получить данные JSON и правильно обращаться с этим в запросе?

+0

@ загружает файл в качестве параметра URL-адрес, так как запрос GET типа. Это выглядит не очень хорошо и может вызвать множество проблем с кодировкой символов. Ты уверен, что так оно и есть? – Fma

ответ

4

request.get_json() ищет данные JSON в запросе тело (например, какой запрос POST будет включать). Вы помещаете данные JSON в строку запроса URL-адреса запроса GET.

Ваша команда curl посылает ваш JSON неэкранированных, и выдает неверный URL, так что сервер справедливо отвергает, что:

http://localhost:8080/resources/?{"parameter": "xxx"} 

Вы не можете иметь пробелы в URL-адрес, например. Вы должны были бы использовать вместо --data-urlencode для этого быть экранированы:

$ curl --data-urlencode @conf.json -G http://localhost:8080/resources/ 

Обратите внимание, что заголовок Content-Type здесь не требуется; у вас нет какого-либо органа запроса для записи контента из.

Скорректированный curl Теперь команда отправляет правильно закодированный URL:

http://localhost:8080/resources/?%7B%22parameter%22%3A%20%22xxx%22%7D%0A%0A 

доступ к этим данным request.query_string. Вы также должны декодирования URL-адрес кодирование снова перед передачей это json.loads():

from urllib import unquote 

json_raw_data = unquote(request.query_string) 
json_data = json.loads(json_raw_data) 

Примите во внимание, что многие веб-сервера поставить ограничения на сколько время URL они будут принимать. Если вы планируете отправлять более 4 тыс. Символов в URL-адресе таким образом, вам действительно нужно пересмотреть и использовать вместо него запросы POST. Это 4k с данными JSON URL-код, что добавляет значительные накладные расходы.

0

Мартейн ответ был прав с этим

$ curl --data-urlencode @conf.json -G http://localhost:8080/resources/ 

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

@resources.route('/resources') 
def test(): 
    args = request.args 
    return args.get('parameter') 

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

from flask_testing import TestCase 
from app import app 

class TestQueryString(TestCase): 

    def create_app(self): # Must be implemented 
     return app 

    def test_json_parse_args(self): 
     data = { 
      'parameter': 'value' 
     } 

     r = self.client.get('/resources', query_string=data) 
     self.assert200(r) 
     self.assertEqual(r.data, 'value') 

https://pythonhosted.org/Flask-Testing/

+0

Спасибо Адаму. Я попытался, но не используя 'urllib', я не могу получить аргументы. Колба Процесс 'ImmutableMultiDict' в арг, как это: ' ImmutableMultiDict ([({ "Параметр": "ххх"} ', и '')]) ' вместо того, чтобы, чем: ' ImmutableMultiDict ([('parameter': u'xxx ')]) ' Так что он не разбирает аргументы в {} Я думаю – adefabritiis

+0

Да, но на самом деле вы не собираетесь взаимодействовать с API через' curl' в производстве. Вы собираетесь использовать язык программирования для отправки запроса, будь то JS или Python. Также, если вы используете '-d parameter = value', он даст вам правильную строку запроса и будет работать. – Adam

Смежные вопросы