Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QNetworkReply and QNetworAccessManager don't emit `finished` signal
Qt 6.11 is out! See what's new in the release blog

QNetworkReply and QNetworAccessManager don't emit `finished` signal

Scheduled Pinned Locked Moved Solved Qt for Python
14 Posts 3 Posters 4.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi and welcome to devnet,

    Did you already check the traffic with Wireshark to see the answer you are getting back from the server ?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    X 1 Reply Last reply
    1
    • X xueqli

      Hello,

      I am trying to access an API which requires authentication, but when I set incorrect bearer token in the header both reply and network manager don't emit finished signal.
      reply.isFinished() -> False
      reply.error() -> NoError
      reply.isRunning() -> True

      If I remove token, then everything's fine and request fails with an error ContentAccessDenied: 201
      If I set the correct token, then everything's working too
      If I use the requests library with an incorrect token, then everything works: the answer has status code 401

      The only thing that I came up with is using setTransferTimeout and waiting for the request to abort after this timeout

      Here is an example of what I'm trying to run:

      import sys
      
      from PyQt6.QtCore import QUrl
      from PyQt6.QtNetwork import QNetworkReply
      from PyQt6.QtNetwork import QNetworkRequest
      from PyQt6.QtNetwork import QNetworkAccessManager
      from PyQt6.QtWidgets import QApplication
      
      
      class ApiAccess:
          def __init__(self) -> None:
              self.manager = QNetworkAccessManager()
              self.manager.finished.connect(self.on_manager_finished)
      
              self.reply = None
              self.token = "123"
      
          def get(self, url: QUrl) -> None:
              request = QNetworkRequest(url)
              request.setRawHeader(b"Authorization", f"Bearer {self.token}".encode("utf-8"))
              request.setRawHeader(b"User-Agent", b"MyUserAgent")
      
              self.reply = self.manager.get(request)
              self.reply.finished.connect(self.on_reply_finished)
              self.reply.errorOccurred.connect(self.on_reply_error)
      
          def on_manager_finished(self, reply: QNetworkReply) -> None:
              print(reply)
      
          def on_reply_error(self, error: QNetworkReply.NetworkError) -> None:
              print(error)
      
          def on_reply_finished(self) -> None:
              data = self.reply.readAll().data()
              print(data)
      
      
      def main():
          app = QApplication(sys.argv)
      
          api = ApiAccess()
          url = QUrl("https://api.someresource.com/path?query")
          api.get(url)
      
          return app.exec()
      
      
      if __name__ == "__main__":
          raise SystemExit(main())
      

      Is this a bug, or am I missing something? (PyQt6 6.6.1)

      Ronel_qtmasterR Offline
      Ronel_qtmasterR Offline
      Ronel_qtmaster
      wrote on last edited by
      #3

      @xueqli in the url, change https to http and try again

      X 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi and welcome to devnet,

        Did you already check the traffic with Wireshark to see the answer you are getting back from the server ?

        X Offline
        X Offline
        xueqli
        wrote on last edited by
        #4

        @SGaist Hi! What exactly am I supposed to look at in the traffic?
        It looks like the server does respond to the requests
        Here are some screens:
        qt_correct_token.png qt_wrong_token.png requests_correct_token.png requests_wrong_token.png

        1 Reply Last reply
        0
        • Ronel_qtmasterR Ronel_qtmaster

          @xueqli in the url, change https to http and try again

          X Offline
          X Offline
          xueqli
          wrote on last edited by
          #5

          @Ronel_qtmaster unfortunately, that didn't help

          1 Reply Last reply
          0
          • X Offline
            X Offline
            xueqli
            wrote on last edited by
            #6

            For now I'm pretty sure that this is related to QTBUG-122281, because when I connect the metaDataChanged signal and look into reply's headers, they contain information about the invalid token, but nothing happens after

            SGaistS 1 Reply Last reply
            0
            • X xueqli

              For now I'm pretty sure that this is related to QTBUG-122281, because when I connect the metaDataChanged signal and look into reply's headers, they contain information about the invalid token, but nothing happens after

              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #7

              @xueqli just to rule out the obvious, you have the same issue if you send requests to a different service ?

              Is there one that is accessible that you can share for testing purposes so we can test it ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              X 1 Reply Last reply
              1
              • SGaistS SGaist

                @xueqli just to rule out the obvious, you have the same issue if you send requests to a different service ?

                Is there one that is accessible that you can share for testing purposes so we can test it ?

                X Offline
                X Offline
                xueqli
                wrote on last edited by
                #8

                @SGaist hmm, I haven't encountered this issue for other services
                At first I thought that the problem is with www-authenticate header field
                So I found the API which also sends it (https://registry-1.docker.io/v2/_catalog, for example), and it works fine (my API sends some other attributes in www-authenticate header, but they are all valid)

                The other difference I noticed, my API doesn't send any content (answer.content == b''), and all API I've tried so far send a non-empty error message, so maybe my problem lies here

                1 Reply Last reply
                0
                • X Offline
                  X Offline
                  xueqli
                  wrote on last edited by
                  #9

                  i don't know, looks like it stuck somewhere in the QIODevice::read?

                  (Pdb) self.reply.isOpen()
                  True
                  (Pdb) self.reply.bytesAvailable()
                  0
                  (Pdb) self.reply.read(1000)
                  b''
                  (Pdb) self.reply.read(1000)
                  b''
                  (Pdb) self.reply.read(1000)
                  b''
                  (Pdb) self.reply.read(1000)
                  b''
                  (Pdb) self.reply.read(1000)
                  b''
                  (Pdb) self.reply.close()
                  got reply error! NetworkError.OperationCanceledError
                  download progress! received=0 total=0
                  manager finished!
                  QIODevice::read (QNetworkReplyHttpImpl): device not open
                  reply finished! b''
                  

                  and after i manually close reply it says, that device is not open and emits all the signals i want it to emit

                  i also made up an http server, which sends similar headers and empty content and it magically works! (but with this "manual close" it has some different output:

                  self.reply.isOpen()=True
                  got reply error! NetworkError.OperationCanceledError
                  download progress! received=0 total=0
                  manager finished!
                  QIODevice::read (QNetworkReplyHttpImpl): device not open
                  reply finished! b''
                  QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
                  

                  i have no ideas. think i probably should give up and create workarounds

                  SGaistS 1 Reply Last reply
                  0
                  • X xueqli

                    i don't know, looks like it stuck somewhere in the QIODevice::read?

                    (Pdb) self.reply.isOpen()
                    True
                    (Pdb) self.reply.bytesAvailable()
                    0
                    (Pdb) self.reply.read(1000)
                    b''
                    (Pdb) self.reply.read(1000)
                    b''
                    (Pdb) self.reply.read(1000)
                    b''
                    (Pdb) self.reply.read(1000)
                    b''
                    (Pdb) self.reply.read(1000)
                    b''
                    (Pdb) self.reply.close()
                    got reply error! NetworkError.OperationCanceledError
                    download progress! received=0 total=0
                    manager finished!
                    QIODevice::read (QNetworkReplyHttpImpl): device not open
                    reply finished! b''
                    

                    and after i manually close reply it says, that device is not open and emits all the signals i want it to emit

                    i also made up an http server, which sends similar headers and empty content and it magically works! (but with this "manual close" it has some different output:

                    self.reply.isOpen()=True
                    got reply error! NetworkError.OperationCanceledError
                    download progress! received=0 total=0
                    manager finished!
                    QIODevice::read (QNetworkReplyHttpImpl): device not open
                    reply finished! b''
                    QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.
                    

                    i have no ideas. think i probably should give up and create workarounds

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    @xueqli before working around, please open a ticket on the bug report system with your findings. It seems you have a valid case to make.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    1
                    • X Offline
                      X Offline
                      xueqli
                      wrote on last edited by xueqli
                      #11

                      i found out that apparently it has nothing to do with either contents or headers,
                      and the real reason is: the request was using HTTP/2 protocol
                      disabling HTTP/2 (request.setAttribute(request.Attribute.Http2AllowedAttribute, False)) solves my problem

                      but what's wrong with HTTP/2 is yet to be figured out

                      SGaistS 1 Reply Last reply
                      1
                      • X xueqli has marked this topic as solved on
                      • X xueqli

                        i found out that apparently it has nothing to do with either contents or headers,
                        and the real reason is: the request was using HTTP/2 protocol
                        disabling HTTP/2 (request.setAttribute(request.Attribute.Http2AllowedAttribute, False)) solves my problem

                        but what's wrong with HTTP/2 is yet to be figured out

                        SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #12

                        @xueqli Nice catch !

                        I would still recommend opening a ticket.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        X 1 Reply Last reply
                        1
                        • SGaistS SGaist

                          @xueqli Nice catch !

                          I would still recommend opening a ticket.

                          X Offline
                          X Offline
                          xueqli
                          wrote on last edited by
                          #13

                          @SGaist yea, i did: https://bugreports.qt.io/browse/QTBUG-123891
                          (and turned out both HTTP/2 and www-authenticate headers are required to reproduce this)

                          1 Reply Last reply
                          1
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #14

                            Thanks for the link and thorough spelunking !

                            Since you have a Python reproducer, you should add it to the bug report, it will make things easier for developers to reproduce :-)

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            1

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved