aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libpathod/language/__init__.py14
-rw-r--r--libpathod/language/http.py6
-rw-r--r--libpathod/language/http2.py113
-rw-r--r--libpathod/pathoc.py8
-rw-r--r--libpathod/pathoc_cmdline.py15
-rw-r--r--libpathod/pathod.py214
-rw-r--r--libpathod/pathod_cmdline.py15
-rw-r--r--libpathod/utils.py10
-rw-r--r--test/test_language_http2.py3
-rw-r--r--test/test_pathoc.py7
10 files changed, 296 insertions, 109 deletions
diff --git a/libpathod/language/__init__.py b/libpathod/language/__init__.py
index ae9a8c76..10050bf8 100644
--- a/libpathod/language/__init__.py
+++ b/libpathod/language/__init__.py
@@ -19,7 +19,7 @@ def expand(msg):
yield msg
-def parse_pathod(s):
+def parse_pathod(s, use_http2=False):
"""
May raise ParseException
"""
@@ -28,12 +28,17 @@ def parse_pathod(s):
except UnicodeError:
raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0)
try:
- reqs = pp.Or(
- [
+ if use_http2:
+ expressions = [
+ # http2.Frame.expr(),
+ http2.Response.expr(),
+ ]
+ else:
+ expressions = [
websockets.WebsocketFrame.expr(),
http.Response.expr(),
]
- ).parseString(s, parseAll=True)
+ reqs = pp.Or(expressions).parseString(s, parseAll=True)
except pp.ParseException as v:
raise exceptions.ParseException(v.msg, v.line, v.col)
return itertools.chain(*[expand(i) for i in reqs])
@@ -55,7 +60,6 @@ def parse_pathoc(s, use_http2=False):
websockets.WebsocketClientFrame.expr(),
http.Request.expr(),
]
-
reqs = pp.OneOrMore(pp.Or(expressions)).parseString(s, parseAll=True)
except pp.ParseException as v:
raise exceptions.ParseException(v.msg, v.line, v.col)
diff --git a/libpathod/language/http.py b/libpathod/language/http.py
index 9a8404f0..115f8069 100644
--- a/libpathod/language/http.py
+++ b/libpathod/language/http.py
@@ -367,10 +367,6 @@ class Request(_HTTPMessage):
return ":".join([i.spec() for i in self.tokens])
-class PathodErrorResponse(Response):
- pass
-
-
def make_error_response(reason, body=None):
tokens = [
Code("800"),
@@ -381,4 +377,4 @@ def make_error_response(reason, body=None):
Reason(base.TokValueLiteral(reason)),
Body(base.TokValueLiteral("pathod error: " + (body or reason))),
]
- return PathodErrorResponse(tokens)
+ return Response(tokens)
diff --git a/libpathod/language/http2.py b/libpathod/language/http2.py
index 4a5b9084..1d2517d3 100644
--- a/libpathod/language/http2.py
+++ b/libpathod/language/http2.py
@@ -45,14 +45,20 @@ class Body(base.Value):
class Times(base.Integer):
preamble = "x"
+class Code(base.Integer):
+ pass
class Request(message.Message):
comps = (
Header,
Body,
-
Times,
)
+ logattrs = ["method", "path"]
+
+ def __init__(self, tokens):
+ super(Response, self).__init__(tokens)
+ self.rendered_values = None
@property
def method(self):
@@ -87,7 +93,6 @@ class Request(message.Message):
Method.expr(),
base.Sep,
Path.expr(),
- base.Sep,
pp.ZeroOrMore(base.Sep + atom)
]
)
@@ -95,21 +100,109 @@ class Request(message.Message):
return resp
def resolve(self, settings, msg=None):
- tokens = self.tokens[:]
- return self.__class__(
- [i.resolve(settings, self) for i in tokens]
+ return self
+
+ def values(self, settings):
+ if self.rendered_values:
+ return self.rendered_values
+ else:
+ headers = self.headers
+ if headers:
+ headers = headers.values(settings)
+
+ body = self.body
+ if body:
+ body = body.string()
+
+ self.rendered_values = settings.protocol.create_request(
+ self.method.string(),
+ self.path.string(),
+ headers, # TODO: parse that into a dict?!
+ body)
+ return self.rendered_values
+
+ def spec(self):
+ return ":".join([i.spec() for i in self.tokens])
+
+
+class Response(message.Message):
+ unique_name = None
+ comps = (
+ Header,
+ Body,
+ )
+
+ def __init__(self, tokens):
+ super(Response, self).__init__(tokens)
+ self.rendered_values = None
+ self.stream_id = 0
+
+ @property
+ def code(self):
+ return self.tok(Code)
+
+ @property
+ def headers(self):
+ return self.toks(Header)
+
+ @property
+ def body(self):
+ return self.tok(Body)
+
+ @property
+ def actions(self):
+ return []
+
+ def resolve(self, settings, msg=None):
+ return self
+
+ @classmethod
+ def expr(klass):
+ parts = [i.expr() for i in klass.comps]
+ atom = pp.MatchFirst(parts)
+ resp = pp.And(
+ [
+ Code.expr(),
+ pp.ZeroOrMore(base.Sep + atom)
+ ]
)
+ resp = resp.setParseAction(klass)
+ return resp
def values(self, settings):
- return settings.protocol.create_request(
- self.method.string(),
- self.path,
- self.headers,
- self.body)
+ if self.rendered_values:
+ return self.rendered_values
+ else:
+ headers = self.headers
+ if headers:
+ headers = headers.values(settings)
+
+ body = self.body
+ if body:
+ body = body.values(settings)
+
+ self.rendered_values = settings.protocol.create_response(
+ self.code.string(),
+ self.stream_id,
+ headers, # TODO: parse that into a dict?!
+ body)
+ return self.rendered_values
def spec(self):
return ":".join([i.spec() for i in self.tokens])
+def make_error_response(reason, body=None):
+ raise NotImplementedError
+ # tokens = [
+ # Code("800"),
+ # Header(
+ # base.TokValueLiteral("Content-Type"),
+ # base.TokValueLiteral("text/plain")
+ # ),
+ # Reason(base.TokValueLiteral(reason)),
+ # Body(base.TokValueLiteral("pathod error: " + (body or reason))),
+ # ]
+ # return Response(tokens)
# class Frame(message.Message):
# pass
diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py
index e9bd5f56..9c021360 100644
--- a/libpathod/pathoc.py
+++ b/libpathod/pathoc.py
@@ -155,13 +155,14 @@ class Pathoc(tcp.TCPClient):
# SSL
ssl=None,
sni=None,
- sslversion=4,
+ sslversion='SSLv23',
clientcert=None,
ciphers=None,
# HTTP/2
use_http2=False,
http2_skip_connection_preface=False,
+ http2_framedump = False,
# Websockets
ws_read_limit = None,
@@ -199,6 +200,7 @@ class Pathoc(tcp.TCPClient):
self.use_http2 = use_http2
self.http2_skip_connection_preface = http2_skip_connection_preface
+ self.http2_framedump = http2_framedump
self.ws_read_limit = ws_read_limit
@@ -219,7 +221,6 @@ class Pathoc(tcp.TCPClient):
if not OpenSSL._util.lib.Cryptography_HAS_ALPN: # pragma: nocover
print >> sys.stderr, "HTTP/2 requires ALPN support. Please use OpenSSL >= 1.0.2."
print >> sys.stderr, "Pathoc might not be working as expected without ALPN."
-
self.protocol = http2.HTTP2Protocol(self)
else:
# TODO: create HTTP or Websockets protocol
@@ -298,7 +299,7 @@ class Pathoc(tcp.TCPClient):
if self.use_http2:
self.protocol.check_alpn()
if not self.http2_skip_connection_preface:
- self.protocol.perform_connection_preface()
+ self.protocol.perform_client_connection_preface()
if self.timeout:
self.settimeout(self.timeout)
@@ -466,6 +467,7 @@ def main(args): # pragma: nocover
ciphers = args.ciphers,
use_http2 = args.use_http2,
http2_skip_connection_preface = args.http2_skip_connection_preface,
+ http2_framedump = args.http2_framedump,
showreq = args.showreq,
showresp = args.showresp,
explain = args.explain,
diff --git a/libpathod/pathoc_cmdline.py b/libpathod/pathoc_cmdline.py
index dcd75d11..1d0df3b5 100644
--- a/libpathod/pathoc_cmdline.py
+++ b/libpathod/pathoc_cmdline.py
@@ -109,12 +109,11 @@ def args_pathoc(argv, stdout=sys.stdout, stderr=sys.stderr):
help="SSL cipher specification"
)
group.add_argument(
- "--sslversion", dest="sslversion", type=int, default=4,
- choices=[1, 2, 3, 4],
- help="""
- Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default
- to SSLv23.
- """
+ "--sslversion", dest="sslversion", type=str, default='SSLv23',
+ choices=utils.SSLVERSIONS.keys(),
+ help=""""
+ Use a specified protocol - TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23.
+ Default to SSLv23."""
)
group = parser.add_argument_group(
@@ -156,6 +155,10 @@ def args_pathoc(argv, stdout=sys.stdout, stderr=sys.stderr):
"-x", dest="hexdump", action="store_true", default=False,
help="Output in hexdump format"
)
+ group.add_argument(
+ "--http2-framedump", dest="http2_framedump", action="store_true", default=False,
+ help="Output all received & sent HTTP/2 frames"
+ )
args = parser.parse_args(argv[1:])
diff --git a/libpathod/pathod.py b/libpathod/pathod.py
index f1496181..535340cb 100644
--- a/libpathod/pathod.py
+++ b/libpathod/pathod.py
@@ -7,7 +7,7 @@ import urllib
import re
import time
-from netlib import tcp, http, wsgi, certutils, websockets
+from netlib import tcp, http, http2, wsgi, certutils, websockets, odict
from . import version, app, language, utils, log
import language.http
@@ -40,7 +40,7 @@ class SSLOptions:
sslversion=tcp.SSLv23_METHOD,
ciphers=None,
certs=None,
- alpn_select=None,
+ alpn_select=http2.HTTP2Protocol.ALPN_PROTO_H2,
):
self.confdir = confdir
self.cn = cn
@@ -69,32 +69,37 @@ class PathodHandler(tcp.BaseHandler):
wbufsize = 0
sni = None
- def __init__(self, connection, address, server, logfp, settings):
- self.logfp = logfp
+ def __init__(self, connection, address, server, logfp, settings, http2_framedump=False):
tcp.BaseHandler.__init__(self, connection, address, server)
+ self.logfp = logfp
self.settings = copy.copy(settings)
+ self.protocol = None
+ self.use_http2 = False
+ self.http2_framedump = http2_framedump
- def handle_sni(self, connection):
+ def _handle_sni(self, connection):
self.sni = connection.get_servername()
def http_serve_crafted(self, crafted):
+ """
+ This method is HTTP/1 and HTTP/2 capable.
+ """
+
error, crafted = self.server.check_policy(
crafted, self.settings
)
if error:
- err = language.http.make_error_response(error)
+ err = self.make_http_error_response(error)
language.serve(err, self.wfile, self.settings)
return None, dict(
type="error",
msg = error
)
- if self.server.explain and not isinstance(
- crafted,
- language.http.PathodErrorResponse
- ):
+ if self.server.explain and not hasattr(crafted, 'is_error_response'):
crafted = crafted.freeze(self.settings)
log.write(self.logfp, ">> Spec: %s" % crafted.spec())
+
response_log = language.serve(
crafted,
self.wfile,
@@ -154,6 +159,8 @@ class PathodHandler(tcp.BaseHandler):
def handle_http_connect(self, connect, lg):
"""
+ This method is HTTP/1 only.
+
Handle a CONNECT request.
"""
http.read_headers(self.rfile)
@@ -171,7 +178,7 @@ class PathodHandler(tcp.BaseHandler):
self.convert_to_ssl(
cert,
key,
- handle_sni=self.handle_sni,
+ handle_sni=self._handle_sni,
request_client_cert=self.server.ssloptions.request_client_cert,
cipher_list=self.server.ssloptions.ciphers,
method=self.server.ssloptions.sslversion,
@@ -185,10 +192,12 @@ class PathodHandler(tcp.BaseHandler):
def handle_http_app(self, method, path, headers, content, lg):
"""
+ This method is HTTP/1 only.
+
Handle a request to the built-in app.
"""
if self.server.noweb:
- crafted = language.http.make_error_response("Access Denied")
+ crafted = self.make_http_error_response("Access Denied")
language.serve(crafted, self.wfile, self.settings)
return None, dict(
type="error",
@@ -209,6 +218,8 @@ class PathodHandler(tcp.BaseHandler):
def handle_http_request(self):
"""
+ This method is HTTP/1 and HTTP/2 capable.
+
Returns a (handler, log) tuple.
handler: Handler for the next request, or None to disconnect
@@ -217,28 +228,24 @@ class PathodHandler(tcp.BaseHandler):
lr = self.rfile if self.server.logreq else None
lw = self.wfile if self.server.logresp else None
with log.Log(self.logfp, self.server.hexdump, lr, lw) as lg:
- line = http.get_request_line(self.rfile)
- if not line:
- # Normal termination
- return None, None
-
- m = utils.MemBool()
- if m(http.parse_init_connect(line)):
- return self.handle_http_connect(m.v, lg)
- elif m(http.parse_init_proxy(line)):
- method, _, _, _, path, httpversion = m.v
- elif m(http.parse_init_http(line)):
- method, path, httpversion = m.v
+ if self.use_http2:
+ self.protocol.perform_server_connection_preface()
+ stream_id, headers, body = self.protocol.read_request()
+ method = headers[':method']
+ path = headers[':path']
+ headers = odict.ODict(headers)
else:
- s = "Invalid first line: %s" % repr(line)
- lg(s)
- return None, dict(type="error", msg=s)
-
- headers = http.read_headers(self.rfile)
- if headers is None:
- s = "Invalid headers"
- lg(s)
- return None, dict(type="error", msg=s)
+ req = self.read_http_request(lg)
+ if 'next_handle' in req:
+ return req['next_handle']
+ if 'errors' in req:
+ return None, req['errors']
+ if not 'method' in req or not 'path' in req:
+ return None, None
+ method = req['method']
+ path = req['path']
+ headers = req['headers']
+ body = req['body']
clientcert = None
if self.clientcert:
@@ -258,7 +265,7 @@ class PathodHandler(tcp.BaseHandler):
path=path,
method=method,
headers=headers.lst,
- httpversion=httpversion,
+ # httpversion=httpversion,
sni=self.sni,
remote_address=self.address(),
clientcert=clientcert,
@@ -268,16 +275,6 @@ class PathodHandler(tcp.BaseHandler):
if self.ssl_established:
retlog["cipher"] = self.get_current_cipher()
- try:
- content = http.read_http_body(
- self.rfile, headers, None,
- method, None, True
- )
- except http.HttpError as s:
- s = str(s)
- lg(s)
- return None, dict(type="error", msg=s)
-
m = utils.MemBool()
websocket_key = websockets.check_client_handshake(headers)
self.settings.websocket_key = websocket_key
@@ -288,28 +285,37 @@ class PathodHandler(tcp.BaseHandler):
anchor_gen = language.parse_pathod("ws")
else:
anchor_gen = None
- for i in self.server.anchors:
- if i[0].match(path):
- anchor_gen = i[1]
+
+ for regex, spec in self.server.anchors:
+ if regex.match(path):
+ anchor_gen = language.parse_pathod(spec, self.use_http2)
break
else:
- print(self.server.craftanchor)
if m(path.startswith(self.server.craftanchor)):
spec = urllib.unquote(path)[len(self.server.craftanchor):]
if spec:
try:
- anchor_gen = language.parse_pathod(spec)
+ anchor_gen = language.parse_pathod(spec, self.use_http2)
except language.ParseException as v:
lg("Parse error: %s" % v.msg)
- anchor_gen = iter([language.http.make_error_response(
+ anchor_gen = iter([self.make_http_error_response(
"Parse Error",
"Error parsing response spec: %s\n" % (
v.msg + v.marked()
)
)])
+ else:
+ if self.use_http2:
+ raise NotImplementedError(\
+ "HTTP/2 only supports request/response with the craft anchor point.")
+
if anchor_gen:
spec = anchor_gen.next()
+
+ if self.use_http2 and isinstance(spec, language.http2.Response):
+ spec.stream_id = stream_id
+
lg("crafting spec: %s" % spec)
nexthandler, retlog["response"] = self.http_serve_crafted(
spec
@@ -319,28 +325,77 @@ class PathodHandler(tcp.BaseHandler):
else:
return nexthandler, retlog
else:
- return self.handle_http_app(method, path, headers, content, lg)
+ return self.handle_http_app(method, path, headers, body, lg)
- def addlog(self, log):
- # FIXME: The bytes in the log should not be escaped. We do this at the
- # moment because JSON encoding can't handle binary data, and I don't
- # want to base64 everything.
- if self.server.logreq:
- bytes = self.rfile.get_log().encode("string_escape")
- log["request_bytes"] = bytes
- if self.server.logresp:
- bytes = self.wfile.get_log().encode("string_escape")
- log["response_bytes"] = bytes
- self.server.add_log(log)
+ def read_http_request(self, lg):
+ """
+ This method is HTTP/1 only.
+ """
+ line = http.get_request_line(self.rfile)
+ if not line:
+ # Normal termination
+ return dict()
+
+ m = utils.MemBool()
+ if m(http.parse_init_connect(line)):
+ return dict(next_handle=self.handle_http_connect(m.v, lg))
+ elif m(http.parse_init_proxy(line)):
+ method, _, _, _, path, httpversion = m.v
+ elif m(http.parse_init_http(line)):
+ method, path, httpversion = m.v
+ else:
+ s = "Invalid first line: %s" % repr(line)
+ lg(s)
+ return dict(errors=dict(type="error", msg=s))
+
+ headers = http.read_headers(self.rfile)
+ if headers is None:
+ s = "Invalid headers"
+ lg(s)
+ return dict(errors=dict(type="error", msg=s))
+
+ try:
+ body = http.read_http_body(
+ self.rfile,
+ headers,
+ None,
+ method,
+ None,
+ True,
+ )
+ except http.HttpError as s:
+ s = str(s)
+ lg(s)
+ return dict(errors=dict(type="error", msg=s))
+
+ return dict(
+ method=method,
+ path=path,
+ headers=headers,
+ body=body)
+
+ def make_http_error_response(self, reason, body=None):
+ """
+ This method is HTTP/1 and HTTP/2 capable.
+ """
+ if self.use_http2:
+ resp = language.http2.make_error_response(reason, body)
+ else:
+ resp = language.http.make_error_response(reason, body)
+ resp.is_error_response = True
+ return resp
def handle(self):
+ self.settimeout(self.server.timeout)
+
if self.server.ssl:
try:
cert, key, _ = self.server.ssloptions.get_cert(None)
self.convert_to_ssl(
cert,
key,
- handle_sni=self.handle_sni,
+ dhparams=self.server.ssloptions.certstore.dhparams,
+ handle_sni=self._handle_sni,
request_client_cert=self.server.ssloptions.request_client_cert,
cipher_list=self.server.ssloptions.ciphers,
method=self.server.ssloptions.sslversion,
@@ -356,8 +411,20 @@ class PathodHandler(tcp.BaseHandler):
)
log.write(self.logfp, s)
return
- self.settimeout(self.server.timeout)
+
+ alp = self.get_alpn_proto_negotiated()
+ if alp == http2.HTTP2Protocol.ALPN_PROTO_H2:
+ self.protocol = http2.HTTP2Protocol(self, is_server=True, dump_frames=self.http2_framedump)
+ self.use_http2 = True
+
+ # if not self.protocol:
+ # # TODO: create HTTP or Websockets protocol
+ # self.protocol = None
+
+ self.settings.protocol = self.protocol
+
handler = self.handle_http_request
+
while not self.finished:
handler, l = handler()
if l:
@@ -365,6 +432,18 @@ class PathodHandler(tcp.BaseHandler):
if not handler:
return
+ def addlog(self, log):
+ # FIXME: The bytes in the log should not be escaped. We do this at the
+ # moment because JSON encoding can't handle binary data, and I don't
+ # want to base64 everything.
+ if self.server.logreq:
+ bytes = self.rfile.get_log().encode("string_escape")
+ log["request_bytes"] = bytes
+ if self.server.logresp:
+ bytes = self.wfile.get_log().encode("string_escape")
+ log["response_bytes"] = bytes
+ self.server.add_log(log)
+
class Pathod(tcp.TCPServer):
LOGBUF = 500
@@ -387,6 +466,7 @@ class Pathod(tcp.TCPServer):
logresp=False,
explain=False,
hexdump=False,
+ http2_framedump=False,
webdebug=False,
logfp=sys.stdout,
):
@@ -414,6 +494,7 @@ class Pathod(tcp.TCPServer):
self.noapi, self.nohang = noapi, nohang
self.timeout, self.logreq = timeout, logreq
self.logresp, self.hexdump = logresp, hexdump
+ self.http2_framedump = http2_framedump
self.explain = explain
self.logfp = logfp
@@ -451,7 +532,8 @@ class Pathod(tcp.TCPServer):
client_address,
self,
self.logfp,
- self.settings
+ self.settings,
+ self.http2_framedump,
)
try:
h.handle()
@@ -508,7 +590,6 @@ def main(args): # pragma: nocover
sslversion = utils.SSLVERSIONS[args.sslversion],
certs = args.ssl_certs,
sans = args.sans,
- alpn_select = args.alpn_select,
)
root = logging.getLogger()
@@ -548,6 +629,7 @@ def main(args): # pragma: nocover
logreq = args.logreq,
logresp = args.logresp,
hexdump = args.hexdump,
+ http2_framedump = args.http2_framedump,
explain = args.explain,
webdebug = args.webdebug
)
diff --git a/libpathod/pathod_cmdline.py b/libpathod/pathod_cmdline.py
index f1bb6982..4343401f 100644
--- a/libpathod/pathod_cmdline.py
+++ b/libpathod/pathod_cmdline.py
@@ -139,10 +139,11 @@ def args_pathod(argv, stdout=sys.stdout, stderr=sys.stderr):
"""
)
group.add_argument(
- "--sslversion", dest="sslversion", type=int, default=4,
- choices=[1, 2, 3, 4],
- help=""""Use a specified protocol - TLSv1, SSLv2, SSLv3, SSLv23. Default
- to SSLv23."""
+ "--sslversion", dest="sslversion", type=str, default='SSLv23',
+ choices=utils.SSLVERSIONS.keys(),
+ help=""""
+ Use a specified protocol - TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23.
+ Default to SSLv23."""
)
group = parser.add_argument_group(
@@ -172,6 +173,12 @@ def args_pathod(argv, stdout=sys.stdout, stderr=sys.stderr):
"-x", dest="hexdump", action="store_true", default=False,
help="Log request/response in hexdump format"
)
+ group.add_argument(
+ "--http2-framedump", dest="http2_framedump", action="store_true", default=False,
+ help="Output all received & sent HTTP/2 frames"
+ )
+
+
args = parser.parse_args(argv[1:])
certs = []
diff --git a/libpathod/utils.py b/libpathod/utils.py
index 9bd2812e..481c5137 100644
--- a/libpathod/utils.py
+++ b/libpathod/utils.py
@@ -3,10 +3,12 @@ import sys
from netlib import tcp
SSLVERSIONS = {
- 1: tcp.TLSv1_METHOD,
- 2: tcp.SSLv2_METHOD,
- 3: tcp.SSLv3_METHOD,
- 4: tcp.SSLv23_METHOD,
+ 'TLSv1.2': tcp.TLSv1_2_METHOD,
+ 'TLSv1.1': tcp.TLSv1_1_METHOD,
+ 'TLSv1': tcp.TLSv1_METHOD,
+ 'SSLv3': tcp.SSLv3_METHOD,
+ 'SSLv2': tcp.SSLv2_METHOD,
+ 'SSLv23': tcp.SSLv23_METHOD,
}
SIZE_UNITS = dict(
diff --git a/test/test_language_http2.py b/test/test_language_http2.py
index de3e5cf9..3c751fd1 100644
--- a/test/test_language_http2.py
+++ b/test/test_language_http2.py
@@ -1,5 +1,6 @@
import cStringIO
+from netlib import tcp
from libpathod import language
from libpathod.language import http2, base
import netlib
@@ -64,7 +65,7 @@ class TestRequest:
s,
language.Settings(
request_host = "foo.com",
- protocol = netlib.http2.HTTP2Protocol(None)
+ protocol = netlib.http2.HTTP2Protocol(tcp.TCPClient(('localhost', 1234)))
)
)
diff --git a/test/test_pathoc.py b/test/test_pathoc.py
index e1e1fe97..d39f9275 100644
--- a/test/test_pathoc.py
+++ b/test/test_pathoc.py
@@ -230,9 +230,6 @@ class TestDaemon(_TestDaemon):
class TestDaemonHTTP2(_TestDaemon):
ssl = True
- ssloptions = pathod.SSLOptions(
- alpn_select = http2.HTTP2Protocol.ALPN_PROTO_H2,
- )
def test_http2(self):
c = pathoc.Pathoc(
@@ -270,5 +267,5 @@ class TestDaemonHTTP2(_TestDaemon):
use_http2 = True,
)
c.connect()
- resp = c.request("get:/api/info")
- assert tuple(json.loads(resp.content)["version"]) == version.IVERSION
+ resp = c.request("get:/p/200")
+ assert resp.status_code == "200"