Skip to content

Commit 314fb0b

Browse files
committed
adds http examples using curl, curlite, and guzzle (GoogleCloudPlatform#101)
* adds http examples using curl, curlite, and guzzle * adds README
1 parent 9246da4 commit 314fb0b

File tree

7 files changed

+231
-51
lines changed

7 files changed

+231
-51
lines changed

appengine/standard/http/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# HTTP Requests & Google App Engine
2+
3+
This sample application demonstrates how to make [HTTP Requests with Google App Engine](https://cloud.google.com/appengine/docs/php/outbound-requests).
4+
5+
## Setup
6+
7+
- Install [`composer`](https://getcomposer.org)
8+
- Install dependencies by running:
9+
10+
```sh
11+
composer install
12+
```
13+
14+
- Install the [Google Cloud SDK](https://developers.google.com/cloud/sdk/).
15+
16+
## Deploy to App Engine
17+
18+
**Run Locally**
19+
20+
Run the sample with [`dev_appserver.py`](https://cloud.google.com/appengine/docs/php/tools/using-local-server):
21+
22+
```
23+
cd /path/to/php-docs-samples/appengine/standard/http
24+
dev_appserver.py .
25+
```
26+
27+
Now browse to `http://localhost:8080` to view the sample.
28+
29+
**Deploy with gcloud**
30+
31+
```
32+
gcloud config set project YOUR_PROJECT_ID
33+
gcloud preview app deploy
34+
gcloud preview app browse
35+
```
36+
37+
The last command will open `https://{YOUR_PROJECT_ID}.appspot.com/`
38+
in your browser.
39+
40+
## Using the App
41+
42+
This app shows you how to make http requests in Google App Engine. To use cURL,
43+
modify the `php.ini` file in the root of this project and uncomment one of the
44+
valid cURL extensions. [Read our documentation] to understand the difference
45+
between using cURL and cURLite.

appengine/standard/http/app.php

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,92 @@
3030
return $twig->render('http.html.twig');
3131
});
3232

33-
$app->post('/http_request', function () use ($app) {
33+
$app->post('/request/file', function () use ($app) {
3434
/** @var Twig_Environment $twig */
3535
$twig = $app['twig'];
3636

3737
# [START http_bin]
38+
$url = 'http://httpbin.org/post?query=update';
3839
$data = ['data' => 'this', 'data2' => 'that'];
39-
$postData = http_build_query($data);
40+
$headers = "accept: */*\r\n" .
41+
"Content-Type: application/x-www-form-urlencoded\r\n" .
42+
"Custom-Header: custom-value\r\n" .
43+
"Custom-Header-Two: custom-value-2\r\n";
44+
4045
$context = [
4146
'http' => [
4247
'method' => 'POST',
43-
'header' => "accept: */*\r\n" .
44-
"content-type: application/x-www-form-urlencoded\r\n" .
45-
"custom-header: custom-value\r\n" .
46-
"custom-header-two: custom-value-2\r\n",
47-
'content' => $postData
48+
'header' => $headers,
49+
'content' => http_build_query($data),
4850
]
4951
];
5052
$context = stream_context_create($context);
51-
$result = file_get_contents('http://httpbin.org/post?query=update', false, $context);
53+
$result = file_get_contents($url, false, $context);
5254
# [END http_bin]
53-
return $twig->render('http.html.twig', ['result' => $result]);
55+
return $twig->render('http.html.twig', ['file_result' => $result]);
56+
});
57+
58+
$app->post('/request/curl', function () use ($app) {
59+
/** @var Twig_Environment $twig */
60+
$twig = $app['twig'];
61+
62+
// make sure one of the extensions is installed
63+
if (!function_exists('curl_init')) {
64+
throw new \Exception('You must enable cURL or cURLite in php.ini');
65+
}
66+
67+
# [START curl_request]
68+
$url = 'http://httpbin.org/post?query=update';
69+
$data = ['data' => 'this', 'data2' => 'that'];
70+
$headers = [
71+
'Accept: */*',
72+
'Content-Type: application/x-www-form-urlencoded',
73+
'Custom-Header: custom-value',
74+
'Custom-Header-Two: custom-value-2'
75+
];
76+
77+
// open connection
78+
$ch = curl_init();
79+
80+
// set curl options
81+
$options = [
82+
CURLOPT_URL => $url,
83+
CURLOPT_POST => count($data),
84+
CURLOPT_POSTFIELDS => http_build_query($data),
85+
CURLOPT_HTTPHEADER => $headers,
86+
CURLOPT_RETURNTRANSFER => true,
87+
];
88+
curl_setopt_array($ch, $options);
89+
90+
// execute
91+
$result = curl_exec($ch);
92+
93+
// close connection
94+
curl_close($ch);
95+
# [END curl_request]
96+
return $twig->render('http.html.twig', ['curl_result' => $result]);
97+
});
98+
99+
$app->post('/request/guzzle', function () use ($app) {
100+
/** @var Twig_Environment $twig */
101+
$twig = $app['twig'];
102+
103+
# [START guzzle_request]
104+
$url = 'http://httpbin.org/post?query=update';
105+
$data = ['data' => 'this', 'data2' => 'that'];
106+
$headers = [
107+
'Accept' => '*/*',
108+
'Content-Type' => 'application/x-www-form-urlencoded',
109+
'Custom-Header' => 'custom-value',
110+
'Custom-Header-Two' => 'custom-value',
111+
];
112+
113+
$guzzle = new GuzzleHttp\Client;
114+
$request = new GuzzleHttp\Psr7\Request('POST', $url, $headers, http_build_query($data));
115+
$result = $guzzle->send($request);
116+
# [END guzzle_request]
117+
118+
return $twig->render('http.html.twig', ['guzzle_result' => $result->getBody()]);
54119
});
55120

56121
return $app;

appengine/standard/http/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"require": {
33
"twig/twig": " ~1.8|~2.0",
44
"symfony/twig-bridge": " ~2.7|3.0.*",
5-
"silex/silex": " ^1.3"
5+
"silex/silex": " ^1.3",
6+
"guzzlehttp/guzzle": "^6.2"
67
},
78
"require-dev": {
89
"symfony/browser-kit": "^3.0"

appengine/standard/http/composer.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

appengine/standard/http/http.html.twig

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,40 @@
77
<body>
88
<h1>Http Example</h1>
99

10-
<form action="/http_request" method="post">
11-
<input type="submit" value="Make an HTTP Request" />
12-
</form>
10+
<div>
11+
<h3>Request with <code>file_get_contents</code></h3>
1312

14-
{% if result is defined %}
15-
<pre>{{ result }}</pre>
16-
{% endif %}
13+
<form action="/request/file" method="post">
14+
<input type="submit" value="Make an HTTP Request" />
15+
</form>
16+
17+
{% if file_result is defined %}
18+
<pre>{{ file_result }}</pre>
19+
{% endif %}
20+
</div>
21+
22+
<div>
23+
<h3>Request with Curl</h3>
24+
25+
<form action="/request/curl" method="post">
26+
<input type="submit" value="Make an HTTP Request" />
27+
</form>
28+
29+
{% if curl_result is defined %}
30+
<pre>{{ curl_result }}</pre>
31+
{% endif %}
32+
</div>
33+
34+
<div>
35+
<h3>Request with Guzzle</h3>
36+
37+
<form action="/request/guzzle" method="post">
38+
<input type="submit" value="Make an HTTP Request" />
39+
</form>
40+
41+
{% if guzzle_result is defined %}
42+
<pre>{{ guzzle_result }}</pre>
43+
{% endif %}
44+
</div>
1745
</body>
1846
</html>

appengine/standard/http/php.ini

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; App Engine Standard supports both cURL and cURLite.
2+
; Both cannot be enabled at the same time.
3+
; @see https://cloud.google.com/appengine/docs/php/runtime#PHP_cURL_support
4+
5+
; To enable cURLite, uncomment the following line:
6+
;
7+
;google_app_engine.enable_curl_lite = "true"
8+
9+
; To enable cURL, uncomment the following line:
10+
;
11+
;extension = "curl.so"

appengine/standard/http/test/httpTest.php

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,44 @@
1818

1919
class httpTest extends WebTestCase
2020
{
21+
private $expected;
22+
23+
public function setup()
24+
{
25+
parent::setup();
26+
27+
$this->expected = '{
28+
"args": {
29+
"query": "update"
30+
},
31+
"data": "",
32+
"files": {},
33+
"form": {
34+
"data": "this",
35+
"data2": "that"
36+
},
37+
"headers": {
38+
"Accept": "*/*",
39+
"Content-Length": "20",
40+
"Content-Type": "application/x-www-form-urlencoded",
41+
"Custom-Header": "custom-value",
42+
"Custom-Header-Two": "custom-value-2",
43+
"Host": "httpbin.org"
44+
},
45+
"json": null,
46+
"origin": "ORIGIN_IP_ADDRESS",
47+
"url": "http://httpbin.org/post?query=update"
48+
}';
49+
// fix issue where there are trailing spaces after the commas
50+
$this->expected = str_replace(',', ', ', $this->expected);
51+
52+
// escape for regex
53+
$this->expected = '#' . preg_quote(htmlspecialchars($this->expected), '#') . '#';
54+
55+
// allow for any IP address
56+
$this->expected = str_replace('ORIGIN_IP_ADDRESS', '.*', $this->expected);
57+
}
58+
2159
public function createApplication()
2260
{
2361
$app = require __DIR__ . '/../app.php';
@@ -41,47 +79,39 @@ public function testHome()
4179
$this->assertTrue($client->getResponse()->isOk());
4280
}
4381

44-
public function testHttpRequest()
82+
public function testFileRequest()
4583
{
4684
$client = $this->createClient();
4785

48-
$crawler = $client->request('POST', '/http_request');
86+
$crawler = $client->request('POST', '/request/file');
4987

5088
$this->assertTrue($client->getResponse()->isOk());
51-
$result = <<<EOF
52-
{
53-
"args": {
54-
"query": "update"
55-
},
56-
"data": "",
57-
"files": {},
58-
"form": {
59-
"data": "this",
60-
"data2": "that"
61-
},
62-
"headers": {
63-
"Accept": "*/*",
64-
"Content-Length": "20",
65-
"Content-Type": "application/x-www-form-urlencoded",
66-
"Custom-Header": "custom-value",
67-
"Custom-Header-Two": "custom-value-2",
68-
"Host": "httpbin.org"
69-
},
70-
"json": null,
71-
"origin": "ORIGIN_IP_ADDRESS",
72-
"url": "http://httpbin.org/post?query=update"
73-
}
74-
EOF;
75-
// fix issue where there are trailing spaces after the commas
76-
$result = str_replace(',', ', ', $result);
7789

78-
// escape for regex
79-
$result = '#' . preg_quote(htmlspecialchars($result), '#') . '#';
90+
// test the regex exists
91+
$this->assertRegExp($this->expected, (string) $client->getResponse());
92+
}
8093

81-
// allow for any IP address
82-
$result = str_replace('ORIGIN_IP_ADDRESS', '.*', $result);
94+
public function testCurlRequest()
95+
{
96+
$client = $this->createClient();
97+
98+
$crawler = $client->request('POST', '/request/curl');
99+
100+
$this->assertTrue($client->getResponse()->isOk());
101+
102+
// test the regex exists
103+
$this->assertRegExp($this->expected, (string) $client->getResponse());
104+
}
105+
106+
public function testGuzzleRequest()
107+
{
108+
$client = $this->createClient();
109+
110+
$crawler = $client->request('POST', '/request/curl');
111+
112+
$this->assertTrue($client->getResponse()->isOk());
83113

84114
// test the regex exists
85-
$this->assertRegExp($result, (string) $client->getResponse());
115+
$this->assertRegExp($this->expected, (string) $client->getResponse());
86116
}
87117
}

0 commit comments

Comments
 (0)