Skip to content
This repository has been archived by the owner on Jan 13, 2021. It is now read-only.

No POST data send with HTTP/2 client (no Content-Length header) #320

Closed
michal-niklas opened this issue Apr 27, 2017 · 3 comments
Closed

Comments

@michal-niklas
Copy link

I have build simple HTTP, HTTPS and HTTP/2 client based on Python hyper library. When I test it on my Jetty based WebService I see that hyper HTTP/2 client do not send POST data like HTTP and HTTPS.

My code looks like:

#!/usr/bin/env python3
# -*- coding: utf8 -*-

PY3 = 0
try:
	import urllib.parse
	PY3 = 1
except:
	import urlparse
import os.path
import ssl
import sys
import traceback

import hyper

DEFAULT_CA_FILE = '/etc/heuthes/ca.crt'

TEST_URLS = """
http://127.0.0.1:8765/isof/echo.hdb
https://stresstest.heuthesd:18443/isof/echo.hdb
"""


def http2_simply_get(url, ssl_context=None):
	try:
		parsed = urllib.parse.urlparse(url)
	except:
		parsed = urlparse.urlparse(url)
	secure = url.startswith('https')
	if secure:
		if not ssl_context:
			if os.path.isfile(DEFAULT_CA_FILE):
				ssl_context = ssl.create_default_context(cafile=DEFAULT_CA_FILE)
			else:
				ssl_context = ssl.create_default_context()
		# comment next line if you want to test only HTTPS
		# unocmment next line if you want to test HTTP/2
		ssl_context.set_alpn_protocols(["h2", "http/1.1"])
	conn = hyper.HTTPConnection(parsed.netloc, secure=secure, ssl_context=ssl_context)
	path_and_qry = parsed.path
	p = url.find(parsed.path)
	if p >= 0:
		path_and_qry = url[p:]
	param_value = 'zorro'
	if PY3:
		body = bytes('param=%s' % (param_value), 'UTF-8')
	else:
		body = 'param=%s' % (param_value)
	conn.request('POST', path_and_qry, body=body)
	result = conn.get_response().read().decode('UTF-8')
	if '<param>%s</param>' % (param_value) in result:
		print('test ok')
	else:
		print('\n\ntest ERROR!!! no param value in response!!!\n\n')
	return result


def test():
	for url in TEST_URLS.split('\n'):
		url = url.strip()
		if url and not url.startswith('#'):
			print('url: [%s]' % (url))
			try:
				http2_response = http2_simply_get(url)
				print(http2_response)
			except Exception as e:
				s = traceback.format_exc()
				print('\n!!!\n!!! Exception: [%s]\n%s\n' % (e, s))
			print('\n--------\n\n\n')


if __name__ == '__main__':
	if '--test' in sys.argv:
		test()

Of course you have to add your own WebService url and CA file.

To test it with HTTP/2 you must uncomment line:

ssl_context.set_alpn_protocols(["h2", "http/1.1"])

To test it with HTTPS you must comment it.

My results:

url: [http://127.0.0.1:8765/isof/echo.hdb]
test ok
<?xml version="1.0" encoding="UTF-8"?>
<info>
<param>zorro</param>
</info>
--------

url: [https://stresstest.heuthesd:18443/isof/echo.hdb]

test ERROR!!! no param value in response!!!

<?xml version="1.0" encoding="UTF-8"?>
<info>
<param></param>
</info>
--------

Of course my WebService works well with Chrome and Firefox using HTTP/2.

I have found similar problem:
#206

When I use HTTP/2 client it probably do not send Content-Length header. With other clients I receive:
http_content_length=11

I test it with hyper 0.7 on Fedora Linux with Python 2.7.13 and Python 3.5.3.

@Lukasa
Copy link
Member

Lukasa commented Apr 27, 2017

Can you confirm that Jetty requires a content-length by manually setting the content-length header yourself in the request to see if that works?

@michal-niklas
Copy link
Author

Yes, when I add that header:

conn.request('POST', path_and_qry, body=body, headers={'content-length': '11'})

I got response with data read from the query body.

@Lukasa
Copy link
Member

Lukasa commented Apr 27, 2017

Ok, so this is a duplicate of #206. If you'd like to pick up the patch from that issue and resolve my concerns with it from that bug report, I'll happily review that fix. =)

@Lukasa Lukasa closed this as completed Apr 27, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants