Skip to content

Commit

Permalink
Remove serve_once and deamon-specific options from utils.py (#102)
Browse files Browse the repository at this point in the history
* removed unused utils functionality

* removed testcase

* fixed Makefile

Co-authored-by: ldruschk <14059613+ldruschk@users.noreply.github.com>
  • Loading branch information
domenukk and ldruschk committed Apr 25, 2021
1 parent 31c240e commit d4bf7ae
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 156 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.PHONY: all lint diff format test

all: format test

lint:
python3 -m isort -c src/ tests/ example/
python3 -m black --check src/ tests/ example/
Expand All @@ -13,6 +17,6 @@ format:
python3 -m black src/ tests/ example/

test:
pip install .
pip3 install .
coverage run -m pytest
coverage report -m
24 changes: 0 additions & 24 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,30 +323,6 @@ Will raise an exception if failed.
:param timeout: a timeout
:return read: the bytes read

## start_daemon
```python
start_daemon(target)
```

starts a thread as daemon
:param target: the function
:return: the started thread

## serve_once
```python
serve_once(html, start_port=5000, autoincrement_port=True, content_type='text/html', headers=None)
```

Render Text in the users browser
Opens a web server that serves a HTML string once and shuts down after the first request.
The port will be open when this function returns. (though serving the request may take a few mils)
:param html: The html code to deliver on the initial request
:param start_port: The port it should try to listen on first.
:param autoincrement_port: If the port should be increased if the server cannot listen on the provided start_port
:param content_type: The content type this server should report (change it if you want json, for example)
:param headers: Additional headers as {header_key: value} dict.
:return: The port the server started listening on

## SimpleSocket
```python
SimpleSocket(self, host=None, port=0, timeout=<object object at 0x000000000303A670>)
Expand Down
2 changes: 0 additions & 2 deletions src/enochecker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
ensure_bytes,
ensure_unicode,
ensure_valid_filename,
serve_once,
sha256ify,
snake_caseify,
start_daemon,
)

name = "enochecker"
105 changes: 1 addition & 104 deletions src/enochecker/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,10 @@
import re
import socket
import telnetlib
import threading
import time
from http.server import BaseHTTPRequestHandler, HTTPServer
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
List,
Match,
Optional,
Pattern,
Sequence,
Tuple,
Union,
)
from typing import Any, Callable, List, Match, Optional, Pattern, Sequence, Tuple, Union

from .results import BrokenServiceException

if TYPE_CHECKING: # pragma: no cover
import requests

PORT_MAX = 65535

logging.basicConfig(level=logging.DEBUG)
Expand Down Expand Up @@ -181,91 +163,6 @@ def debase64ify(
return base64.b64decode(s).decode("utf-8")


def start_daemon(target: Callable[..., Any]) -> threading.Thread:
"""
Start a thread as daemon.
:param target: the function
:return: the started thread
"""
t = threading.Thread(target=target)
t.daemon = True
t.start()
return t


def serve_once(
html: Union[str, bytes, "requests.Response"],
start_port: int = 5000,
autoincrement_port: bool = True,
content_type: str = "text/html",
headers: Optional[Dict[str, str]] = None,
logger: Optional[logging.Logger] = None,
) -> int:
"""
Render Text in the users browser.
Opens a web server that serves a HTML string once and shuts down after the first request.
The port will be open when this function returns. (though serving the request may take a few mils)
:param html: The html code to deliver on the initial request
:param start_port: The port it should try to listen on first.
:param autoincrement_port: If the port should be increased if the server cannot listen on the provided start_port
:param content_type: The content type this server should report (change it if you want json, for example)
:param headers: Additional headers as {header_key: value} dict.
:param logger: the optional logger to redirect logs to.
:return: The port the server started listening on
"""
# see https://github.com/psf/requests/issues/2925
import requests

logger_: logging.Logger = logger or utilslogger
headers_: Dict[str, str] = headers or {}
if isinstance(html, requests.Response):
payload: bytes = html.text.encode("UTF-8")
elif isinstance(html, str):
payload = html.encode("UTF-8")
else:
payload = html

class OutputHandler(BaseHTTPRequestHandler):

# noinspection PyPep8Naming
def do_GET(self) -> None:
self.send_response(200)
self.send_header("Content-type", content_type)
for key, value in headers_.items():
self.send_header(key, value)
self.end_headers()
self.wfile.write(payload)
logger_.info("Served HTTP once. Stopping.")
start_daemon(self.server.shutdown)

for port in range(start_port, PORT_MAX):
try:
server = HTTPServer(("", port), OutputHandler)
logging.debug("Serving {} bytes on port {}".format(len(payload), port))
start_daemon(server.serve_forever)
time.sleep(0.1) # some extra time thrown in for good measure. :)
return port
except OSError as ex:
if not autoincrement_port:
logger_.info(
"Serve once was not set to automatically increment port {} but faced socket exception{}".format(
start_port, ex
),
exc_info=True,
stack_info=True,
)
break

raise OSError(
"No unused port found, start_port={}, autoincrement_port={}".format(
start_port, autoincrement_port
)
)


class SimpleSocket(telnetlib.Telnet):
"""
Telnetlib with some additions.
Expand Down
25 changes: 0 additions & 25 deletions tests/test_enochecker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import functools
import sys
import tempfile
import time
from logging import DEBUG

import pytest
Expand All @@ -17,7 +16,6 @@
assert_in,
ensure_bytes,
ensure_unicode,
serve_once,
snake_caseify,
)

Expand Down Expand Up @@ -168,29 +166,6 @@ def test_dict():
assert len(db) == 0


@temp_storage_dir
def test_checker_connections():
# TODO: Check timeouts?
text = "ECHO :)"
_ = serve_once(text, 9999)
checker = CheckerExampleImpl(
CheckerMethod.CHECKER_METHOD_PUTFLAG,
) # Conflict between logging and enochecker.logging because of wildcart import
assert (
checker.http_get("/").text == text
) # Should probably rename it to enologger to avoid further conflicts

# Give server time to shut down
time.sleep(0.2)

_ = serve_once(text, 9999)
checker = CheckerExampleImpl(CheckerMethod.CHECKER_METHOD_PUTFLAG)
t = checker.connect()
t.write(b"GET / HTTP/1.0\r\n\r\n")
assert t.readline_expect("HTTP")
t.close()


@temp_storage_dir
def test_checker():
flag = "ENOFLAG"
Expand Down

0 comments on commit d4bf7ae

Please sign in to comment.