Does anyone know how to use drupal_http_request as a way to check if a URL exists while passing authentication? For example, if I wanted to check that '/admin' existed, it would require authentication.

I am trying:

$url = 'http://www.domain.com/admin/reports?user='.$user->name.'&password='.$user->pass;
$try = drupal_http_request($url, $headers, 'GET', 0, 3);

results in a 403, and

$url = 'http://www.domain.com/?q=admin/reports&user='.$user->name.'&password='.$user->pass;
$try = drupal_http_request($url, $headers, 'GET', 0, 3);

results in a 301.

Not quite sure what I am doing wrong.

Comments

stevenc’s picture

I -think- the problem is your parameter for the password.

According to the API documentation, that function will parse the query string for authentication, but password is named "pass"

Reference:
http://api.drupal.org/api/function/drupal_http_request/6

Code about 1/2 way through the function:

...
 // If the server url has a user then attempt to use basic authentication
  if (isset($uri['user'])) {
    $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : ''));
  }
...

Try changing "password" to "pass" and see what happens.

Note that I've not tried this myself, so I'm curious what your results are.

---------------------------------
Steven Wright

Slalom

kevinquillen’s picture

Oh, duh. Can't beleive I missed that. I will try it out.

I am trying to find a way to solve menu rebuild bug where the menu doesn't always get rebuilt and parts of the administrative section are not available. So, I thought if I could check the response code from these URLs, if I didn't get a 200 I could call menu_router_build or cache_clear_all to attempt to solve the issue.

Previously we had modified menu.inc to use db transactions which required making tables InnoDB... I wanted to try something a bit cleaner.

===========
read my thoughts

kevinquillen’s picture

That did the trick. Rename mymodule with whatever name you want to use. Here is what I came up with to solve our problem:


// set a threshold 
define('ATTEMPT_THRESHOLD', 90);

/*
 * Implementation of hook_init()
 */

function mymodule_menu_rebuild_init() {
	global $user;
	
	if ((in_array('administrator', $user->roles) || in_array('developer', $user->roles) || $user->uid == 1) && preg_match('/admin/', $_SERVER['REQUEST_URI'])) {
		// build an array pointing at critical administrative paths
		// if any of these does not return a 200, rebuild the menu and clear cache
		$time = time();
		$last_run = variable_get('mymodule_menu_rebuild_last_run', time());
		
		if ($time - $last_run > ATTEMPT_THRESHOLD) {
		
			$url = 'http://'.$_SERVER['HTTP_HOST'];
			$try = array();
			
			$try[] = $url.'/?q=admin/content&user='.$user->name.'&pass='.$user->pass;
			$try[] = $url.'/?q=admin/settings&user='.$user->name.'&pass='.$user->pass;
			$try[] = $url.'/?q=admin/build&user='.$user->name.'&pass='.$user->pass;
			$try[] = $url.'/?q=admin/user&user='.$user->name.'&pass='.$user->pass;
			$try[] = $url.'/?q=admin/reports&user='.$user->name.'&pass='.$user->pass;
			
			foreach ($try as $attempt) {
				$response = drupal_http_request($attempt, array(), 'GET', 0, 3);
				if ($response->code) {
					switch ($response->code) {
						case '200':
							watchdog('mymodule_menu_rebuild', 'Administrative path found. Menu not rebuilt. Response code was @code for user @user', array('@code' => $response->code, '@user' => $user->name), WATCHDOG_NOTICE);
							break;
						case '404':
						case '500':
							cache_clear_all();
							menu_router_build();
							cache_clear_all();
							watchdog('mymodule_menu_rebuild', 'Administrative path not reached. Menu rebuilt. Response code was @code for user @user', array('@code' => $response->code, '@user' => $user->name), WATCHDOG_NOTICE);
							break;
					}
				}
			}
			
			variable_set('mymodule_menu_rebuild_last_run', time());
		}			
	}
}



Maybe not the ultimate solution, but it works for me right now.

===========
read my thoughts

paulhudson’s picture

Hey chaps,

I don't see how the above could work?

The php manual gives the example:

$url = 'http://username:password@hostname/path?arg=value#anchor';

In my test I can only get php drupal_http_request to return a value for $defaults['Authorization'] by using the above format rather than passing the user and pass in the query.

e.g. $url = 'http://'.$user->name.':'.$user->pass.'@hostname/path?arg=value';

result:

Value returned for $defaults['Authorization'] but it still 403 errors.

Am I missing something? Any thoughts would be appreciated.

Paul

paulhudson’s picture

pft.

Turns out I was close with the above. However, Drupal doesn't seem to allow HTTP authentication out of the box.

Use the http://drupal.org/project/httpauth module to enable HTTP authentication and you might need to append '&authenticate' as a query to your URL.

I also couldn't get it working with the MD5 value of $user->pass, I had to enter the password as a plain-text string... HTTP Auth isn't secure so this is a problem!??

So it works with:

1. Enable httpauth module

2.

$url = 'http://username:password@hostname/path?arg=value&authenticate';

not

$url = 'http://'.$user->name.':'.$user->pass.'@hostname/path?arg=value&authenticate';

I know the above post seems to have been answered but I found almost nothing on Google regarding drupal_http_request so I’m posting here to help others and see if I can get some feedback on the method above.

Kind regards,

Paul

kevinquillen’s picture

I'm not sure. I can't get it working either.

===========
read my thoughts