Compare commits
3 Commits
07023f2837
...
7ecfedbec7
Author | SHA1 | Date | |
---|---|---|---|
7ecfedbec7 | |||
48c4f207a8 | |||
1f0ade0f09 |
@@ -10,7 +10,7 @@ def main():
|
|||||||
parser = argparse.ArgumentParser(description='HTTP Client')
|
parser = argparse.ArgumentParser(description='HTTP Client')
|
||||||
parser.add_argument("--verbose", "-v", action='count', default=0, help="Increase verbosity level of logging")
|
parser.add_argument("--verbose", "-v", action='count', default=0, help="Increase verbosity level of logging")
|
||||||
parser.add_argument("--command", "-c", help="HEAD, GET, PUT or POST", default="GET")
|
parser.add_argument("--command", "-c", help="HEAD, GET, PUT or POST", default="GET")
|
||||||
parser.add_argument("--port", "-p", help="The port used to connect with the server", default=80)
|
parser.add_argument("--port", "-p", help="The port used to connect with the server", default=80, type=int)
|
||||||
parser.add_argument("URI", help="The URI to connect to")
|
parser.add_argument("URI", help="The URI to connect to")
|
||||||
|
|
||||||
arguments = parser.parse_args()
|
arguments = parser.parse_args()
|
||||||
|
@@ -7,7 +7,7 @@ from client.httpclient import HTTPClient
|
|||||||
from httplib import parser
|
from httplib import parser
|
||||||
from httplib.exceptions import InvalidResponse, InvalidStatusLine, UnsupportedEncoding
|
from httplib.exceptions import InvalidResponse, InvalidStatusLine, UnsupportedEncoding
|
||||||
from httplib.httpsocket import FORMAT
|
from httplib.httpsocket import FORMAT
|
||||||
from httplib.message import ClientMessage as Message
|
from httplib.message import ResponseMessage as Message
|
||||||
from httplib.retriever import PreambleRetriever
|
from httplib.retriever import PreambleRetriever
|
||||||
|
|
||||||
sockets: Dict[str, HTTPClient] = {}
|
sockets: Dict[str, HTTPClient] = {}
|
||||||
@@ -38,18 +38,38 @@ class AbstractCommand(ABC):
|
|||||||
"""
|
"""
|
||||||
A class representing the command for sending an HTTP request.
|
A class representing the command for sending an HTTP request.
|
||||||
"""
|
"""
|
||||||
uri: str
|
_uri: str
|
||||||
host: str
|
_host: str
|
||||||
path: str
|
_path: str
|
||||||
port: int
|
_port: int
|
||||||
sub_request: bool
|
sub_request: bool
|
||||||
|
|
||||||
def __init__(self, uri: str, port):
|
def __init__(self, uri: str, port):
|
||||||
self.uri = uri
|
self.uri = uri
|
||||||
self.host, _, self.path = parser.parse_uri(uri)
|
self._port = int(port)
|
||||||
self.port = int(port)
|
|
||||||
self.sub_request = False
|
self.sub_request = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def uri(self):
|
||||||
|
return self._uri
|
||||||
|
|
||||||
|
@uri.setter
|
||||||
|
def uri(self, value):
|
||||||
|
self._uri = value
|
||||||
|
self._host, self._port, self._path = parser.parse_uri(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def host(self):
|
||||||
|
return self._host
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
return self._path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port(self):
|
||||||
|
return self._port
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def method(self):
|
def method(self):
|
||||||
@@ -61,6 +81,7 @@ class AbstractCommand(ABC):
|
|||||||
|
|
||||||
@param sub_request: If this execution is in function of a prior command.
|
@param sub_request: If this execution is in function of a prior command.
|
||||||
"""
|
"""
|
||||||
|
self.uri = ""
|
||||||
self.sub_request = sub_request
|
self.sub_request = sub_request
|
||||||
(host, path) = self.parse_uri()
|
(host, path) = self.parse_uri()
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ from client.httpclient import HTTPClient
|
|||||||
from httplib import parser
|
from httplib import parser
|
||||||
from httplib.exceptions import InvalidResponse
|
from httplib.exceptions import InvalidResponse
|
||||||
from httplib.httpsocket import FORMAT
|
from httplib.httpsocket import FORMAT
|
||||||
from httplib.message import ClientMessage as Message
|
from httplib.message import ResponseMessage as Message
|
||||||
from httplib.retriever import Retriever
|
from httplib.retriever import Retriever
|
||||||
|
|
||||||
BASE_REGEX = re.compile(r"<\s*base[^>]*\shref\s*=\s*['\"]([^\"']+)['\"][^>]*>", re.M | re.I)
|
BASE_REGEX = re.compile(r"<\s*base[^>]*\shref\s*=\s*['\"]([^\"']+)['\"][^>]*>", re.M | re.I)
|
||||||
@@ -78,7 +78,7 @@ class BasicResponseHandler(ResponseHandler):
|
|||||||
if self.msg.status == 101:
|
if self.msg.status == 101:
|
||||||
# Switching protocols is not supported
|
# Switching protocols is not supported
|
||||||
print("".join(self.msg.raw), end="")
|
print("".join(self.msg.raw), end="")
|
||||||
return
|
return None
|
||||||
|
|
||||||
if 200 <= self.msg.status < 300:
|
if 200 <= self.msg.status < 300:
|
||||||
return self.retriever
|
return self.retriever
|
||||||
@@ -87,6 +87,7 @@ class BasicResponseHandler(ResponseHandler):
|
|||||||
# Redirect
|
# Redirect
|
||||||
self._skip_body()
|
self._skip_body()
|
||||||
return self._handle_redirect()
|
return self._handle_redirect()
|
||||||
|
|
||||||
if 400 <= self.msg.status < 600:
|
if 400 <= self.msg.status < 600:
|
||||||
self._skip_body()
|
self._skip_body()
|
||||||
# Dump headers and exit with error
|
# Dump headers and exit with error
|
||||||
@@ -114,7 +115,6 @@ class BasicResponseHandler(ResponseHandler):
|
|||||||
raise InvalidResponse("Only http is supported")
|
raise InvalidResponse("Only http is supported")
|
||||||
|
|
||||||
self.cmd.uri = location
|
self.cmd.uri = location
|
||||||
self.cmd.host, self.cmd.port, self.cmd.path = parser.parse_uri(location)
|
|
||||||
|
|
||||||
if self.msg.status == 301:
|
if self.msg.status == 301:
|
||||||
logging.info("Status 301. Closing socket [%s]", self.cmd.host)
|
logging.info("Status 301. Closing socket [%s]", self.cmd.host)
|
||||||
@@ -177,8 +177,8 @@ class DownloadHandler(ResponseHandler, ABC):
|
|||||||
|
|
||||||
class RawDownloadHandler(DownloadHandler):
|
class RawDownloadHandler(DownloadHandler):
|
||||||
|
|
||||||
def __init__(self, retriever: Retriever, client: HTTPClient, msg: Message, cmd: AbstractCommand, dir=None):
|
def __init__(self, retriever: Retriever, client: HTTPClient, msg: Message, cmd: AbstractCommand, directory=None):
|
||||||
super().__init__(retriever, client, msg, cmd, dir)
|
super().__init__(retriever, client, msg, cmd, directory)
|
||||||
|
|
||||||
def handle(self) -> str:
|
def handle(self) -> str:
|
||||||
logging.debug("Retrieving payload")
|
logging.debug("Retrieving payload")
|
||||||
|
@@ -16,7 +16,7 @@ class Message(ABC):
|
|||||||
self.body = body
|
self.body = body
|
||||||
|
|
||||||
|
|
||||||
class ClientMessage(Message):
|
class ResponseMessage(Message):
|
||||||
status: int
|
status: int
|
||||||
msg: str
|
msg: str
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ class ClientMessage(Message):
|
|||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|
||||||
|
|
||||||
class ServerMessage(Message):
|
class RequestMessage(Message):
|
||||||
method: str
|
method: str
|
||||||
target: SplitResult
|
target: SplitResult
|
||||||
|
|
||||||
|
@@ -78,7 +78,7 @@ def parse_request_line(line: str):
|
|||||||
raise BadRequest(f"Invalid HTTP-version: {version}")
|
raise BadRequest(f"Invalid HTTP-version: {version}")
|
||||||
|
|
||||||
if len(target) == "":
|
if len(target) == "":
|
||||||
raise BadRequest()
|
raise BadRequest("request-target not specified")
|
||||||
parsed_target = urlsplit(target)
|
parsed_target = urlsplit(target)
|
||||||
|
|
||||||
return method, parsed_target, version.split("/")[1]
|
return method, parsed_target, version.split("/")[1]
|
||||||
@@ -174,7 +174,7 @@ def get_uri(url: str):
|
|||||||
|
|
||||||
def urljoin(base, url):
|
def urljoin(base, url):
|
||||||
"""
|
"""
|
||||||
Join a base url and a URL to form a absolute url.
|
Join a base url and a URL to form an absolute url.
|
||||||
"""
|
"""
|
||||||
return urllib.parse.urljoin(base, url)
|
return urllib.parse.urljoin(base, url)
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ from wsgiref.handlers import format_date_time
|
|||||||
from httplib import parser
|
from httplib import parser
|
||||||
from httplib.exceptions import NotFound, Forbidden, NotModified
|
from httplib.exceptions import NotFound, Forbidden, NotModified
|
||||||
from httplib.httpsocket import FORMAT
|
from httplib.httpsocket import FORMAT
|
||||||
from httplib.message import ServerMessage as Message
|
from httplib.message import RequestMessage as Message
|
||||||
|
|
||||||
CONTENT_ROOT = os.path.join(os.path.dirname(sys.argv[0]), "public")
|
CONTENT_ROOT = os.path.join(os.path.dirname(sys.argv[0]), "public")
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ from httplib import parser
|
|||||||
from httplib.exceptions import MethodNotAllowed, BadRequest, UnsupportedEncoding, NotImplemented, NotFound, \
|
from httplib.exceptions import MethodNotAllowed, BadRequest, UnsupportedEncoding, NotImplemented, NotFound, \
|
||||||
HTTPVersionNotSupported
|
HTTPVersionNotSupported
|
||||||
from httplib.httpsocket import HTTPSocket, FORMAT
|
from httplib.httpsocket import HTTPSocket, FORMAT
|
||||||
from httplib.message import ServerMessage as Message
|
from httplib.message import RequestMessage as Message
|
||||||
from httplib.retriever import Retriever, PreambleRetriever
|
from httplib.retriever import Retriever, PreambleRetriever
|
||||||
from server import command
|
from server import command
|
||||||
from server.serversocket import ServerSocket
|
from server.serversocket import ServerSocket
|
||||||
|
Reference in New Issue
Block a user