diff --git a/httprl.module b/httprl.module
index 1053360..bff7d0c 100644
--- a/httprl.module
+++ b/httprl.module
@@ -51,6 +51,11 @@ define('HTTPRL_URL_INVALID_SCHEMA', -1003);
 define('HTTPRL_ERROR_INITIALIZING_STREAM', -1004);
 
 /**
+ * Error code indicating that the DNS lookup timed out.
+ */
+define('HTTPRL_DNS_TIMEOUT', -1005);
+
+/**
  * Error code indicating that the request exceeded the specified timeout.
  *
  * @see http://msdn.microsoft.com/en-us/library/aa924071.aspx
@@ -322,6 +327,18 @@ function httprl_request($url, $options = array()) {
     $flags = STREAM_CLIENT_CONNECT;
   }
 
+  // hook_httprl_request_alter()
+  // Allow other programs to alter the connection before it is made.
+  $data = array($socket, $flags, $uri, $url, $options, $result);
+  drupal_alter('httprl_request', $data);
+  list($socket, $flags, $uri, $url, $options, $result) = $data;
+
+  if (isset($result->error)) {
+    // Add in failed request to the output.
+    // Exit if an invalid scheme was passed in.
+    return httprl_send_request(FALSE, $url, $result, $options);
+  }
+
   // Start the timer.
   $timer_name = mt_rand();
   timer_start($timer_name);
@@ -1126,6 +1143,78 @@ function httprl_background_processing($output, $wait = TRUE, $content_type = "te
 }
 
 /**
+ * Implement hook_httprl_request_alter().
+ *
+ * Use nslookup because it supports timeouts.
+ * Use static cache for DNS lookups.
+ */
+function httprl_httprl_request_alter(&$data) {
+  // Use the advanced drupal_static() pattern.
+  static $hosts;
+  if (!isset($hosts) && function_exists('drupal_static')) {
+    $hosts = &drupal_static(__FUNCTION__);
+  }
+
+  // Extract parameters passed in.
+  list($socket, $flags, $uri, $url, $options, $result) = $data;
+
+  // Return if request timed out.
+  if ($options['timeout'] < 0) {
+    return;
+  }
+  // Return if request already has an error set.
+  if (isset($result->error)) {
+    return;
+  }
+
+  // Parse URL, getting hostname for DNS lookup.
+  $parsed = @parse_url($socket);
+  if (empty($parsed) || empty($parsed['host'])) {
+    return;
+  }
+  if (!is_numeric($options['timeout'])) {
+    return;
+  }
+
+
+  // See if host was already looked up.
+  if (isset($hosts[$parsed['host']])) {
+    $parsed['host'] = $hosts[$parsed['host']];
+  }
+  else {
+    // Start the timer.
+    $timeout = max(1, floor($options['timeout']-1));
+    $timer_name = mt_rand();
+    timer_start($timer_name);
+
+    // Execute nslookup.
+    $query = shell_exec('nslookup -timeout=' . $timeout . ' -retry=1 ' . escapeshellarg($parsed['host']));
+    if (preg_match('/\nAddress: (.*)\n/', $query, $matches)) {
+      $matches[1] = trim($matches[1]);
+      $hosts[$parsed['host']] = $matches[1];
+      $parsed['host'] = $matches[1];
+    }
+
+    // Stop the timer.
+    $options['timeout'] = $options['timeout'] - timer_read($timer_name) / 1000;
+    timer_stop($timer_name);
+
+    // Set error if we are out of time.
+    if ($options['timeout'] < 0) {
+      $result->code = HTTPRL_DNS_TIMEOUT;
+      $result->error = t('DNS lookup timed out. php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution.');
+    }
+  }
+
+  // Glue $socket back together.
+  $socket = httprl_glue_url($parsed);
+
+  // Send it back.
+  $data = array($socket, $flags, $uri, $url, $options, $result);
+}
+
+
+/**
  * Get the length of a string in bytes.
  *
  * @param $string
