1

I am trying to implement a client-server using tornado_http2 api in python but server never receive messages from the client.

I have checked that server is well started with this comm

and and I had this result:
(mmsx-TPjM8MGB-py3.9) xx@ITLP071: 7 (master) ~/dev/mmsx/tornado_http2/demo$ proxy=127.0.0.1:8443; curl --http2-prior-knowledge -d "bla bla" -X POST https://localhost:8443/ -E test.crt
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html
 
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

And from the output server :

(mmsx-TPjM8MGB-py3.9) xx@ITLP071: 130 (master) ~/dev/mmsx/tornado_http2/demo$ poetry run python server_test.py
[I 220722 04:02:37 server_test:30] starting
[W 220722 04:02:41 iostream:1517] SSL Error on 7 ('127.0.0.1', 60040): [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:1123)

The connection is not perfectly done (that I do not succed to resolve for now) but at least I have a reaction from the server.

With request from the client, I have no response.

Please find my server code below:

import logging
import os
import ssl

from tornado.ioloop import IOLoop
from tornado.options import parse_command_line
from tornado.web import Application, RequestHandler
from tornado_http2.server import Server


class MainHandler(RequestHandler):
    def get(self):
        self.write("Hello world")

    def post(self):
        self.write("bla bla")


def main():
    parse_command_line()
    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    ssl_ctx.load_cert_chain(
        os.path.join(os.path.dirname(__file__), 'test.crt'),
        os.path.join(os.path.dirname(__file__), 'test.key'))
    app = Application([('/hello', MainHandler)], debug=True)
    server = Server(app, ssl_options=ssl_ctx)
    port = 8443
    address = "127.0.0.1"
    server.listen(port, address)
    logging.info("starting")
    IOLoop.instance().start()


if __name__ == '__main__':
    main()

And my client code:

from tornado_http2.curl import CurlAsyncHTTP2Client as HTTP2Client
import asyncio


URI = "http:127.0.0.1:8443/hello"


class Test():
    def __init__(self):
        self.__client = HTTP2Client(force_instance=True)

    async def send(self):
        global URI
        body = "body"
        response = await self.__client.fetch(URI, method='POST', body=body,
                                             validate_cert=False)
        print(response)


def main():
    asyncio.run(Test().send())


if __name__ == "__main__":
    main()

I started the server in a terminal and then the client in another one and for me, it should displayed in the client console the result of the request.

Thanks for your help !

Le E
  • 11
  • 1

1 Answers1

0

OK, I have found.

It is a bug in tornado_http2 api. The event loop has to be created before the instanciation of the class HTTP2Client, else this does not work.

If the client code is remplaced bu this, it will work :

from tornado_http2.curl import CurlAsyncHTTP2Client as HTTP2Client
import asyncio
from tornado.httpclient import AsyncHTTPClient

from tornado.ioloop import IOLoop


class Test():
    def __init__(self):
        self.__client = HTTP2Client(force_instance=True)

    async def send(self):
        uri = "https://127.0.0.1:8443/hello"
        response = await self.__client.fetch(uri, validate_cert=False)
        print(response.body.decode('utf-8'))

def run_asyncio():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        return loop.run_until_complete(Test().send())
    finally:
        loop.close()
        asyncio.set_event_loop(None)

def main():
    run_asyncio()


if __name__ == "__main__":
    main()

Hopefully it will help someone =).

Le E
  • 11
  • 1