From dc568f478570eb8217b271783eae75418b405795 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Mon, 7 Jan 2019 23:35:18 +0000 Subject: [PATCH] Get rid of Hug dependency, use python default http server --- README.md | 2 +- server/ci.sh | 5 ++- server/grasp_server.py | 74 +++++++++++++++++++++++++++--------------- server/setup | 7 ++-- src/js/background.js | 1 + 5 files changed, 55 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 37701c9..9edc674 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ possibly selected text, additional comments or tags and send it into your [Org M [See a short demo](https://www.youtube.com/watch?v=Z8Bk-IazdGo). # Requirements -* `pip3 install --user hug` for [Hug](http://www.hug.rest/) HTTP server. +No third party dependencies! Just `python 3.6`. # Running 1. Install server counterpart as systemd service (to autostart it): `server/setup --path /path/to/your/capture.org [--port ]`. diff --git a/server/ci.sh b/server/ci.sh index f22b3fb..f16e0b5 100755 --- a/server/ci.sh +++ b/server/ci.sh @@ -1,7 +1,6 @@ #!/bin/bash set -eux # TODO add to proper ci pipeline -pylint -E server.py setup +pylint -E *.py setup -# TODO ugh mypy complains at hug's annotations -mypy --check-untyped-defs server.py setup +mypy --check-untyped-defs *.py setup diff --git a/server/grasp_server.py b/server/grasp_server.py index 00b4601..c8808b5 100755 --- a/server/grasp_server.py +++ b/server/grasp_server.py @@ -1,41 +1,38 @@ #!/usr/bin/python3 import argparse +from http.server import BaseHTTPRequestHandler, HTTPServer import json -import re import os from pathlib import Path - -import hug # type: ignore -import hug.types as T # type: ignore +import re +from typing import List from org_tools import append_org_entry CAPTURE_PATH_VAR = 'GRASP_CAPTURE_PATH' -def empty(s) -> bool: - return s is None or len(s.strip()) == 0 - def log(*things): # TODO proper logging print(*things) -# TODO allow to pass tags?? -@hug.local() -@hug.post('/capture') + def capture( - url: T.text, - title: T.Nullable(T.text), - selection: T.Nullable(T.text), - comment: T.Nullable(T.text), - tag_str: T.Nullable(T.text), + url, + title, + selection, + comment, + tag_str, ): + def empty(s) -> bool: + return s is None or len(s.strip()) == 0 + log("capturing", url, title, selection, comment) capture_path = Path(os.environ[CAPTURE_PATH_VAR]).expanduser() heading = url parts = [] - tags = [] + tags: List[str] = [] if not empty(tag_str): tags = re.split('[\s,]', tag_str) tags = [t for t in tags if not empty(t)] # just in case @@ -81,19 +78,42 @@ def capture( return json.dumps(response).encode('utf8') + + +class GraspRequestHandler(BaseHTTPRequestHandler): + def handle_POST(self): + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + payload = json.loads(post_data.decode('utf8')) + log("incoming request:") + log(payload) + res = capture(**payload) + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + self.wfile.write(res) + + def respond_error(self, message: str): + self.send_response(500) + self.send_header('Content-Type', 'text/html') + self.end_headers() + self.wfile.write(message.encode('utf8')) + + def do_POST(self): + try: + self.handle_POST() + except Exception as e: + log("Error during processing") + log(str(e)) + self.respond_error(message=str(e)) + + def run(port: str, capture_path: str): - env = os.environ.copy() # not sure if there is a simpler way to communicate with the server... - env[CAPTURE_PATH_VAR] = capture_path - os.execvpe( - 'hug', - [ - 'grasp-server', - '-p', port, - '-f', __file__, - ], - env, - ) + os.environ[CAPTURE_PATH_VAR] = capture_path + httpd = HTTPServer(('', int(port)), GraspRequestHandler) + log(f"Starting httpd on port {port}") + httpd.serve_forever() def setup_parser(p): p.add_argument('--port', type=str, default='12212', help='Port for communicating with extension') diff --git a/server/setup b/server/setup index b31ff71..ebd853c 100755 --- a/server/setup +++ b/server/setup @@ -2,7 +2,7 @@ import argparse from pathlib import Path -from subprocess import check_call +from subprocess import check_call, run from grasp_server import setup_parser @@ -20,8 +20,8 @@ Restart=always """ -def systemd(*args): - check_call([ +def systemd(*args, method=check_call): + method([ 'systemctl', '--user', *args, ]) @@ -40,6 +40,7 @@ def setup(args): )) try: + systemd('stop' , unit_name, method=run) # ignore errors here if it wasn't running in the first place systemd('daemon-reload') systemd('enable', unit_name) systemd('start' , unit_name) diff --git a/src/js/background.js b/src/js/background.js index 7c2b0c4..e5a66fe 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -27,6 +27,7 @@ function makeCaptureRequest( } console.log('[background] status:', request.status); if (request.status >= 200 && request.status < 400) { // success + // TODO handle json parsing defensively here var response = JSON.parse(request.responseText); console.log(`[background] success: ${response}`); showNotification(`OK: ${response}`);