diff options
Diffstat (limited to 'libmproxy/models/http.py')
-rw-r--r-- | libmproxy/models/http.py | 166 |
1 files changed, 43 insertions, 123 deletions
diff --git a/libmproxy/models/http.py b/libmproxy/models/http.py index e07dff69..3c024e76 100644 --- a/libmproxy/models/http.py +++ b/libmproxy/models/http.py @@ -1,36 +1,20 @@ from __future__ import (absolute_import, print_function, division) import Cookie import copy +import warnings from email.utils import parsedate_tz, formatdate, mktime_tz import time from libmproxy import utils from netlib import encoding -from netlib.http import status_codes, Headers, Request, Response, CONTENT_MISSING, decoded +from netlib.http import status_codes, Headers, Request, Response, decoded from netlib.tcp import Address -from .. import version, stateobject +from .. import version from .flow import Flow -class MessageMixin(stateobject.StateObject): - _stateobject_attributes = dict( - http_version=bytes, - headers=Headers, - timestamp_start=float, - timestamp_end=float - ) - _stateobject_long_attributes = {"body"} - - def get_state(self, short=False): - ret = super(MessageMixin, self).get_state(short) - if short: - if self.content: - ret["contentLength"] = len(self.content) - elif self.content == CONTENT_MISSING: - ret["contentLength"] = None - else: - ret["contentLength"] = 0 - return ret + +class MessageMixin(object): def get_decoded_content(self): """ @@ -43,33 +27,6 @@ class MessageMixin(stateobject.StateObject): return self.content return encoding.decode(ce, self.content) - def decode(self): - """ - Decodes body based on the current Content-Encoding header, then - removes the header. If there is no Content-Encoding header, no - action is taken. - - Returns True if decoding succeeded, False otherwise. - """ - ce = self.headers.get("content-encoding") - if not self.content or ce not in encoding.ENCODINGS: - return False - data = encoding.decode(ce, self.content) - if data is None: - return False - self.content = data - self.headers.pop("content-encoding", None) - return True - - def encode(self, e): - """ - Encodes body with the encoding e, where e is "gzip", "deflate" - or "identity". - """ - # FIXME: Error if there's an existing encoding header? - self.content = encoding.encode(e, self.content) - self.headers["content-encoding"] = e - def copy(self): c = copy.copy(self) if hasattr(self, "data"): # FIXME remove condition @@ -86,10 +43,12 @@ class MessageMixin(stateobject.StateObject): Returns the number of replacements made. """ - with decoded(self): - self.content, count = utils.safe_subn( - pattern, repl, self.content, *args, **kwargs - ) + count = 0 + if self.content: + with decoded(self): + self.content, count = utils.safe_subn( + pattern, repl, self.content, *args, **kwargs + ) fields = [] for name, value in self.headers.fields: name, c = utils.safe_subn(pattern, repl, name, *args, **kwargs) @@ -161,6 +120,9 @@ class HTTPRequest(MessageMixin, Request): timestamp_start=None, timestamp_end=None, form_out=None, + is_replay=False, + stickycookie=False, + stickyauth=False, ): Request.__init__( self, @@ -179,51 +141,26 @@ class HTTPRequest(MessageMixin, Request): self.form_out = form_out or first_line_format # FIXME remove # Have this request's cookies been modified by sticky cookies or auth? - self.stickycookie = False - self.stickyauth = False + self.stickycookie = stickycookie + self.stickyauth = stickyauth # Is this request replayed? - self.is_replay = False - - _stateobject_attributes = MessageMixin._stateobject_attributes.copy() - _stateobject_attributes.update( - content=bytes, - first_line_format=str, - method=bytes, - scheme=bytes, - host=bytes, - port=int, - path=bytes, - form_out=str, - is_replay=bool - ) - - @classmethod - def from_state(cls, state): - f = cls( - None, - b"", - None, - None, - None, - None, - None, - None, - None, - None, - None) - f.load_state(state) - return f + self.is_replay = is_replay + + def get_state(self): + state = super(HTTPRequest, self).get_state() + state.update( + stickycookie = self.stickycookie, + stickyauth = self.stickyauth, + is_replay = self.is_replay, + ) + return state - @classmethod - def from_protocol( - self, - protocol, - *args, - **kwargs - ): - req = protocol.read_request(*args, **kwargs) - return self.wrap(req) + def set_state(self, state): + self.stickycookie = state.pop("stickycookie") + self.stickyauth = state.pop("stickyauth") + self.is_replay = state.pop("is_replay") + super(HTTPRequest, self).set_state(state) @classmethod def wrap(self, request): @@ -241,10 +178,17 @@ class HTTPRequest(MessageMixin, Request): timestamp_end=request.timestamp_end, form_out=(request.form_out if hasattr(request, 'form_out') else None), ) - if hasattr(request, 'stream_id'): - req.stream_id = request.stream_id return req + @property + def form_out(self): + warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning) + return self.first_line_format + + @form_out.setter + def form_out(self, value): + warnings.warn(".form_out is deprecated, use .first_line_format instead.", DeprecationWarning) + def __hash__(self): return id(self) @@ -297,6 +241,7 @@ class HTTPResponse(MessageMixin, Response): content, timestamp_start=None, timestamp_end=None, + is_replay = False ): Response.__init__( self, @@ -310,32 +255,9 @@ class HTTPResponse(MessageMixin, Response): ) # Is this request replayed? - self.is_replay = False + self.is_replay = is_replay self.stream = False - _stateobject_attributes = MessageMixin._stateobject_attributes.copy() - _stateobject_attributes.update( - body=bytes, - status_code=int, - msg=bytes - ) - - @classmethod - def from_state(cls, state): - f = cls(None, None, None, None, None) - f.load_state(state) - return f - - @classmethod - def from_protocol( - self, - protocol, - *args, - **kwargs - ): - resp = protocol.read_response(*args, **kwargs) - return self.wrap(resp) - @classmethod def wrap(self, response): resp = HTTPResponse( @@ -347,8 +269,6 @@ class HTTPResponse(MessageMixin, Response): timestamp_start=response.timestamp_start, timestamp_end=response.timestamp_end, ) - if hasattr(response, 'stream_id'): - resp.stream_id = response.stream_id return resp def _refresh_cookie(self, c, delta): @@ -448,7 +368,7 @@ class HTTPFlow(Flow): @classmethod def from_state(cls, state): f = cls(None, None) - f.load_state(state) + f.set_state(state) return f def __repr__(self): |