Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在没有原始数据的情况下重新发送post/put请求_C++_Qt_Qtnetwork - Fatal编程技术网

C++ 在没有原始数据的情况下重新发送post/put请求

C++ 在没有原始数据的情况下重新发送post/put请求,c++,qt,qtnetwork,C++,Qt,Qtnetwork,我最近有一个问题一直困扰着我。我正在创建一个简单的web浏览器,用于与单个网站交互,以便用户管理产品。我目前面临的问题是:用户可以通过基本web表单的ui上传新文件。选择上载后,请求将失败,错误代码为205,即: QNetworkReply::ContentReSendError-需要再次发送请求,但此操作失败,例如,因为无法再次读取上载数据 如果用户再次尝试上载,文件将无误上载。为了解决这个问题,我想检测是否有错误,如果有,重新发送请求 我的问题是,我没有与请求相关的数据。我可以检索请求本身,

我最近有一个问题一直困扰着我。我正在创建一个简单的web浏览器,用于与单个网站交互,以便用户管理产品。我目前面临的问题是:用户可以通过基本web表单的ui上传新文件。选择上载后,请求将失败,错误代码为205,即:

QNetworkReply::ContentReSendError-需要再次发送请求,但此操作失败,例如,因为无法再次读取上载数据

如果用户再次尝试上载,文件将无误上载。为了解决这个问题,我想检测是否有错误,如果有,重新发送请求

我的问题是,我没有与请求相关的数据。我可以检索请求本身,但不能检索数据。我想象我的解决方案看起来像嵌套的if-in

但是,该用户可以访问_currentItem,因为他们最初在程序中创建了请求,而我的请求是动态创建的。是否有某种方法可以捕获或缓存发送的数据?我曾希望QNetworkAccessManager存储以前的请求以便于重试,但我没有看到类似的情况。谢谢你的帮助

编辑


澄清:是否可以使用QNetworkAccessManager来获取程序中未定义的post/put的请求和数据。

是的,有两种方法,但实际上该功能不存在

  • 编辑Qt的源代码,将其直接添加到
    QNetworkAccessManager
    ,或

  • 将其实现为在同一进程中运行的仅缓存HTTP代理。代理的实现可以使用嵌套的
    QNetworkAccessManager
    在实际网络上执行请求。实现需要解码传入的请求,重新构建
    QNetworkRequest
    头,并将其与任何请求数据一起传递给嵌套的管理器。此时,您可以搁置数据,并在代理级别实现重试


  • 实现选项1可能会减少工作量和麻烦,但有些项目不合理地反对修改Qt,因此我将在这种情况下使用选项2。

    使用Python和PyQt,我通过使用函数装饰器解决了类似的问题,该装饰器将请求保存在lambda函数中,并在失败时重新发送请求。可能在C++中有类似的结构。 在我的特殊情况下,应用程序必须使用OAuth2系统,该系统发出的令牌仅在一小时内有效(并且无法刷新;隐式授权)。因此,在这一小时之后,用户可能会突然收到对其请求的“未经验证”响应,这当然不是真正的用户友好。所以我想,我应该捕获这个401响应,让用户重新验证,然后重新发送最后一个失败的请求

    在我的QNetworkAccessManager子类中,我用一个名为requires\u internet\u connection的函数修饰了我的HTTP函数(get、put、post等),因此我的get函数示例如下

     @check_network_accessibility
     def get(self, url, callback, *args, **kwargs):
        """ Perform a HTTP GET request """
        ...
    
    装潢师的样子如下:

    def check_network_accessibility(func):
        """ Decorator function, not to be called directly.
        Buffers the network request so that it can be sent again if it fails the first time, due to an invalidated 
        OAuth2 token. In this case the user will be presented with the login 
        screen again. If the *same* user successfully logs in again, the request 
        will be resent. """
    
        @wraps(func)
        def func_wrapper(inst, *args, **kwargs):
            if inst.logged_in_user:
                # Create an internal ID for this request
                request_id=uuid.uuid4()
                current_request = lambda: func(inst, *args, **kwargs)
                # Add tuple with current user, and request to be performed
                # to the pending request dictionary
                inst.pending_requests[request_id] = (
                    inst.logged_in_user['data']['id'], 
                    current_request)
                # Add current request id to kwargs of function being called
                kwargs['_request_id'] = request_id
            return func(inst, *args, **kwargs)
        return func_wrapper
    
    总之,我检查用户是否已登录,然后才将要发送的请求(完全包含传递的参数和所有参数)存储在lambda函数中,并将其存储在挂起的_请求字典中,使用唯一的uuid作为密钥。我将这个唯一的uuid注入到要调用的函数的kwargs中(使用键_request_id),以便如果请求成功,我可以使用这个uuid将其从包含未决请求的字典中删除(换句话说:清理)。如果QNetworkReply完成时没有问题,则可以在其回调函数中执行此操作

    但是,如果请求未成功,则会向用户显示一个登录窗口,如果用户再次成功登录,则会调用一个函数,该函数将遍历挂起请求的字典,并再次尝试执行以下操作:

    def handle_login(self):
        """ Handles the login event received after login. """
        self.get_logged_in_user(self.set_logged_in_user)
    
    def set_logged_in_user(self, user_data):
        """ Callback function for handle_login; get_logged_in_user"""
        # Parse received data about logged in user
        self.logged_in_user = json.loads(safe_decode(user_data.readAll().data()))
    
        # If user had any pending requests from previous login, execute them now
        for (user_id, request) in self.pending_requests.values():
            if user_id == self.logged_in_user['data']['id']:
                request()
        self.pending_requests = {}
    
    我使用字典的原因是,在Qt中可以并行发送多个请求,当用户必须重新验证时,它们当然都会失败。我希望在同一用户再次登录后再次尝试所有这些操作


    正如我前面所说的,我知道这是一个完全不同于C++的Python(我几乎不知道),但是我希望它能很好地说明这个原理,让我们在C++ ++中找到一个类似的结构,啊,那是不幸的。我会继续寻找另一个解决方案。谢谢你的回复!

    def handle_login(self):
        """ Handles the login event received after login. """
        self.get_logged_in_user(self.set_logged_in_user)
    
    def set_logged_in_user(self, user_data):
        """ Callback function for handle_login; get_logged_in_user"""
        # Parse received data about logged in user
        self.logged_in_user = json.loads(safe_decode(user_data.readAll().data()))
    
        # If user had any pending requests from previous login, execute them now
        for (user_id, request) in self.pending_requests.values():
            if user_id == self.logged_in_user['data']['id']:
                request()
        self.pending_requests = {}