114 lines
3.5 KiB
Python
Raw Normal View History

2015-07-17 23:44:26 +00:00
#!/usr/bin/env python3
import os
2015-07-18 03:49:24 +00:00
import json
import pprint
2015-07-18 03:17:27 +00:00
# Can't use trollius because then onConnect never gets called
2015-07-18 03:33:57 +00:00
# https://github.com/tavendo/AutobahnPython/issues/426
2015-07-17 23:44:26 +00:00
import asyncio
from autobahn.asyncio.websocket import WebSocketServerFactory, WebSocketServerProtocol
2015-07-18 10:57:57 +00:00
class GrabberServerProtocol(WebSocketServerProtocol):
def __init__(self):
super().__init__()
self.mode = None
2015-07-17 23:44:26 +00:00
def onConnect(self, request):
self.peer = request.peer
print("{} connected".format(self.peer))
self.factory.clients.add(self)
def onClose(self, wasClean, code, reason):
print("{} disconnected".format(self.peer))
self.factory.clients.discard(self)
def broadcastToDashboards(self, obj):
for client in self.factory.clients:
if client.mode == "dashboard":
##print("Broadcasting", pprint.pformat(obj))
client.sendMessage(json.dumps(obj).encode("utf-8"))
def onMessage(self, payload, isBinary):
##print(payload)
obj = json.loads(payload.decode('utf-8'))
type = obj["type"]
if self.mode is None and type == "hello" and obj.get("mode"):
mode = obj['mode']
if mode in ('dashboard', 'grabber'):
self.mode = mode
if mode == "grabber":
print("{} is grabbing {}".format(self.peer, obj['url']))
elif mode == "dashboard":
print("{} is dashboarding with {}".format(self.peer, obj.get('user_agent', '(no User-Agent)')))
elif self.mode == "grabber":
if type == "download":
self.broadcastToDashboards({
"type": type,
"job_data": obj["job_data"],
"url": obj["url"],
"response_code": obj["response_code"],
"wget_code": obj["response_message"]
})
elif type in ("stdout", "stderr"):
self.broadcastToDashboards({
"type": type,
"job_data": obj["job_data"],
"message": obj["message"]
})
elif type == "ignore":
self.broadcastToDashboards({
"type": type,
"job_data": obj["job_data"],
"url": obj["url"],
"pattern": obj["pattern"],
})
2015-07-17 23:44:26 +00:00
2016-02-24 16:44:13 -06:00
# Called when we get an HTTP request instead of a WebSocket request
def sendServerStatus(self, redirectUrl=None, redirectAfter=0):
requestPath = self.http_request_uri.split("?")[0]
if requestPath == "/":
2016-02-24 23:58:43 +00:00
self.sendPage("dashboard.html", 200, "OK", "text/html; charset=UTF-8")
2016-05-22 10:59:32 +00:00
elif requestPath == "/favicon.ico":
self.sendPage("favicon.ico", 200, "OK", "image/x-icon")
else:
2016-02-24 23:58:43 +00:00
self.sendPage("404.html", 404, "Not Found", "text/html; charset=UTF-8")
# Based on AutoBahn's WebSocketServerProtocol.sendHtml
def sendPage(self, fname, code, status, contentType):
with open(os.path.join(os.path.dirname(__file__), fname), "rb") as f:
responseBody = f.read()
2016-02-24 23:58:43 +00:00
response = "HTTP/1.1 {} {}\r\n".format(code, status)
response += "Content-Type: {}\r\n".format(contentType)
response += "Content-Length: {}\r\n".format(len(responseBody))
2016-02-25 00:01:27 +00:00
response += "X-Frame-Options: DENY\r\n"
2016-02-24 23:47:03 +00:00
response += "\r\n"
self.sendData(response.encode("utf-8"))
self.sendData(responseBody)
2015-07-17 23:44:26 +00:00
2015-07-18 10:57:57 +00:00
class GrabberServerFactory(WebSocketServerFactory):
protocol = GrabberServerProtocol
def __init__(self):
super().__init__()
self.clients = set()
2015-07-17 23:44:26 +00:00
def main():
loop = asyncio.get_event_loop()
2016-05-22 11:06:38 +00:00
ports = list(int(p) for p in os.environ.get('GRAB_SITE_PORT', "29000").split(','))
interface = os.environ.get('GRAB_SITE_INTERFACE', '0.0.0.0')
2015-07-17 23:44:26 +00:00
factory = GrabberServerFactory()
for port in ports:
coro = loop.create_server(factory, interface, port)
loop.run_until_complete(coro)
2016-02-25 00:32:42 +00:00
print("grab-site server listening on {}:{}".format(interface, port))
2015-07-17 23:44:26 +00:00
loop.run_forever()
if __name__ == '__main__':
main()