docs: function do_plain(url, opts) {
  	opts = do_args(url, opts);
  	if(opts.redirect_loop_counter === undefined) {
  		opts.redirect_loop_counter = 10;
  	}
  	var buffer;
  	var d = Q.defer();
  	var req = require(opts.protocol).request(opts.url, function(res) {
  		var buffer = "";
  		res.setEncoding('utf8');
  		function collect_chunks(chunk) {
  			buffer += chunk;
  		}
  		res.on('data', collect_chunks);
  		res.once('end', function() {
  
  			res.removeListener('data', collect_chunks);
  
  			var content_type = res.headers['content-type'] || undefined;
  			//debug.log('content_type = ' , content_type);
  			d.resolve( Q.fcall(function() {
  
  				//debug.log('buffer = ', buffer);
  				//debug.log('res.headers = ', res.headers);
  
  				if(res.headers && res.headers['set-cookie']) {
  					_cookies.set(opts.url, res.headers['set-cookie']);
  				}
  
  				if( (res.statusCode >= 301) && (res.statusCode <= 303) ) {
  					if(opts.redirect_loop_counter < 0) {
  						throw new Error('Redirect loop detected');
  					}
  					opts.redirect_loop_counter -= 1;
  					//debug.log('res.statusCode = ', res.statusCode);
  					//debug.log('res.headers.location = ', res.headers.location);
  					return do_plain(res.headers.location, {
  						'method': 'GET',
  						'headers': {
  							'accept': opts.url.headers && opts.url.headers.accept
  						}
  					});
  				}
  				if(!((res.statusCode >= 200) && (res.statusCode < 400))) {
  					throw new HTTPError(res.statusCode, ((content_type === 'application/json') ? JSON.parse(buffer) : buffer) );
  				}
  				return buffer;
  			}) );
  		});
  
  	}).once('error', function(e) {
  		d.reject(new TypeError(''+e));
  	});
  
  	if(opts.body && (url.method !== 'GET')) {
  		buffer = is.string(opts.body) ? opts.body : JSON.stringify(opts.body);
  		//debug.log('Writing buffer = ', buffer);
  		req.end( buffer, 'utf8' );
  	} else {
  		req.end();
  	}
  
  	return d.promise;
  }