Pluggable architecture for drupal_http_request()

pepiqueta - May 22, 2006 - 08:52
Project:Drupal
Version:7.x-dev
Component:base system
Category:feature request
Priority:normal
Assigned:Dave Reid
Status:needs work
Description

In case your hosting provider has disabled fsockopen() for some reasen, here's a patch that can bypass that restriction using curl.
I know the code is ugly, but it was a quick hack for a site I administer. Please add suggestions or improvements.
Code below replaces ping_ping() in ping.module.

function ping_ping($name = '', $url = '') {

  function curl_xmlrpc_ping ($ping_server, $local_name, $local_url) {

    $xml_request  = '<?xml version="1.0"?>'; //  encoding?
    $xml_request .= '<methodCall><methodName>weblogUpdates.ping</methodName>';
    $xml_request .= '<params><param><value>'.$local_name.'</value></param>';
    $xml_request .= '<param><value>'.$local_url.'</value></param></params></methodCall>';

    $curl_handle = curl_init();
    $post_header  =  array( 'Content-type: text/xml' ); //  required for xml posting
    curl_setopt ($curl_handle, CURLOPT_URL, $ping_server); //  hostname with 'http://'
    curl_setopt ($curl_handle, CURLOPT_POST, 1);
    curl_setopt ($curl_handle, CURLOPT_HTTPHEADER, $post_header);
    curl_setopt ($curl_handle, CURLOPT_POSTFIELDS, $xml_request);
    curl_setopt ($curl_handle, CURLOPT_RETURNTRANSFER, 1);
    $curl_buffer = curl_exec($curl_handle);
    curl_close($curl_handle);

    $response = trim(strip_tags($curl_buffer));
    if (preg_match ('/flerror{0,1}/i',$response)) {
      $return_msg = 'Server response: ';
        if (preg_match ('/flerror0/i',$response)) {
          $return_msg .= 'OK, ';
          $return_code = 0;
        } else {
          $return_msg .= 'ERROR, ';
          $return_code = 1;
        }
        $return_msg .= preg_replace ('/message/i','',stristr ($response, 'message'));
    } else {
      $return_msg = 'ERROR, NOT a weblogUpdates.ping response: ';
      $return_msg .= $response;
      $return_code = 2;
    }
    $return_array[code] = $return_code;
    $return_array[msg] = $return_msg;
    return $return_array;
  }

  $pingers = explode("\n", variable_get('ping_pinger_list', 'http://rpc.pingomatic.com'));
  foreach ($pingers as $pinger) {
    $pinger = trim($pinger);
    if (empty($pinger)) {
      continue;
    }
    $result = curl_xmlrpc_ping ($pinger, $name, $url);

    if ($result[code] = 0) {
      $watchdog_severity = 'WATCHDOG_NOTICE'; //log successful pings too
    }
    else {
      $watchdog_severity = 'WATCHDOG_WARNING';
    }
    watchdog('directory ping',t('Server: '.$pinger.'. Response: '.$result[msg]), $watchdog_severity);
  }
}

#1

killes@www.drop.org - May 22, 2006 - 10:43
Version:4.7.0» x.y.z

no new features for 4.7

#2

pepiqueta - May 22, 2006 - 14:06

Oh, sorry.

#3

breyten - May 22, 2006 - 14:30

What are the odds that fsockopen is disabled, and curl is enabled? I think it's not very likely.

#4

chx - May 22, 2006 - 14:54
Title:Ping without fsockopen or xmlrpc: custom curl function for pinging sites» Make it possible to use other transport mechanisms
Status:needs review» active

Core should provide a hook in drupal_http_request through which a curl_http_request can take over. That's a minimal patch. Then curlhttprequest module can be put to contrib (not into core, though).

#5

breyten - May 22, 2006 - 15:29
Component:ping.module» base system

Let's make ab object out of drupal_http_request ;p

But seriously, chx is right. I think we should make an implementation akin to user_mail.

#6

pepiqueta - May 22, 2006 - 22:14

I don't know how often this happens. In fact I know of only one case: mine! I set up a site and when I tried to ping some servers it failed because fsockopen was disabled (it seems that some users on that hosting provider abused it for spamming or something). So I did this for bypassing that restriction. I don't know if this will be helpful for someone, but I just wanted to share this.

I just wanted that feature for ping.module. I agree that it should appear somewhere else in the source tree, but I'm noob to Drupal (well, PHP newbie too...) so that's too much for my skills. Maybe someone could do this.

BTW, I aplied for CVS access a couple of days ago but got no response from admins.

#7

LAsan - April 7, 2008 - 11:02
Version:x.y.z» 7.x-dev

Any work done in the patch code?

Moving to cvs.

#8

Dave Reid - October 11, 2008 - 09:03
Assigned to:Anonymous» Dave Reid

I'm going to pick up this issue. I'd like to be able to over-ride drupal_http_request with curl.

#9

Dave Reid - October 29, 2008 - 06:41
Status:active» needs review

Here's my first attempt at this patch. Introduces a new hook: hook_http_request. The main fetching code done in drupal_http_request has been moved to system_http_request. drupal_http_request now acts as the abstract HTTP request function:

<?php
 
// Perform request.
 
$module = variable_get('http_request', 'system');
 
$result = module_invoke($module, 'http_request', $url, $options);
?>

Patch also makes use of the new hook_modules_enabled and hook_modules_disabled hooks to override and un-override the http_request variable:

<?php
/**
* Implementation of hook_modules_enabled().
*/
function system_modules_enabled($modules) {
 
// Check if modules define hook_http_request().
  // Set override variable if it requests successfully.
  // TODO: Registry has not been rebuilt yet and module_hook FAILS if module does have hook_http_request().
 
foreach ($modules as $module) {
    if (
module_hook($module, 'http_request') && module_invoke($module, 'check_http_request')) {
     
variable_set('http_request', $module);
      break;
    }
  }
}

/**
* Implementation of hook_modules_disabled().
*/
function system_modules_disabled($modules) {
 
// Check if modules defined hook_http_request().
  // Reset override variableif no longer available.
 
foreach ($modules as $module) {
    if (
module_hook($module, 'http_request')) {
     
variable_set('http_request', 'system');
     
module_invoke('system', 'check_http_request');
      break;
    }
  }
}
?>

Attached is the patch to core and the first-version curl module to test overriding http requests. Hopefully this can start getting a little momentum and review towards this patch.

AttachmentSizeStatusTest resultOperations
64866-http-request-override-D7.patch14.69 KBIdleFailed: Failed to apply patch.View details | Re-test
curl-module-D7.zip1.03 KBIgnoredNoneNone

#10

Dave Reid - October 29, 2008 - 06:36

I should note that this patch also changes drupal_http_request to use an $options parameter instead of the $headers, $method, $data, and $retry parameters.

#11

Dries - October 29, 2008 - 09:56

Mollom is affected by this too so I'd like to see us fix this. For Mollom, we would like to open a secure 'https' connection to mollom.com. That seems impossible to do with the current drupal_http_request() code but would be possible with CURL.

Looking at your patch, I wonder if it needs to be that configurable. It feels a bit over-engineered to me. Why don't we just use CURL, when CURL is available, and fall-back to the current implementation when CURL is not available?

#12

chx - October 30, 2008 - 00:57

Someone might want to use the http extension in PECL mayhaps in php core soon? Anyways those system hooks hurt my eyes. Why not jus let moudles set their variables in their install hook instead of burdening system with it? Also, why is this in .module instead of a handy system.http.inc or something? Excellent opportunity to remove rarely run code out of every page request!

#13

Anonymous (not verified) - November 13, 2008 - 07:02
Status:needs review» needs work

The last submitted patch failed testing.

#14

Dave Reid - December 2, 2008 - 21:16
Title:Make it possible to use other transport mechanisms» Pluggable architecture for drupal_http_request()

I should probably model this patch off the work done in #303930: Pluggable architecture for aggregator.module, and give the site administrator the option to select which module to use for drupal_http_request instead of having the modules set variables on install/uninstall. I'm also going to split off the parameter array-itizing into #337783: DX: Array-itize drupal_http_request()'s parameters and hopefully get that accepted first before this issue.

#15

Dave Reid - December 6, 2008 - 20:18
Status:needs work» postponed

Postponing until #337783: DX: Array-itize drupal_http_request()'s parameters gets in HEAD.

#16

boombatower - December 11, 2008 - 21:38

#17

drewish - December 26, 2008 - 20:41

subscribing. i'd love to see this feature added.

#18

Dries - December 26, 2008 - 21:03
Status:postponed» needs work

#337783: DX: Array-itize drupal_http_request()'s parameters has landed, so I'm switching this back to 'code needs work'.

#19

Dries - December 26, 2008 - 21:09

When CURL is supported, core should use it. For one, it makes SSL support a lot easier, and it is more robust than our own implementation is. So, OK for making it a pluggable solution (if needed), but let's avoid introducing a barrier here -- we don't want people to install or configure anything when CURL is available, IMO. I think CURL should be the default, with a silent and graceful fallback to our own implementation when CURL is not available.

#20

boombatower - December 27, 2008 - 00:55

Considering SimpleTest already has a CURL browser I would recommend we focus on it. I already have a working pluggable backend patch at: #340283: Abstract SimpleTest browser in to its own object.

It still needs a bit of work, but getting close.

#21

chx - December 29, 2008 - 04:05

I still think that the system_http_request should use the HTTP(S) wrapper with file_get_contents. We can use stream_context_create to set options and stream_get_meta_data to read the response headers.

#22

Dave Reid - January 6, 2009 - 21:35

#23

Rob Loach - January 25, 2009 - 21:50

#24

ibandyop - January 29, 2009 - 13:47

subscribing. Looking forward to cURL with Proxy handling

#25

boombatower - January 29, 2009 - 19:44

can we focus/look at #20

I think it is rather far along, just been to busy to finish it.

#26

pwolanin - June 16, 2009 - 19:28

essentially blocked on Crell's mythical handlers in core?

#27

chx - June 16, 2009 - 23:25

The way we make things pluggable can now be seen in system.queue.inc and soon cache.inc. (and field_sql_storage.module)

#28

boombatower - June 17, 2009 - 00:32

I will be working on #20 and I would like some reviews (hope to have documented patch later today). It will provide the same tools that drupal_http_request() does (we could even keep that as a wrapper), but also has a number of advanced browser tools and a pluggable architecture.

#29

pwolanin - July 30, 2009 - 13:57

any progress on this?

 
 

Drupal is a registered trademark of Dries Buytaert.