Skip to content

adds CloudEvent helloworld to examples, README, and tests #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 58 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,64 @@ in the [Cloud Console][cloud-run-console].
[cloud-run-regions]: https://cloud.google.com/run/docs/locations
[cloud-run-console]: https://console.cloud.google.com/run

## Use CloudEvents

The Functions Framework can unmarshall incoming [CloudEvents][cloud-events]
payloads to a `cloudevent` object. This will be passed as arguments to your
function when it receives a request. Note that your function must use the
cloudevent function signature:

```php
use Google\CloudFunctions\CloudEvent;

function helloCloudEvents(CloudEvent $cloudevent)
{
// Print the whole CloudEvent
$stdout = fopen('php://stdout', 'wb');
fwrite($stdout, $cloudevent);
}
```

You will also need to set the `FUNCTION_SIGNATURE_TYPE` environment
variable to `cloudevent`.

```sh
export FUNCTION_TARGET=helloCloudEvent
export FUNCTION_SIGNATURE_TYPE=cloudevent
php -S localhost:8080 vendor/bin/router.php
```

In a separate tab, make a cURL request in Cloud Event format to your function:

```
curl localhost:8080 \
-H "ce-id: 1234567890" \
-H "ce-source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC" \
-H "ce-specversion: 1.0" \
-H "ce-type: com.google.cloud.pubsub.topic.publish" \
-d '{"foo": "bar"}'
```

Your original process should output the following:

```
CLOUDEVENT metadata:
- id: 1234567890
- source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC
- specversion: 1.0
- type: com.google.cloud.pubsub.topic.publish
- datacontenttype:
- dataschema:
- subject:
- time:
```

**IMPORTANT**: The above tutorials to deploy to a docker container and to
Cloud Run work for CloudEvents as well, as long as `FUNCTION_TARGET` and
`FUNCTION_SIGNATURE_TYPE` are set appropriately.

[cloud-events]: http://cloudevents.io

## Working with PSR-7 HTTP Objects

The first parameter of your function is a `Request` object which implements the
Expand Down Expand Up @@ -237,30 +295,6 @@ You can configure the Functions Framework using the environment variables shown
| `FUNCTION_SOURCE` | The name of the file containing the source code for your function to load. Default: **`index.php`** (if it exists)
| `FUNCTION_SIGNATURE_TYPE` | The signature used when writing your function. Controls unmarshalling rules and determines which arguments are used to invoke your function. Can be either `http`, `event`, or `cloudevent`. Default: **`http`**

# Enable CloudEvents

The Functions Framework can unmarshall incoming [CloudEvents](http://cloudevents.io)
payloads to a `cloudevent` object. This will be passed as arguments to your function when it
receives a request. Note that your function must use the cloudevent-style function
signature:

```php
use Google\CloudFunctions\CloudEvent;

function helloCloudEvents(CloudEvent $cloudevent)
{
// Get a single property
printf('id: %s', $cloudevent->getId());
printf('type: %s', $cloudevent->getType());

// Print the whole CloudEvent
print($cloudevent);
}
```

To enable automatic unmarshalling, set the `FUNCTION_SIGNATURE_TYPE` environment
variable to `cloudevent`.

# Contributing

Contributions to this library are welcome and encouraged. See
Expand Down
2 changes: 1 addition & 1 deletion examples/hello/composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"require": {
"google/cloud-functions-framework": "^0.3"
"google/cloud-functions-framework": "dev-master as 0.6.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this downloading the latest code available directly from GitHub? (i.e. disabling version pinning)

(This is a beta version, so I'm willing to allow it for now - but we definitely shouldn't do this once we release publicly.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's only for testing. I will change it back once a version is tagged

}
}
20 changes: 20 additions & 0 deletions examples/hello/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,30 @@
* limitations under the License.
*/

/**
* To use this, set the following environment variables:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can these also be specified as command-line args?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no CLI for php at the moment

* FUNCTION_TARGET=helloHttp
* FUNCTION_EVENT_TYPE=http
*/

use Psr\Http\Message\ServerRequestInterface;

function helloHttp(ServerRequestInterface $request)
{
return sprintf("Hello %s from PHP HTTP function!" . PHP_EOL,
$request->getQueryParams()['name'] ?? 'World');
}

/**
* To use this, set the following environment variables:
* FUNCTION_TARGET=helloCloudEvent
* FUNCTION_EVENT_TYPE=cloudevent
*/

use Google\CloudFunctions\CloudEvent;

function helloCloudEvent(CloudEvent $cloudevent)
{
$stdout = fopen('php://stdout', 'wb');
fwrite($stdout, $cloudevent);
}
56 changes: 50 additions & 6 deletions tests/exampleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,77 @@ public static function setUpBeforeClass(): void
$cmd = sprintf('docker build %s -t %s', $exampleDir, self::$imageId);

passthru($cmd, $output);
}

public function testHttp(): void
{
$cmd = 'docker run -d -p 8080:8080 '
. '-e FUNCTION_TARGET=helloHttp '
. self::$imageId;

exec($cmd, $output);
self::$containerId = $output[0];

// Tests fail if we do not wait before sending requests in
sleep(1);
}

public function testIndex(): void
{
exec('curl -v http://localhost:8080', $output);
$this->assertContains('Hello World from PHP HTTP function!', $output);
}

public function testIndexWithQuery(): void
{
exec('curl -v http://localhost:8080?name=Foo', $output);
$this->assertContains('Hello Foo from PHP HTTP function!', $output);

passthru('docker rm -f ' . self::$containerId);
self::$containerId = null;
}

public function testCloudEvent(): void
{
$cmd = 'docker run -d -t -p 8080:8080 '
. '-e FUNCTION_TARGET=helloCloudEvent '
. '-e FUNCTION_SIGNATURE_TYPE=cloudevent '
. self::$imageId;

exec($cmd, $output);
self::$containerId = $output[0];

// Tests fail if we do not wait before sending requests in
sleep(1);

$curl = 'curl -v localhost:8080 '
. '-H "ce-id: 1234567890" '
. ' -H "ce-source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC" '
. '-H "ce-specversion: 1.0" '
. '-H "ce-type: com.google.cloud.pubsub.topic.publish" '
. '-d \'{"foo": "bar"}\' &> /dev/stdout';

exec($curl);

exec('docker logs ' . self::$containerId, $output);

$outputAsString = implode("\n", $output);
$this->assertStringContainsString('- id: 1234567890', $outputAsString);
$this->assertStringContainsString(
'- type: com.google.cloud.pubsub.topic.publish',
$outputAsString
);
$this->assertStringContainsString(
'- source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC"',
$outputAsString
);

passthru('docker rm -f ' . self::$containerId);
self::$containerId = null;
}

public static function tearDownAfterClass(): void
{
// If a test failed before it could delete its container
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: would it be better to have a single "clean up test resources" comment?

(Or maybe even delete these comments outright, if you're of the "code should be self-documenting" philosophy.)

if (self::$containerId) {
passthru('docker rm -f ' . self::$containerId);
}
// Remove the test image
if (self::$imageId) {
passthru('docker rmi -f ' . self::$imageId);
}
}
Expand Down