Search code examples
pythonwebserver

spin up a simple web server that prints post data to console


I've found a number of simple web servers in python that will spin up a quick server and respond to requests simply. What I need is a server that won't just print the IP address, timestamp, method, and response code of each request (127.0.0.1 - - [28/Aug/2017 10:42:11] "POST / HTTP/1.1" 200 -), but also, if a POST request, I need it to print out the POST data.

So for example, if I send a POST request with {"foo":"bar"} in the body of the message, I want the server to print 127.0.0.1 - - [28/Aug/2017 10:42:11] "POST / HTTP/1.1" 200 - {"foo":"bar"} to the console before responding.

I'm not sure how to modify any of the linked options above to do this. If there's another simple option, that would work as well.


Solution

  • To just print out whatever JSON gets sent to a server, build yourself a basic catch-all endpoint and just print the JSON from it. In flask, this looks like the following:

    import logging
    from flask import Flask, request
    app = Flask(__name__)
    
    @app.route('/', methods=['POST', 'GET'], defaults={'path': ''})
    @app.route('/<path:path>', methods=['POST', 'GET'])
    def index(path):
        print("HTTP {} to URL /{} received JSON {}".format(request.method, path, request.get_json()))
        return "True"
    

    Here's my calls to the server:

    In [15]: requests.post('http://localhost:5000/', json={'a': 1})
    Out[15]: <Response [200]>
    
    In [16]: requests.post('http://localhost:5000/some/endpoint', json={'a': 1})
    Out[16]: <Response [200]>
    
    In [17]: requests.get('http://localhost:5000/', json={'a': 1})
    Out[17]: <Response [200]>
    

    Here's the server output:

    In [7]: app.run(host='0.0.0.0')
     * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    HTTP POST to URL / received JSON {'a': 1}
    127.0.0.1 - - [28/Aug/2017 11:57:49] "POST / HTTP/1.1" 200 -
    HTTP POST to URL /some/endpoint received JSON {'a': 1}
    127.0.0.1 - - [28/Aug/2017 11:57:51] "POST /some/endpoint HTTP/1.1" 200 -
    HTTP GET to URL / received JSON {'a': 1}
    127.0.0.1 - - [28/Aug/2017 11:57:55] "GET / HTTP/1.1" 200 -
    

    Original Answer

    A simple decorator should do the trick:

    from flask import Flask, request
    app = Flask(__name__)
    
    def print_if_post(*args, **kwargs):
        def inner_decorator(f):
            def inner(*args, **kwargs):
                if request.method == 'POST':
                    json = request.get_json()
                    print("JSON Data: {}".format(json))
    
                return f(*args, **kwargs)
    
            return app.route(*args, **kwargs)(inner)
        return inner_decorator
    

    This decorator will function exactly like app.route, but will print any JSON data sent to its endpoint:

    @print_if_post('/', methods=['POST', 'GET'])
    def index():
        return "True"
    

    Called with the following code:

    In [4]: requests.get('http://localhost:5000/')
    Out[4]: <Response [200]>
    
    In [5]: requests.post('http://localhost:5000/', json={'a': 1})
    Out[5]: <Response [200]>
    

    Server outputs:

    In [2]: app.run(host='0.0.0.0')
     * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    127.0.0.1 - - [28/Aug/2017 11:03:11] "GET / HTTP/1.1" 200 -
    JSON Data: {'a': 1}
    127.0.0.1 - - [28/Aug/2017 11:03:23] "POST / HTTP/1.1" 200 -