Get rid of Hug dependency, use python default http server

This commit is contained in:
Dima Gerasimov 2019-01-07 23:35:18 +00:00
parent fea9092497
commit dc568f4785
5 changed files with 55 additions and 34 deletions

View file

@ -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). [See a short demo](https://www.youtube.com/watch?v=Z8Bk-IazdGo).
# Requirements # Requirements
* `pip3 install --user hug` for [Hug](http://www.hug.rest/) HTTP server. No third party dependencies! Just `python 3.6`.
# Running # Running
1. Install server counterpart as systemd service (to autostart it): `server/setup --path /path/to/your/capture.org [--port <custom port>]`. 1. Install server counterpart as systemd service (to autostart it): `server/setup --path /path/to/your/capture.org [--port <custom port>]`.

View file

@ -1,7 +1,6 @@
#!/bin/bash #!/bin/bash
set -eux set -eux
# TODO add to proper ci pipeline # 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 *.py setup
mypy --check-untyped-defs server.py setup

View file

@ -1,41 +1,38 @@
#!/usr/bin/python3 #!/usr/bin/python3
import argparse import argparse
from http.server import BaseHTTPRequestHandler, HTTPServer
import json import json
import re
import os import os
from pathlib import Path from pathlib import Path
import re
import hug # type: ignore from typing import List
import hug.types as T # type: ignore
from org_tools import append_org_entry from org_tools import append_org_entry
CAPTURE_PATH_VAR = 'GRASP_CAPTURE_PATH' CAPTURE_PATH_VAR = 'GRASP_CAPTURE_PATH'
def empty(s) -> bool:
return s is None or len(s.strip()) == 0
def log(*things): def log(*things):
# TODO proper logging # TODO proper logging
print(*things) print(*things)
# TODO allow to pass tags??
@hug.local()
@hug.post('/capture')
def capture( def capture(
url: T.text, url,
title: T.Nullable(T.text), title,
selection: T.Nullable(T.text), selection,
comment: T.Nullable(T.text), comment,
tag_str: T.Nullable(T.text), tag_str,
): ):
def empty(s) -> bool:
return s is None or len(s.strip()) == 0
log("capturing", url, title, selection, comment) log("capturing", url, title, selection, comment)
capture_path = Path(os.environ[CAPTURE_PATH_VAR]).expanduser() capture_path = Path(os.environ[CAPTURE_PATH_VAR]).expanduser()
heading = url heading = url
parts = [] parts = []
tags = [] tags: List[str] = []
if not empty(tag_str): if not empty(tag_str):
tags = re.split('[\s,]', tag_str) tags = re.split('[\s,]', tag_str)
tags = [t for t in tags if not empty(t)] # just in case 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') 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): def run(port: str, capture_path: str):
env = os.environ.copy()
# not sure if there is a simpler way to communicate with the server... # not sure if there is a simpler way to communicate with the server...
env[CAPTURE_PATH_VAR] = capture_path os.environ[CAPTURE_PATH_VAR] = capture_path
os.execvpe( httpd = HTTPServer(('', int(port)), GraspRequestHandler)
'hug', log(f"Starting httpd on port {port}")
[ httpd.serve_forever()
'grasp-server',
'-p', port,
'-f', __file__,
],
env,
)
def setup_parser(p): def setup_parser(p):
p.add_argument('--port', type=str, default='12212', help='Port for communicating with extension') p.add_argument('--port', type=str, default='12212', help='Port for communicating with extension')

View file

@ -2,7 +2,7 @@
import argparse import argparse
from pathlib import Path from pathlib import Path
from subprocess import check_call from subprocess import check_call, run
from grasp_server import setup_parser from grasp_server import setup_parser
@ -20,8 +20,8 @@ Restart=always
""" """
def systemd(*args): def systemd(*args, method=check_call):
check_call([ method([
'systemctl', '--user', *args, 'systemctl', '--user', *args,
]) ])
@ -40,6 +40,7 @@ def setup(args):
)) ))
try: try:
systemd('stop' , unit_name, method=run) # ignore errors here if it wasn't running in the first place
systemd('daemon-reload') systemd('daemon-reload')
systemd('enable', unit_name) systemd('enable', unit_name)
systemd('start' , unit_name) systemd('start' , unit_name)

View file

@ -27,6 +27,7 @@ function makeCaptureRequest(
} }
console.log('[background] status:', request.status); console.log('[background] status:', request.status);
if (request.status >= 200 && request.status < 400) { // success if (request.status >= 200 && request.status < 400) { // success
// TODO handle json parsing defensively here
var response = JSON.parse(request.responseText); var response = JSON.parse(request.responseText);
console.log(`[background] success: ${response}`); console.log(`[background] success: ${response}`);
showNotification(`OK: ${response}`); showNotification(`OK: ${response}`);