cachinghttpsdnsvalahttp-caching

How to cache DNS in libsoup in Vala?


I am using libsoup in my Vala application to get data from Instagram API. But it takes about 10 seconds to load one page from it (while browser displays the same page in ~1-2 seconds). I thought initially that it is because of HTTPS (HTTPS pages load way longer that HTTP pages), but I figured out that most of the time it resolves my most.

So, the question is: is there any way I can cache DNS results to not resolve host every time I need a connection to it? Or is it possible?

Here is the function I'm using:

public string getResponse (string host) 
{
    var session = new Soup.Session ();
    session.ssl_strict = false;
    session.user_agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36";

    var message = new Soup.Message ("GET", host);
    message.tls_errors = GLib.TlsCertificateFlags.VALIDATE_ALL;
    message.network_event.connect((event) => {
        if (event == SocketClientEvent.RESOLVING) print("RESOLVING\n");
        if (event == SocketClientEvent.RESOLVED) print("RESOLVED\n");
        if (event == SocketClientEvent.CONNECTING) print("CONNECTING\n");
        if (event == SocketClientEvent.CONNECTED) print("CONNECTED\n");
        if (event == SocketClientEvent.PROXY_NEGOTIATING) print("PROXY_NEGOTIATING\n");
        if (event == SocketClientEvent.PROXY_NEGOTIATED) print("PROXY_NEGOTIATED\n");
        if (event == SocketClientEvent.TLS_HANDSHAKING ) print("TLS_HANDSHAKING \n");
        if (event == SocketClientEvent.TLS_HANDSHAKED) print("TLS_HANDSHAKED\n");
        if (event == SocketClientEvent.COMPLETE) print("COMPLETE\n");
    });

    print("start sending\n");
    session.send_message (message);
    print("stop sending\n");
    return (string) message.response_body.data;
}

and most of the time of loading is between "RESOLVING" and "RESOLVED.

Btw, I thought it's a good idea to set some field in GSettings to store Instagram API server IP and replacing host's hostname to that IP address, will that work? And if it will, how to implement it?


Solution

  • I rewrote my getResponse function this way and now it works the way I wanted it to.

    public string getResponse (string host) 
    { 
        var ip = loadAddress();
        if (ip == "")
            ip = resolveHost();
    
        var newHost = replaceHostWithIp(host, ip);
    
        var session = new Soup.Session ();
        session.ssl_strict = false;
        session.user_agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36";
    
        var message = new Soup.Message ("GET", newHost);
        message.tls_errors = GLib.TlsCertificateFlags.VALIDATE_ALL;  
    
        message.request_headers.append("Host", "api.instagram.com");
    
        session.send_message (message);
    
        if (loadAddress() == "")
            setAddress(ip);
    
        return (string) message.response_body.data;
    }
    

    where loadAddress() and setAddress() are functions which load IP from GSettings and sets it and replaceHostWithIp() is a function that replaces api.instagram.com with given IP address.