)]}'
{"zun/websocket/websocketproxy.py":[{"author":{"_account_id":22406,"name":"Kien Nguyen","email":"kiennt2609@gmail.com","username":"kiennt"},"change_message_id":"b0124e6887518832da13a0a845a3ddf85ded7795","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        if not exec_instance:"},{"line_number":268,"context_line":"            raise exception.InvalidWebsocketToken(token)"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"        access_url \u003d \u0027%s?token\u003d%s\u0026uuid\u003d%s\u0027 % (CONF.websocket_proxy.base_url,"},{"line_number":271,"context_line":"                                              token, uuid)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        # Verify Origin"},{"line_number":274,"context_line":"        expected_origin_hostname \u003d self.headers.get(\u0027Host\u0027)"},{"line_number":275,"context_line":"        if \u0027:\u0027 in expected_origin_hostname:"},{"line_number":276,"context_line":"            e \u003d expected_origin_hostname"},{"line_number":277,"context_line":"            if \u0027[\u0027 in e and \u0027]\u0027 in e:"},{"line_number":278,"context_line":"                expected_origin_hostname \u003d e.split(\u0027]\u0027)[0][1:]"},{"line_number":279,"context_line":"            else:"},{"line_number":280,"context_line":"                expected_origin_hostname \u003d e.split(\u0027:\u0027)[0]"},{"line_number":281,"context_line":"        expected_origin_hostnames \u003d CONF.websocket_proxy.allowed_origins"},{"line_number":282,"context_line":"        expected_origin_hostnames.append(expected_origin_hostname)"},{"line_number":283,"context_line":"        origin_url \u003d self.headers.get(\u0027Origin\u0027)"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"        # missing origin header indicates non-browser client which is OK"},{"line_number":286,"context_line":"        if origin_url is not None:"},{"line_number":287,"context_line":"            origin \u003d urlparse.urlparse(origin_url)"},{"line_number":288,"context_line":"            origin_hostname \u003d origin.hostname"},{"line_number":289,"context_line":"            origin_scheme \u003d origin.scheme"},{"line_number":290,"context_line":"            if origin_hostname \u003d\u003d \u0027\u0027 or origin_scheme \u003d\u003d \u0027\u0027:"},{"line_number":291,"context_line":"                detail \u003d _(\"Origin header not valid.\")"},{"line_number":292,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":293,"context_line":"            if origin_hostname not in expected_origin_hostnames:"},{"line_number":294,"context_line":"                detail \u003d _(\"Origin header does not match this host.\")"},{"line_number":295,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":296,"context_line":"            if not self.verify_origin_proto(access_url, origin_scheme):"},{"line_number":297,"context_line":"                detail \u003d _(\"Origin header protocol does not match this host.\")"},{"line_number":298,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        client \u003d docker.APIClient(base_url\u003dexec_instance.url)"},{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_8f0a1677","line":298,"range":{"start_line":270,"start_character":8,"end_line":298,"end_character":55},"updated":"2018-06-15 14:43:11.000000000","message":"It seems duplicated with _new_websocket_client(). How about combine these two methods?\n\ndef _new_websocket_client(self. container, token, uuid, exec_id\u003dNone):\n    if exec_id:\n        # Create ExecInstance...","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"},{"author":{"_account_id":22406,"name":"Kien Nguyen","email":"kiennt2609@gmail.com","username":"kiennt"},"change_message_id":"fbc61d21b516066a980e076a18d8c6e62065c206","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        if not exec_instance:"},{"line_number":268,"context_line":"            raise exception.InvalidWebsocketToken(token)"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"        access_url \u003d \u0027%s?token\u003d%s\u0026uuid\u003d%s\u0027 % (CONF.websocket_proxy.base_url,"},{"line_number":271,"context_line":"                                              token, uuid)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        # Verify Origin"},{"line_number":274,"context_line":"        expected_origin_hostname \u003d self.headers.get(\u0027Host\u0027)"},{"line_number":275,"context_line":"        if \u0027:\u0027 in expected_origin_hostname:"},{"line_number":276,"context_line":"            e \u003d expected_origin_hostname"},{"line_number":277,"context_line":"            if \u0027[\u0027 in e and \u0027]\u0027 in e:"},{"line_number":278,"context_line":"                expected_origin_hostname \u003d e.split(\u0027]\u0027)[0][1:]"},{"line_number":279,"context_line":"            else:"},{"line_number":280,"context_line":"                expected_origin_hostname \u003d e.split(\u0027:\u0027)[0]"},{"line_number":281,"context_line":"        expected_origin_hostnames \u003d CONF.websocket_proxy.allowed_origins"},{"line_number":282,"context_line":"        expected_origin_hostnames.append(expected_origin_hostname)"},{"line_number":283,"context_line":"        origin_url \u003d self.headers.get(\u0027Origin\u0027)"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"        # missing origin header indicates non-browser client which is OK"},{"line_number":286,"context_line":"        if origin_url is not None:"},{"line_number":287,"context_line":"            origin \u003d urlparse.urlparse(origin_url)"},{"line_number":288,"context_line":"            origin_hostname \u003d origin.hostname"},{"line_number":289,"context_line":"            origin_scheme \u003d origin.scheme"},{"line_number":290,"context_line":"            if origin_hostname \u003d\u003d \u0027\u0027 or origin_scheme \u003d\u003d \u0027\u0027:"},{"line_number":291,"context_line":"                detail \u003d _(\"Origin header not valid.\")"},{"line_number":292,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":293,"context_line":"            if origin_hostname not in expected_origin_hostnames:"},{"line_number":294,"context_line":"                detail \u003d _(\"Origin header does not match this host.\")"},{"line_number":295,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":296,"context_line":"            if not self.verify_origin_proto(access_url, origin_scheme):"},{"line_number":297,"context_line":"                detail \u003d _(\"Origin header protocol does not match this host.\")"},{"line_number":298,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        client \u003d docker.APIClient(base_url\u003dexec_instance.url)"},{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_73f75c5b","line":298,"range":{"start_line":270,"start_character":8,"end_line":298,"end_character":55},"in_reply_to":"5f7c97a3_4dd71df0","updated":"2018-06-16 09:04:42.000000000","message":"+1","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"},{"author":{"_account_id":11536,"name":"hongbin","email":"hongbin034@gmail.com","username":"hongbin"},"change_message_id":"3d3209f81dfa7858ad52305c7cc9bb9af7f0af95","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        if not exec_instance:"},{"line_number":268,"context_line":"            raise exception.InvalidWebsocketToken(token)"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"        access_url \u003d \u0027%s?token\u003d%s\u0026uuid\u003d%s\u0027 % (CONF.websocket_proxy.base_url,"},{"line_number":271,"context_line":"                                              token, uuid)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        # Verify Origin"},{"line_number":274,"context_line":"        expected_origin_hostname \u003d self.headers.get(\u0027Host\u0027)"},{"line_number":275,"context_line":"        if \u0027:\u0027 in expected_origin_hostname:"},{"line_number":276,"context_line":"            e \u003d expected_origin_hostname"},{"line_number":277,"context_line":"            if \u0027[\u0027 in e and \u0027]\u0027 in e:"},{"line_number":278,"context_line":"                expected_origin_hostname \u003d e.split(\u0027]\u0027)[0][1:]"},{"line_number":279,"context_line":"            else:"},{"line_number":280,"context_line":"                expected_origin_hostname \u003d e.split(\u0027:\u0027)[0]"},{"line_number":281,"context_line":"        expected_origin_hostnames \u003d CONF.websocket_proxy.allowed_origins"},{"line_number":282,"context_line":"        expected_origin_hostnames.append(expected_origin_hostname)"},{"line_number":283,"context_line":"        origin_url \u003d self.headers.get(\u0027Origin\u0027)"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"        # missing origin header indicates non-browser client which is OK"},{"line_number":286,"context_line":"        if origin_url is not None:"},{"line_number":287,"context_line":"            origin \u003d urlparse.urlparse(origin_url)"},{"line_number":288,"context_line":"            origin_hostname \u003d origin.hostname"},{"line_number":289,"context_line":"            origin_scheme \u003d origin.scheme"},{"line_number":290,"context_line":"            if origin_hostname \u003d\u003d \u0027\u0027 or origin_scheme \u003d\u003d \u0027\u0027:"},{"line_number":291,"context_line":"                detail \u003d _(\"Origin header not valid.\")"},{"line_number":292,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":293,"context_line":"            if origin_hostname not in expected_origin_hostnames:"},{"line_number":294,"context_line":"                detail \u003d _(\"Origin header does not match this host.\")"},{"line_number":295,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":296,"context_line":"            if not self.verify_origin_proto(access_url, origin_scheme):"},{"line_number":297,"context_line":"                detail \u003d _(\"Origin header protocol does not match this host.\")"},{"line_number":298,"context_line":"                raise exception.ValidationError(detail)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"        client \u003d docker.APIClient(base_url\u003dexec_instance.url)"},{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_4dd71df0","line":298,"range":{"start_line":270,"start_character":8,"end_line":298,"end_character":55},"in_reply_to":"5f7c97a3_8f0a1677","updated":"2018-06-16 02:22:13.000000000","message":"I looked into the diff and it seems a bit difficult to combine these two methods into one. However, I tried to extract to common code into method _verify_origin instead.","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"},{"author":{"_account_id":22406,"name":"Kien Nguyen","email":"kiennt2609@gmail.com","username":"kiennt"},"change_message_id":"b0124e6887518832da13a0a845a3ddf85ded7795","unresolved":false,"context_lines":[{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        try:"},{"line_number":304,"context_line":"            self.do_proxy(tsock)"},{"line_number":305,"context_line":"        finally:"},{"line_number":306,"context_line":"            if tsock:"},{"line_number":307,"context_line":"                tsock.shutdown(socket.SHUT_RDWR)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_4c0acc27","line":304,"range":{"start_line":304,"start_character":17,"end_line":304,"end_character":25},"updated":"2018-06-15 14:43:11.000000000","message":"do_websocket_proxy","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"},{"author":{"_account_id":22406,"name":"Kien Nguyen","email":"kiennt2609@gmail.com","username":"kiennt"},"change_message_id":"fbc61d21b516066a980e076a18d8c6e62065c206","unresolved":false,"context_lines":[{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        try:"},{"line_number":304,"context_line":"            self.do_proxy(tsock)"},{"line_number":305,"context_line":"        finally:"},{"line_number":306,"context_line":"            if tsock:"},{"line_number":307,"context_line":"                tsock.shutdown(socket.SHUT_RDWR)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_b3fdf43c","line":304,"range":{"start_line":304,"start_character":17,"end_line":304,"end_character":25},"in_reply_to":"5f7c97a3_2d08a18f","updated":"2018-06-16 09:04:42.000000000","message":"+1 sorry, I got it :)","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"},{"author":{"_account_id":11536,"name":"hongbin","email":"hongbin034@gmail.com","username":"hongbin"},"change_message_id":"3d3209f81dfa7858ad52305c7cc9bb9af7f0af95","unresolved":false,"context_lines":[{"line_number":301,"context_line":"        tsock \u003d client.exec_start(exec_id, socket\u003dTrue, tty\u003dTrue)"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        try:"},{"line_number":304,"context_line":"            self.do_proxy(tsock)"},{"line_number":305,"context_line":"        finally:"},{"line_number":306,"context_line":"            if tsock:"},{"line_number":307,"context_line":"                tsock.shutdown(socket.SHUT_RDWR)"}],"source_content_type":"text/x-python","patch_set":13,"id":"5f7c97a3_2d08a18f","line":304,"range":{"start_line":304,"start_character":17,"end_line":304,"end_character":25},"in_reply_to":"5f7c97a3_4c0acc27","updated":"2018-06-16 02:22:13.000000000","message":"Call do_proxy is correct. Here is details:\n\n* do_websocket_proxy (defined in this class): do websocket to websocket proxy\n* do_proxy (defined in super class): do websocket to http proxy.\n\nIn here, we intent to do websocket to http proxy since the Docker exec API is for http streaming only (which is unlike the docker attach API that supports websocket).","commit_id":"2433eacce83c307ddb7b24697b9a57dd36645ad3"}]}
