The world of KIO metadata - checking the HTTP response from a server

Recently, I investigated how to perform some checks on web addresses using KIO for Danbooru Client. My old code was synchronous, so it blocked the application while checking, thus causing all sort of troubles (UI freezing, etc.). Therefore, making the switch to KIO was the best solution. However, I had one problem: how could I check the HTTP response?

I knew already that the various ioslaves can store metadata, consisting of key-value pairs which are specific on the slave used. Normally you can get the whole map by accessing the metaData function of the job you have used, in the slot connected from the result signal. For some reason, however, in PyKDE4 calling metaData() triggers an assert in SIP, which ends in a crash (at least in my application; I stil need to debug further). KIO jobs have also the queryMetaData function, which returns the value of the key you have queried. Unfortunately, there was no way I could find the name.

Thus began my search for the right key. Googling didn’t help, and on IRC I got the first answers I needed but not enough to reach the goal. Until I saw a commit by David Faure in trunk/kdelibs/kio/ which touched a file called DESIGN.metadata (link is for the branch version). After checking with webSVN, that was exactly the thing I was looking for! It lists all the keys for the metadata, indicating also to which ioslave they begin. After that, the solution was easy.

Of course I’m not leaving you hanging there and now I’ll show you how, in PyKDE4, you can quickly check for the server response:

from PyKDE4.kio import KIO
from PyQt4.QtCore import SIGNAL

class my_widget(QWidget):

def check_address(self, url):

    # You can add optional flags such as KIO.HideProgressInfo
    job = KIO.get(KUrl(url))
    self.connect(job, SIGNAL("result (KJob *)"), self.slot_result)

def slot_result(self, job):
    if job.error():
        # Bail out if there's an error

    # Get the HTTP response through queryMetaData
    http_response = job.queryMetaData("responsecode")
    print "Got response: %s" % unicode(http_response)


This snippet does a few things. Firstly, it gets the specified URL, using KIO.get (KIO.stat doesn’t set the required metadata). Notice that the call is not wrapped in the new-style PyQt API because result (KJob *) isn’t wrapped like that (there’s a bug open for that). In any case, the signal passes to the connecting slot (slot_result) where we first check if there’s an error (perhaps the address didn’t exist?) and then we use queryMetaData(“responsecode”) to get the actual response code.

If you want to do error checking basing on the result, bear in mind that KIO operates asynchronously, so you should use a signal to tell your application that the result is what it expected or not.

I wonder if this should be documented in Techbase…

Dialogue & Discussion