4

Using Qt5, how to simply check if given url is available?

Not using special functions for signal slots, but simply using something like bool isUrlAvailable(QString url), are there any function like this?

Update QUrl.isValid() is incorrect answer, it is just checks if url is correctly formed.

Update 2 QUrl.host() is incorrect answer too, it is just returns host part of given url, it does not check for its availability.

Update 3 pinging host is also incorrect, because url may be available, but does not accept icmp echo (=ping)

vladon
  • 8,158
  • 2
  • 47
  • 91
  • In my opinion your question is too broad, because method of checking of availability depends on specific [URI schema](http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes) in URL. – Gluttton Feb 13 '15 at 08:53
  • @Gluttton, if it always will be http, may be simply HEAD request to given url? I cannot find how to do it simply in Qt5. – vladon Feb 13 '15 at 09:15

2 Answers2

6

Yes, you can do a HEAD request to a given URL.

bool urlExists (QString url_string) {
    QUrl url(url_string);
    QTcpSocket socket;
    socket.connectToHost(url.host(), 80);
    if (socket.waitForConnected()) {
        socket.write("HEAD " + url.path().toUtf8() + " HTTP/1.1\r\n"
                     "Host: " + url.host().toUtf8() + "\r\n\r\n");
        if (socket.waitForReadyRead()) {
            QByteArray bytes = socket.readAll();
            if (bytes.contains("200 OK")) {
                return true;
            }
        }
    }
    return false;
}

This is just an example for 200 OK and you might also want to check if the status code is some other in 2XX or in 3XX (redirection) class.

pajaja
  • 2,164
  • 4
  • 25
  • 33
2

So taking from pajaja + a few other SO answers + a tutorial I found (http://www.blikoon.com/networking/http-potocol-writting-a-simple-client-using-qt-qtcpsocket-and-troubleshooting-using-telnet)

I came up with this tweaked version because the one above didn't work

bool urlExists(QUrl theurl){
    QTextStream out(stdout);
    QTcpSocket socket;
    QByteArray buffer;

    socket.connectToHost(theurl.host(), 80);
    if (socket.waitForConnected()) {
        //Standard http request
        socket.write("GET / HTTP/1.1\r\n"
                 "host: " + theurl.host().toUtf8() + "\r\n\r\n");
        if (socket.waitForReadyRead()) {
            while(socket.bytesAvailable()){
                buffer.append(socket.readAll());
                int packetSize=buffer.size();
                while(packetSize>0)
                {
                    //Output server response for debugging
                    out << "[" << buffer.data() << "]" <<endl;

                    //set Url if 200, 301, or 302 response given assuming that server will redirect
                    if (buffer.contains("200 OK") ||
                        buffer.contains("302 Found") ||
                        buffer.contains("301 Moved")) {
                        return true;
                    }
                    buffer.remove(0,packetSize);
                    //packetSize=getPacketSize(buffer);
                    packetSize=buffer.size();

                } //while packet size >0
            } //while socket.bytesavail

        } //socket wait for ready read
    }//socket write   
return false;
}

The QTextStream prints what is being read from the socket so you can know what conditions to add and why your http request didn't work (I used it to figure out that I needed 301 and 302). The while loops are a modified version of ratchetfreak's answer here

How to read complete data in QTcpSocket?

to make sure you get everything out of the socket. I'm testing if I need to change the "/index.html" part of the socket write but so far it seems fine.


Edit: Should just be "GET /" not "GET /index.html"

Community
  • 1
  • 1
S. Pan
  • 619
  • 7
  • 13