def connect(self): self.anomaly_tracker = AnomalyTracker(now()) if self.current_printer().is_authenticated: self.accept() async_to_sync(self.channel_layer.group_add)( channels.octo_group_name(self.current_printer().id), self.channel_name) self.last_touch = time.time() Room.objects.add( channels.octo_group_name(self.current_printer().id), self.channel_name) # Send remote status to OctoPrint as soon as it connects self.printer_message({ 'remote_status': { 'viewing': channels.num_ws_connections( channels.web_group_name(self.current_printer().id)) > 0, 'should_watch': self.current_printer().should_watch(), } }) else: self.close()
def connect(self): self.anomaly_tracker = AnomalyTracker(now()) self.printer = None self.printer = self.get_printer() self.accept() async_to_sync(self.channel_layer.group_add)(channels.octo_group_name( self.printer.id), self.channel_name) self.last_touch = time.time() Room.objects.add(channels.octo_group_name(self.printer.id), self.channel_name) # Send remote status to OctoPrint as soon as it connects self.printer_message({ 'remote_status': { 'viewing': channels.num_ws_connections( channels.web_group_name(self.printer.id)) > 0, 'should_watch': self.printer.should_watch(), } }) touch_user_last_active(self.printer.user)
def is_octoprint_connected(self): return channels.num_ws_connections( channels.octo_group_name(self.printer.id) ) > 0
def _octoprint_http_tunnel(request, octoprinttunnel): user = octoprinttunnel.printer.user if user.tunnel_usage_over_cap(): return HttpResponse(OVER_FREE_LIMIT_HTML, status=OVER_FREE_LIMIT_STATUS_CODE) # if plugin is disconnected, halt if channels.num_ws_connections( channels.octo_group_name(octoprinttunnel.printer.id)) < 1: return HttpResponse(NOT_CONNECTED_HTML, status=NOT_CONNECTED_STATUS_CODE) version = (cache.printer_settings_get(octoprinttunnel.printer.pk) or {}).get('tsd_plugin_version', '') is_v1 = version and not is_plugin_version_supported(version) if is_v1: return HttpResponse(NOT_CONNECTED_HTML, status=NOT_CONNECTED_STATUS_CODE) method = request.method.lower() path = request.get_full_path() IGNORE_HEADERS = [ 'HTTP_HOST', 'HTTP_ORIGIN', 'HTTP_REFERER', # better not to tell 'HTTP_AUTHORIZATION', # handled explicitely 'HTTP_COOKIE', # handled explicitely 'HTTP_ACCEPT_ENCODING', # should be handled by TSD server ] req_headers = { k[5:].replace('_', ' ').title().replace(' ', '-'): v for (k, v) in request.META.items() if (k.startswith('HTTP') and k not in IGNORE_HEADERS and not k.startswith('HTTP_X_FORWARDED') # meant for TSD server ) } if 'CONTENT_TYPE' in request.META: req_headers['Content-Type'] = request.META['CONTENT_TYPE'] if 'HTTP_COOKIE' in request.META: # let's not forward cookies of TSD server stripped_cookies = '; '.join([ cookie.strip() for cookie in request.META['HTTP_COOKIE'].split(';') if DJANGO_COOKIE_RE.match(cookie.strip()) is None ]) if stripped_cookies: req_headers['Cookie'] = stripped_cookies if hasattr(request, 'auth_header'): # let's not forward basic auth header of external tunnel stripped_auth_heaader = ', '.join([ h for h in request.META['HTTP_AUTHORIZATION'].split(',') if h != request.auth_header ]) if stripped_auth_heaader: req_headers['Authorization'] = stripped_auth_heaader ref = f'v2.{octoprinttunnel.id}.{method}.{time.time()}.{path}' channels.send_msg_to_printer( octoprinttunnel.printer.id, { 'http.tunnelv2': { 'ref': ref, 'method': method, 'headers': req_headers, 'path': path, 'data': request.body }, 'as_binary': True, }) data = cache.octoprinttunnel_http_response_get(ref) if data is None: # request timed out return HttpResponse(NOT_CONNECTED_HTML, status=TIMED_OUT_STATUS_CODE) content_type = data['response']['headers'].get('Content-Type') or None status_code = data['response']['status'] resp = HttpResponse( status=status_code, content_type=content_type, ) to_ignore = ( 'content-length', # set by django 'content-encoding', # if its set, it is probably incorrect/unapplicable 'x-frame-options', # response must load in TSD's iframe ) for k, v in data['response']['headers'].items(): if k.lower() in to_ignore: continue if k.lower() == 'etag': # pre 1.6.? octoprint has invalid etag format for some responses v = fix_etag(v) resp[k] = v # plugin connects over http to octoprint, # but TSD needs cookies working over https. # without this, cookies set in response might not be used # in some browsers (FF gives wwarning) for cookie in (data['response'].get('cookies', ()) or ()): if (request.is_secure() and 'secure' not in cookie.lower()): cookie += '; Secure' if 'Expires=' not in cookie and 'Max-Age=' not in cookie: cookie += '; Max-Age=7776000' # 3 months resp['Set-Cookie'] = cookie if data['response'].get('compressed', False): content = zlib.decompress(data['response']['content']) else: content = data['response']['content'] cache.octoprinttunnel_update_stats(user.id, len(content)) resp.write(content) return resp