Issue #1869002 by mikeytown2: Set the default domain_connections to 2 instead of 8.
[project/httprl.git] / README.txt
1
2 ------------------------------------------------
3 HTTP PARALLEL REQUEST & THREADING LIBRARY MODULE
4 ------------------------------------------------
5
6
7 CONTENTS OF THIS FILE
8 ---------------------
9
10  * About HTTPRL
11  * Requirements
12  * Configuration
13  * API Overview
14  * Technical Details
15  * Code Examples
16
17
18 ABOUT HTTPRL
19 ------------
20
21 http://drupal.org/project/httprl
22
23 HTTPRL is a flexible and powerful HTTP client implementation. Correctly handles
24 GET, POST, PUT or any other HTTP requests & the sending of data. Issue blocking
25 or non-blocking requests in parallel. Set timeouts, max simultaneous connection
26 limits, chunk size, and max redirects to follow. Can handle data with
27 content-encoding and transfer-encoding headers set. Correctly follows
28 redirects. Option to forward the referrer when a redirect is found. Cookie
29 extraction and parsing into key value pairs. Can multipart encode data so files
30 can easily be sent in a HTTP request.
31
32
33 REQUIREMENTS
34 ------------
35
36 Requires PHP 5. The following functions must be available on the server:
37  * stream_socket_client
38  * stream_select
39  * stream_set_blocking
40  * stream_get_meta_data
41  * stream_socket_get_name
42 Some hosting providers disable these functions; but they do come standard with
43 PHP 5.
44
45
46 CONFIGURATION
47 -------------
48
49 Settings page is located at:
50 6.x: admin/settings/httprl
51 7.x: admin/config/development/httprl
52
53  * IP Address to send all self server requests to. If left blank it will use the
54    same server as the request. If set to -1 it will use the host name instead of
55    an IP address. This controls the output of httprl_build_url_self().
56
57
58 API OVERVIEW
59 ------------
60
61 Issue HTTP Requests:
62 httprl_build_url_self()
63  - Helper function to build an URL for asynchronous requests to self.
64 httprl_request()
65  - Queue up a HTTP request in httprl_send_request().
66 httprl_send_request()
67  - Perform many HTTP requests.
68
69 Create and use a thread:
70 httprl_queue_background_callback()
71  - Queue a special HTTP request (used for threading) in httprl_send_request().
72
73 Other Functions:
74 httprl_background_processing()
75  - Output text, close connection, continue processing in the background.
76 httprl_strlen()
77  - Get the length of a string in bytes.
78 httprl_glue_url()
79  - Alt to http_build_url().
80 httprl_get_server_schema()
81  - Return the server schema (http or https).
82 httprl_pr()
83  - Pretty print data.
84 httprl_fast403()
85  - Issue a 403 and exit.
86
87
88 TECHNICAL DETAILS
89 -----------------
90
91 Using stream_select() HTTPRL will send http requests out in parallel. These
92 requests can be made in a blocking or non-blocking way. Blocking will wait for
93 the http response; Non-Blocking will close the connection not waiting for the
94 response back. The API for httprl is similar to the Drupal 7 version of
95 drupal_http_request().
96
97 HTTPRL can be used independent of drupal. For basic operations it doesn't
98 require any built in drupal functions.
99
100
101 CODE EXAMPLES
102 -------------
103
104 **Simple HTTP**
105
106 Request http://drupal.org/.
107
108     <?php
109     // Queue up the request.
110     httprl_request('http://drupal.org/');
111     // Execute request.
112     $request = httprl_send_request();
113
114     // Echo out the results.
115     echo httprl_pr($request);
116     ?>
117
118
119 Request this servers own front page & the node page.
120
121     <?php
122     // Build URL to point to front page of this server.
123     $url_front = httprl_build_url_self();
124     // Build URL to point to /node on this server.
125     $url_node = httprl_build_url_self('node');
126     // Queue up the requests.
127     httprl_request($url_front);
128     httprl_request($url_node);
129     // Execute requests.
130     $request = httprl_send_request();
131
132     // Echo out the results.
133     echo httprl_pr($request);
134     ?>
135
136
137 **Non Blocking HTTP Operations**
138
139 Request 10 URLs in a non blocking manner on this server. Checkout watchdog as
140 this should generate 10 404s and the $request object won't contain much info.
141
142     <?php
143     // Set the blocking mode.
144     $options = array(
145       'blocking' => FALSE,
146     );
147     // Queue up the requests.
148     $max = 10;
149     for ($i=1; $i <= $max; $i++) {
150       // Build URL to a page that doesn't exist.
151       $url = httprl_build_url_self('asdf-asdf-asdf-' . $i);
152       httprl_request($url, $options);
153     }
154     // Execute requests.
155     $request = httprl_send_request();
156
157     // Echo out the results.
158     echo httprl_pr($request);
159     ?>
160
161
162 Request 10 URLs in a non blocking manner with one httprl_request() call. These
163 URLs will all have the same options.
164
165     <?php
166     // Set the blocking mode.
167     $options = array(
168       'method' => 'HEAD',
169       'blocking' => FALSE,
170     );
171     // Queue up the requests.
172     $max = 10;
173     $urls = array();
174     for ($i=1; $i <= $max; $i++) {
175       // Build URL to a page that doesn't exist.
176       $urls[] = httprl_build_url_self('asdf-asdf-asdf-' . $i);
177     }
178     // Queue up the requests.
179     httprl_request($urls, $options);
180     // Execute requests.
181     $request = httprl_send_request();
182
183     // Echo out the results.
184     echo httprl_pr($request);
185     ?>
186
187
188 Request 1000 URLs in a non blocking manner with one httprl_request() call. These
189 URLs will all have the same options. This will saturate the server and any
190 connections that couldn't be made will be dropped.
191
192     <?php
193     // Set the blocking mode.
194     $options = array(
195       'method' => 'HEAD',
196       'blocking' => FALSE,
197     );
198     // Queue up the requests.
199     $max = 1000;
200     $urls = array();
201     for ($i=1; $i <= $max; $i++) {
202       // Build URL to a page that doesn't exist.
203       $urls[] = httprl_build_url_self('asdf-asdf-asdf-' . $i);
204     }
205     // Queue up the requests.
206     httprl_request($urls, $options);
207     // Execute requests.
208     $request = httprl_send_request();
209
210     // Echo out the results.
211     echo httprl_pr($request);
212     ?>
213
214
215 Request 1000 URLs in a non blocking manner with one httprl_request() call. These
216 URLs will all have the same options. This will saturate the server. All 1000
217 requests will eventually hit the server due to it waiting for the connection to
218 be established; `async_connect` is FALSE.
219
220     <?php
221     // Set the blocking mode.
222     $options = array(
223       'method' => 'HEAD',
224       'blocking' => FALSE,
225       'async_connect' => FALSE,
226     );
227     // Queue up the requests.
228     $max = 1000;
229     $urls = array();
230     for ($i=1; $i <= $max; $i++) {
231       // Build URL to a page that doesn't exist.
232       $urls[] = httprl_build_url_self('asdf-asdf-asdf-' . $i);
233     }
234     // Queue up the requests.
235     httprl_request($urls, $options);
236     // Execute requests.
237     $request = httprl_send_request();
238
239     // Echo out the results.
240     echo httprl_pr($request);
241     ?>
242
243
244 **HTTP Operations and Callbacks**
245
246 Use a callback in the event loop to do processing on the request. In this case
247 we are going to use httprl_pr() as the callback function.
248
249     <?php
250     // Setup return variable.
251     $x = '';
252     // Setup options array.
253     $options = array(
254       'method' => 'HEAD',
255       'callback' => array(
256         array(
257           'function' => 'httprl_pr',
258           'return' => &$x,
259         ),
260       ),
261     );
262     // Build URL to point to front page of this server.
263     $url_front = httprl_build_url_self();
264     // Queue up the request.
265     httprl_request($url_front, $options);
266     // Execute request.
267     $request = httprl_send_request();
268
269     // Echo returned value from function callback.
270     echo $x;
271     ?>
272
273
274 Use a background callback in the event loop to do processing on the request.
275 In this case we are going to use httprl_pr() as the callback function. A
276 background callback creates a new thread to run this function in.
277
278     <?php
279     // Setup return variable.
280     $x = '';
281     // Setup options array.
282     $options = array(
283       'method' => 'HEAD',
284       'background_callback' => array(
285         array(
286           'function' => 'httprl_pr',
287           'return' => &$x,
288         ),
289       ),
290     );
291     // Build URL to point to front page of this server.
292     $url_front = httprl_build_url_self();
293     // Queue up the request.
294     httprl_request($url_front, $options);
295     // Execute request.
296     $request = httprl_send_request();
297
298     // Echo returned value from function callback.
299     echo $x;
300     ?>
301
302
303 Use a background callback in the event loop to do processing on the request.
304 In this case we are going to use print_r() as the callback function. A
305 background callback creates a new thread to run this function in. The first
306 argument passed in is the request object, the FALSE tells print_r to echo out
307 instead of returning a value.
308
309     <?php
310     // Setup return & print variable.
311     $x = '';
312     $y = '';
313     // Setup options array.
314     $options = array(
315       'method' => 'HEAD',
316       'background_callback' => array(
317         array(
318           'function' => 'print_r',
319           'return' => &$x,
320           'printed' => &$y,
321         ),
322         FALSE,
323       ),
324     );
325     // Build URL to point to front page of this server.
326     $url_front = httprl_build_url_self();
327     // Queue up the request.
328     httprl_request($url_front, $options);
329     // Execute request.
330     $request = httprl_send_request();
331
332     // Echo what was returned and printed from function callback.
333     echo $x . "<br />\n";
334     echo $y;
335     ?>
336
337
338 **More Advanced HTTP Operations**
339
340 Hit 4 different URLs, Using at least 2 that has a status code of 200 and
341 erroring out the others that didn't return fast. Data is truncated as well.
342
343     <?php
344     // Array of URLs to get.
345     $urls = array(
346       'http://google.com/',
347       'http://bing.com/',
348       'http://yahoo.com/',
349       'http://www.duckduckgo.com/',
350       'http://www.drupal.org/',
351     );
352
353     // Process list of URLs.
354     $options = array(
355       'alter_all_streams_function' => 'need_two_good_results',
356       'callback' => array(array('function' => 'limit_data_size')),
357     );
358     // Queue up the requests.
359     httprl_request($urls, $options);
360
361     // Execute requests.
362     $requests = httprl_send_request();
363
364     // Print what was done.
365     echo httprl_pr($requests);
366
367     function need_two_good_results($id, &$responses) {
368       static $counter = 0;
369       foreach ($responses as $id => &$result) {
370         // Skip if we got a 200.
371         if ($result->code == 200) {
372           $counter += 1;
373           continue;
374         }
375         if ($result->status == 'Done.') {
376           continue;
377         }
378
379         if ($counter >= 2) {
380           // Set the code to request was aborted.
381           $result->code = HTTPRL_REQUEST_ABORTED;
382           $result->error = 'Software caused connection abort.';
383           // Set status to done and set timeout.
384           $result->status = 'Done.';
385           $result->options['timeout'] -= $result->running_time;
386
387           // Close the file pointer and remove from the stream from the array.
388           fclose($result->fp);
389           unset($result->fp);
390         }
391       }
392     }
393
394     function limit_data_size(&$result) {
395       // Only use the first and last 256 characters in the data array.
396       $result->data = substr($result->data, 0, 256) . "\n\n ... \n\n" . substr($result->data, strlen($result->data)-256);
397     }
398     ?>
399
400
401 Send 2 files in one field via a POST request.
402
403     <?php
404     // Send request to front page.
405     $url_front = httprl_build_url_self();
406     // Set options.
407     $options = array(
408       'method' => 'POST',
409       'data' => array(
410         'x' => 1,
411         'y' => 2,
412         'z' => 3,
413         'files' => array(
414           'core_js' => array(
415             'misc/form.js',
416             'misc/batch.js',
417           ),
418         ),
419       ),
420     );
421     // Queue up the request.
422     httprl_request($url_front, $options);
423     // Execute request.
424     $request = httprl_send_request();
425     // Echo what was returned.
426     echo httprl_pr($request);
427     ?>
428
429
430 **Threading Examples**
431
432 Use 2 threads to load up 4 different nodes.
433
434     <?php
435     // List of nodes to load; 241-244.
436     $nodes = array(241 => '', 242 => '', 243 => '', 244 => '');
437     foreach ($nodes as $nid => &$node) {
438       // Setup callback options array.
439       $callback_options = array(
440         array(
441           'function' => 'node_load',
442           'return' => &$node,
443           // Setup options array.
444           'options' => array(
445             'domain_connections' => 2, // Only use 2 threads for this request.
446           ),
447         ),
448         $nid,
449       );
450       // Queue up the request.
451       httprl_queue_background_callback($callback_options);
452     }
453     // Execute request.
454     httprl_send_request();
455
456     // Echo what was returned.
457     echo httprl_pr($nodes);
458     ?>
459
460
461 Run a function in the background. Notice that there is no return or printed key
462 in the callback options.
463
464     <?php
465     // Setup callback options array; call watchdog in the background.
466     $callback_options = array(
467       array(
468         'function' => 'watchdog',
469       ),
470       'httprl-test', 'background watchdog call done', array(), WATCHDOG_DEBUG,
471     );
472     // Queue up the request.
473     httprl_queue_background_callback($callback_options);
474
475     // Execute request.
476     httprl_send_request();
477     ?>
478
479
480 Pass by reference example. Example is D7 only; pass by reference works in
481 D6 & D7.
482
483     <?php
484     // Code from system_rebuild_module_data().
485     $modules = _system_rebuild_module_data();
486     ksort($modules);
487
488     // Show first module before running system_get_files_database().
489     echo httprl_pr(current($modules));
490
491     $callback_options = array(
492       array(
493         'function' => 'system_get_files_database',
494         'return' => '',
495       ),
496       &$modules, 'module'
497     );
498     httprl_queue_background_callback($callback_options);
499
500     // Execute requests.
501     httprl_send_request();
502
503     // Show first module after running system_get_files_database().
504     echo httprl_pr(current($modules));
505     ?>
506
507
508 Get 2 results from 2 different queries at the hook_boot bootstrap level in D6.
509
510     <?php
511     // Run 2 queries and get the result.
512     $x = db_result(db_query_range("SELECT filename FROM {system} ORDER BY filename ASC", 0, 1));
513     $y = db_result(db_query_range("SELECT filename FROM {system} ORDER BY filename DESC", 0, 1));
514     echo $x . "<br \>\n" . $y . "<br \>\n";
515     unset($x, $y);
516
517
518     // Run above 2 queries and get the result via a background callback.
519     $args = array(
520       // First query.
521       array(
522         'type' => 'function',
523         'call' => 'db_query_range',
524         'args' => array('SELECT filename FROM {system} ORDER BY filename ASC', 0, 1),
525       ),
526       array(
527         'type' => 'function',
528         'call' => 'db_result',
529         'args' => array('last' => NULL),
530         'return' => &$x,
531       ),
532
533       // Second Query.
534       array(
535         'type' => 'function',
536         'call' => 'db_query_range',
537         'args' => array('SELECT filename FROM {system} ORDER BY filename DESC', 0, 1),
538       ),
539       array(
540         'type' => 'function',
541         'call' => 'db_result',
542         'args' => array('last' => NULL),
543         'return' => &$y,
544       ),
545     );
546     $callback_options = array(array('return' => ''), &$args);
547     // Queue up the request.
548     httprl_queue_background_callback($callback_options);
549     // Execute request.
550     httprl_send_request();
551
552     // Echo what was returned.
553     echo httprl_pr($x, $y);
554     ?>
555
556
557 Get 2 results from 2 different queries at the hook_boot bootstrap level in D7.
558
559     <?php
560     $x = db_select('system', 's')
561       ->fields('s', array('filename'))
562       ->orderBy('filename', 'ASC')
563       ->range(0, 1)
564       ->execute()
565       ->fetchField();
566     $y = db_select('system', 's')
567       ->fields('s', array('filename'))
568       ->orderBy('filename', 'DESC')
569       ->range(0, 1)
570       ->execute()
571       ->fetchField();
572     echo $x . "<br \>\n" . $y . "<br \>\n";
573     unset($x, $y);
574
575     // Run above 2 queries and get the result via a background callback.
576     $args = array(
577       // First query.
578       array(
579         'type' => 'function',
580         'call' => 'db_select',
581         'args' => array('system', 's',),
582       ),
583       array(
584         'type' => 'method',
585         'call' => 'fields',
586         'args' => array('s', array('filename')),
587       ),
588       array(
589         'type' => 'method',
590         'call' => 'orderBy',
591         'args' => array('filename', 'ASC'),
592       ),
593       array(
594         'type' => 'method',
595         'call' => 'range',
596         'args' => array(0, 1),
597       ),
598       array(
599         'type' => 'method',
600         'call' => 'execute',
601         'args' => array(),
602       ),
603       array(
604         'type' => 'method',
605         'call' => 'fetchField',
606         'args' => array(),
607         'return' => &$x,
608       ),
609
610       // Second Query.
611       array(
612         'type' => 'function',
613         'call' => 'db_select',
614         'args' => array('system', 's',),
615       ),
616       array(
617         'type' => 'method',
618         'call' => 'fields',
619         'args' => array('s', array('filename')),
620       ),
621       array(
622         'type' => 'method',
623         'call' => 'orderBy',
624         'args' => array('filename', 'DESC'),
625       ),
626       array(
627         'type' => 'method',
628         'call' => 'range',
629         'args' => array(0, 1),
630       ),
631       array(
632         'type' => 'method',
633         'call' => 'execute',
634         'args' => array(),
635       ),
636       array(
637         'type' => 'method',
638         'call' => 'fetchField',
639         'args' => array(),
640         'return' => &$y,
641       ),
642     );
643     $callback_options = array(array('return' => ''), &$args);
644     // Queue up the request.
645     httprl_queue_background_callback($callback_options);
646     // Execute request.
647     httprl_send_request();
648
649     // Echo what was returned.
650     echo httprl_pr($x, $y);
651     ?>
652
653
654 Run a cache clear at the DRUPAL_BOOTSTRAP_FULL level as the current user in a
655 non blocking background request.
656
657     <?php
658     // Normal way to do this.
659     drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
660     module_load_include('inc', 'system', 'system.admin');
661     system_clear_cache_submit();
662
663
664     // How to do it in a non blocking background request.
665     $args = array(
666       array(
667         'type' => 'function',
668         'call' => 'drupal_bootstrap',
669         'args' => array(DRUPAL_BOOTSTRAP_FULL),
670       ),
671       array(
672         'type' => 'function',
673         'call' => 'module_load_include',
674         'args' => array('inc', 'system', 'system.admin'),
675       ),
676       array(
677         'type' => 'function',
678         'call' => 'system_clear_cache_submit',
679         'args' => array('', ''),
680       ),
681       array(
682         'type' => 'function',
683         'call' => 'watchdog',
684         'args' => array('httprl-test', 'background cache clear done', array(), WATCHDOG_DEBUG),
685       ),
686     );
687
688     // Pass the current session to the sub request.
689     if (!empty($_COOKIE[session_name()])) {
690       $options = array('headers' => array('Cookie' => session_name() . '=' . $_COOKIE[session_name()] . ';'));
691     }
692     else {
693       $options = array();
694     }
695     $callback_options = array(array('options' => $options), &$args);
696
697     // Queue up the request.
698     httprl_queue_background_callback($callback_options);
699     // Execute request.
700     httprl_send_request();
701     ?>
702
703
704 print 'My Text'; cut the connection by sending the data over the wire and do
705 processing in the background.
706
707     <?php
708     httprl_background_processing('My Text');
709     // Everything after this point does not affect page load time.
710     sleep(5);
711     echo 'You should not see this text';
712     ?>