6

I'm attempting to make the simplest possible REST API server and client, with both the server and client being written in Python and running on the same computer.

From this tutorial:

https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask

I'm using this for the server:

# server.py

from flask import Flask, jsonify

app = Flask(__name__)

tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]

@app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
    return jsonify({'tasks': tasks})

if __name__ == '__main__':
    app.run(debug=True)

If I run this from the command line:

curl -i http://localhost:5000/todo/api/v1.0/tasks

I get this:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 317
Server: Werkzeug/0.16.0 Python/3.6.9
Date: Thu, 05 Mar 2020 02:45:59 GMT

{
  "tasks": [
    {
      "description": "Milk, Cheese, Pizza, Fruit, Tylenol", 
      "done": false, 
      "id": 1, 
      "title": "Buy groceries"
    }, 
    {
      "description": "Need to find a good Python tutorial on the web", 
      "done": false, 
      "id": 2, 
      "title": "Learn Python"
    }
  ]
}

Great, now my question is, how can I write a Python script using requests to obtain the same information?

I suspect this is the proper idea:

# client.py

import requests

url = 'http://todo/api/v1.0/tasks'

response = requests.get(url,
                        # what goes here ??
                        )

print('response = ' + str(response))

However as you can see from my comment, I'm not sure how to set up the parameters for requests.get.

I attempted to use this SO post:

Making a request to a RESTful API using python

as a guideline however it's not clear how to adjust the formatting per the message change.

Can provide a brief description of how to set up params to pass into requests.get and suggest the necessary changes to get the client example above working? Thanks!

--- Edit ---

Something else I can mention is that I got the client to work using Postman pretty easily, I'm just not sure how to set up the syntax in Python:

enter image description here

--- Edit ---

Based on icedwater's response below, this is complete, working code for the client:

# client.py

import requests
import json

url = 'http://localhost:5000/todo/api/v1.0/tasks'

response = requests.get(url)

print(str(response))
print('')
print(json.dumps(response.json(), indent=4))

result:

<Response [200]>

{
    "tasks": [
        {
            "description": "Milk, Cheese, Pizza, Fruit, Tylenol",
            "done": false,
            "id": 1,
            "title": "Buy groceries"
        },
        {
            "description": "Need to find a good Python tutorial on the web",
            "done": false,
            "id": 2,
            "title": "Learn Python"
        }
    ]
}
cdahms
  • 3,402
  • 10
  • 49
  • 75
  • It looks like `url` hasn't been defined correctly to reach the endpoint. Can you check that, please? – icedwater Mar 05 '20 at 02:56
  • 1
    I have mixed feelings about the amount of detail in this post. It's useful, but might be overwhelming too. Consider making the question shorter so people can see what it is? :P – icedwater Mar 05 '20 at 02:58
  • 1
    `data = requests.get(...).json()` then `for task in data['tasks']` – Joran Beasley Mar 05 '20 at 02:58
  • 1
    @icedwater, if the client works using Curl and Postman, how can the endpoint be at fault? Doesn't Curl and Postman working prove out that I'm just missing the necessary lines in Python? – cdahms Mar 05 '20 at 03:02
  • Because I only see `http://todo/...` in your Python script, rather than `http://localhost:5000/todo/...`, so I asked. – icedwater Mar 05 '20 at 03:04
  • 1
    I'm now to rest so I'm not sure where the 5000 is from, perhaps some sort of default. In any case if Curl and Postman can receive the message it has to be possible to make a Python script to receive the message as well. – cdahms Mar 05 '20 at 03:09
  • When you run the first Python script, which port does Flask say it's listening on? Does your `curl` request work with `http://localhost/todo/api/v1.0/tasks` as well? – icedwater Mar 05 '20 at 03:14

1 Answers1

3

From help(requests.get):

Help on function get in module requests.api:

get(url, params=None, **kwargs)
    Sends a GET request.

    :param url: URL for the new :class:`Request` object.
    :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response

so I would say requests.get(url) would be enough to get a response. Then look at either the json() or data() functions in response depending on what the API is expected to return.

So for the case of a JSON response, the following code should be enough:

import requests
import json

url = "https://postman-echo.com/get?testprop=testval"
response = requests.get(url)
print(json.dumps(response.json(), indent=4))

Try the above code with an actual test API.

icedwater
  • 4,701
  • 3
  • 35
  • 50
  • If I change to URL text to 'http://todo/api/v1.0/tasks' to be consistent with the server, with your code I get the error 'http://todo/api/v1.0/tasks' – cdahms Mar 05 '20 at 03:07
  • Thanks @cdahms for the response, I'm glad it was helpful. But I'm not sure it was necessary to add it to the answer, so I rejected the edit. – icedwater Mar 05 '20 at 03:21