re-add http1 replay

This commit is contained in:
Maximilian Hils 2015-08-27 15:48:41 +02:00
parent 0f97899fbd
commit ecfde4247f

View File

@ -1,14 +1,18 @@
from __future__ import (absolute_import, print_function, division)
from .. import version
import threading
from ..exceptions import InvalidCredentials, HttpException, ProtocolException
from .layer import Layer
from libmproxy import utils
from libmproxy.controller import Channel
from libmproxy.protocol2.layer import Kill
from libmproxy.protocol import KILL
from libmproxy.protocol import KILL, Error
from libmproxy.protocol.http import HTTPFlow
from libmproxy.protocol.http_wrappers import HTTPResponse, HTTPRequest
from libmproxy.proxy import Log
from libmproxy.proxy.connection import ServerConnection
from netlib import tcp
from netlib.http import status_codes, http1, http2, HttpErrorConnClosed, HttpError
from netlib.http.semantics import CONTENT_MISSING
@ -509,3 +513,87 @@ class HttpLayer(Layer):
odict.ODictCaseless([[k,v] for k, v in self.config.authenticator.auth_challenge_headers().items()])
))
raise InvalidCredentials("Proxy Authentication Required")
class RequestReplayThread(threading.Thread):
name = "RequestReplayThread"
def __init__(self, config, flow, masterq, should_exit):
"""
masterqueue can be a queue or None, if no scripthooks should be
processed.
"""
self.config, self.flow = config, flow
if masterq:
self.channel = Channel(masterq, should_exit)
else:
self.channel = None
super(RequestReplayThread, self).__init__()
def run(self):
r = self.flow.request
form_out_backup = r.form_out
try:
self.flow.response = None
# If we have a channel, run script hooks.
if self.channel:
request_reply = self.channel.ask("request", self.flow)
if request_reply is None or request_reply == KILL:
raise Kill()
elif isinstance(request_reply, HTTPResponse):
self.flow.response = request_reply
if not self.flow.response:
# In all modes, we directly connect to the server displayed
if self.config.mode == "upstream":
# FIXME
server_address = self.config.mode.get_upstream_server(
self.flow.client_conn
)[2:]
server = ServerConnection(server_address)
server.connect()
protocol = HTTP1Protocol(server)
if r.scheme == "https":
connect_request = make_connect_request((r.host, r.port))
server.send(protocol.assemble(connect_request))
server.establish_ssl(
self.config.clientcerts,
sni=self.flow.server_conn.sni
)
r.form_out = "relative"
else:
r.form_out = "absolute"
else:
server_address = (r.host, r.port)
server = ServerConnection(server_address)
server.connect()
protocol = HTTP1Protocol(server)
if r.scheme == "https":
server.establish_ssl(
self.config.clientcerts,
sni=self.flow.server_conn.sni
)
r.form_out = "relative"
server.send(protocol.assemble(r))
self.flow.server_conn = server
self.flow.response = HTTPResponse.from_protocol(
protocol,
r.method,
body_size_limit=self.config.body_size_limit,
)
if self.channel:
response_reply = self.channel.ask("response", self.flow)
if response_reply is None or response_reply == KILL:
raise Kill()
except (HttpError, tcp.NetLibError) as v:
self.flow.error = Error(repr(v))
if self.channel:
self.channel.ask("error", self.flow)
except Kill:
# KillSignal should only be raised if there's a channel in the
# first place.
self.channel.tell("log", Log("Connection killed", "info"))
finally:
r.form_out = form_out_backup