diff --git a/globalredirect.module b/globalredirect.module
index 34f5310..903b21b 100644
--- a/globalredirect.module
+++ b/globalredirect.module
@@ -148,7 +148,7 @@ function globalredirect_init() {
 
         // If there is, go to the translation.
         if (!empty($node_translations[$language->language]) && $node_translations[$language->language] != $matches[0]) {
-          drupal_goto($node_translations[$language->language], $options, 301);
+          globalredirect_goto($node_translations[$language->language], $options);
         }
         // If there is no translation, change the language to fit the content
         else {
@@ -160,7 +160,7 @@ function globalredirect_init() {
             // Change the global $language's prefix, to make drupal_goto()
             // follow the proper prefix
             $options['language'] = $language = $all_languages[$node->language];
-            drupal_goto('node/' . $node->nid, $options, 301);
+            globalredirect_goto('node/' . $node->nid, $options);
           }
         }
         break;
@@ -218,14 +218,14 @@ function globalredirect_init() {
   if ($request_path != $prefix . $alias) {
     // If it's not just a slash or user has deslash on, redirect
     if (str_replace($prefix . $alias, '', $request_path) != '/' || $settings['deslash']) {
-      drupal_goto($alias, $options, 301);
+      globalredirect_goto($alias, $options);
     }
   }
 
   // If no alias was returned, the final check is to direct non-clean to
   // clean - if clean is enabled
   if ($settings['nonclean_to_clean'] && ((bool)variable_get('clean_url', 0)) && strpos(request_uri(), '?q=')) {
-    drupal_goto($current_path, $options, 301);
+    globalredirect_goto($current_path, $options);
   }
 
   // Restore the destination from earlier so its available in other places.
@@ -249,6 +249,28 @@ function globalredirect_init() {
 }
 
 /**
+ * A wrapper for drupal_goto() that does not pass through if $path is an
+ * external URL.
+ */
+function globalredirect_goto($path = '', array $options = array(), $http_response_code = 301) {
+  if (!globalredirect_url_is_external($path)) {
+    return drupal_goto($path, $options, $http_response_code);
+  }
+}
+
+/**
+ * Check if a path is external (e.g. http://example.com).
+ *
+ * This is a simple copy of url_is_external() which if given an URL with an
+ * invalid protocal will return FALSE, an undesired value. This function will
+ * return TRUE given an URL with an invalid protocol.
+ */
+function globalredirect_url_is_external($path) {
+  $colonpos = strpos($path, ':');
+  return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos));
+}
+
+/**
  * Implements hook_menu().
  */
 function globalredirect_menu() {
@@ -291,13 +313,6 @@ function _globalredirect_is_active($settings) {
   }
 
   /**
-   * Check if the request is an attempted url mask
-   */
-  if (strpos(request_uri(), '://') !== FALSE) {
-    return FALSE;
-  }
-
-  /**
    * If the site is in offline mode there is little point doing any of this as
    * you might end up redirecting to a 503.
    */
diff --git a/globalredirect.test b/globalredirect.test
index c24b92a..c644cb6 100644
--- a/globalredirect.test
+++ b/globalredirect.test
@@ -133,11 +133,41 @@ class GlobalRedirectTestCase extends DrupalWebTestCase {
         'expected-path' => $settings['nonclean_to_clean'] ? 'node/add/page' : '?q=node/add/page',
       ),
 
+      // Ensure that the NonClean to Clean with an external URL does not redirect.
+      array(
+        'request' => url('<front>', array('absolute' => TRUE)),
+        'options' => array('query' => array('q' => 'http://www.example.com'), 'external' => TRUE),
+        'return-code' => 404,
+      ),
+      array(
+        'request' => url('<front>', array('absolute' => TRUE)),
+        'options' => array('query' => array('q' => 'http://www.example.com/'), 'external' => TRUE),
+        'return-code' => 404,
+      ),
+      // Also test un-escaped query strings with external URLs.
+      array(
+        'request' => url('<front>', array('absolute' => TRUE)) . '?q=http://www.example.com',
+        'options' => array('external' => TRUE),
+        'return-code' => 404,
+      ),
+      array(
+        'request' => url('<front>', array('absolute' => TRUE)) . '?q=http://www.example.com/',
+        'options' => array('external' => TRUE),
+        'return-code' => 404,
+      ),
+      // Test with external URLs in the destination query string.
+      array(
+        'request' => 'node/1',
+        'options' => array('query' => array('destination' => 'http://www.example.com/')),
+        'return-code' => 301,
+        'expected-path' => 'test-node',
+      ),
+
       // Case Sensitive URL Check --- This may or may not redirect, depending on the state of case_sensitive_urls as we're requesting an aliased path in the wrong case
       array(
         'request' => 'Test-Node',
         'options' => array('external' => TRUE),
-        'return-code' => $settings['case_sensitive_urls'] ? 301 : 200,
+        'return-code' => $settings['case_sensitive_urls'] ? (db_driver() == 'sqlite' ? 404 : 301) : (db_driver() == 'sqlite' ? 404 : 200), // SQLite cannot return case-insensitive rows.
         'expected-path' => $settings['case_sensitive_urls'] ? 'test-node' : 'Test-Node',
       ),
 
