Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
13 changes: 13 additions & 0 deletions net/grpc/web/echo_example/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's skip the example code for now. As we probably want to use the same proto defined in grpc report instead of using echo.prot here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All example related files are removed.

"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"require": {
"google/protobuf": "^v3.3.0"
},
"autoload": {
"psr-4": {
"": "./",
"Grpc\\": "../grpc/src/lib"
}
}
}
89 changes: 89 additions & 0 deletions net/grpc/web/echo_example/echo.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
syntax = "proto3";

package grpc.gateway.testing;

message Empty {
}

message EchoRequest {
string message = 1;
}

message EchoResponse {
string message = 1;
int32 message_count = 2;
}

// Request type for server side streaming echo.
message ServerStreamingEchoRequest {
// Message string for server streaming request.
string message = 1;

// The total number of messages to be generated before the server
// closes the stream; default is 10.
int32 message_count = 2;

// The interval (ms) between two server messages. The server implementation
// may enforce some minimum interval (e.g. 100ms) to avoid message overflow.
int32 message_interval = 3;
}

// Response type for server streaming response.
message ServerStreamingEchoResponse {
// Response message.
string message = 1;
}

// Request type for client side streaming echo.
message ClientStreamingEchoRequest {
// A special value "" indicates that there's no further messages.
string message = 1;
}

// Response type for client side streaming echo.
message ClientStreamingEchoResponse {
// Total number of client messages that have been received.
int32 message_count = 1;
}

// A simple echo service.
service EchoService {
// One request followed by one response
// The server returns the client message as-is.
rpc Echo(EchoRequest) returns (EchoResponse);

// Sends back abort status.
rpc EchoAbort(EchoRequest) returns (EchoResponse) {
};

// One empty request, ZERO processing, followed by one empty response
// (minimum effort to do message serialization).
rpc NoOp(Empty) returns (Empty);

// One request followed by a sequence of responses (streamed download).
// The server will return the same client message repeatedly.
rpc ServerStreamingEcho(ServerStreamingEchoRequest)
returns (stream ServerStreamingEchoResponse);

// One request followed by a sequence of responses (streamed download).
// The server abort directly.
rpc ServerStreamingEchoAbort(ServerStreamingEchoRequest)
returns (stream ServerStreamingEchoResponse) {
}

// A sequence of requests followed by one response (streamed upload).
// The server returns the total number of messages as the result.
rpc ClientStreamingEcho(stream ClientStreamingEchoRequest)
returns (ClientStreamingEchoResponse);

// A sequence of requests with each message echoed by the server immediately.
// The server returns the same client messages in order.
// E.g. this is how the speech API works.
rpc FullDuplexEcho(stream EchoRequest) returns (stream EchoResponse);

// A sequence of requests followed by a sequence of responses.
// The server buffers all the client messages and then returns the same
// client messages one by one after the client half-closes the stream.
// This is how an image recognition API may work.
rpc HalfDuplexEcho(stream EchoRequest) returns (stream EchoResponse);
}
4 changes: 4 additions & 0 deletions net/grpc/web/echo_example/generate_proto.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
protoc --proto_path=./ --php_out=./ --grpc_out=./ \
--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin ./my_echo.proto

26 changes: 26 additions & 0 deletions net/grpc/web/echo_example/greeter_client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
require dirname(__FILE__).'/vendor/autoload.php';

$client = new \Grpc\Gateway\Testing\EchoServiceClient('localhost:9091', []);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we re-use the plugin from grpc-php(C-core)? Generated Client doesn't have the default value for it. Something like credentials must be set at the second parameter.


$echo_request = new \Grpc\Gateway\Testing\EchoRequest();
$message = "Hello";
$echo_request->setMessage($message);
$call_echo = $client->Echo($echo_request);

$streamRequest = new \Grpc\Gateway\Testing\ServerStreamingEchoRequest();
$streamRequest->setMessage($message);
$streamRequest->setMessageCount(3);
$streamRequest->setMessageInterval(500);
$call_stream_echo = $client->ServerStreamingEcho($streamRequest);

// Get response
$streamResponse = $call_stream_echo->responses($streamRequest);
list($reply, $status) = $call_echo->wait();
// Print response
echo "Echo response:".PHP_EOL.$reply->getMessage().PHP_EOL;
echo "StreamEcho response:".PHP_EOL;
foreach ($streamResponse as $feature) {
echo $feature->getMessage().PHP_EOL;
}
$client->close();
24 changes: 24 additions & 0 deletions net/grpc/web/grpc/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Move this to /src/Grpc folder. The dir structure would be something like:
/src
/test
/doc
...

"name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP",
"keywords": ["rpc"],
"homepage": "https://grpc.io",
"license": "Apache-2.0",
"version": "1.6.0",
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"google/auth": "v0.9"
},
"suggest": {
"ext-protobuf": "For better performance, install the protobuf C extension.",
"google/protobuf": "To get started using grpc quickly, install the native protobuf library."
},
"autoload": {
"psr-4": {
"Grpc\\": "src/lib/"
}
}
}
175 changes: 175 additions & 0 deletions net/grpc/web/grpc/src/lib/AbstractCall.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

namespace Grpc;

/**
* Class AbstractCall.
* @package Grpc
*/
abstract class AbstractCall
{
/**
* @var Call
*/
//protected $call;
protected $deserialize;
protected $metadata;
protected $trailing_metadata;
protected $channel;
protected $ch;

/**
* Create a new Call wrapper object.
*
* @param resource $channel The channel to communicate on
* @param string $method The method to call on the
* remote server
* @param callback $deserialize A callback function to deserialize
* the response
* @param array $options Call options (optional)
*/
public function __construct($channel,
$method,
$deserialize,
array $options = [])
{
// TODO: check Timeout,etc from $options
// TODO: call credentials?
$this->ch = curl_init();
$headers[] = 'custom-header-1: value1';
$headers[] = 'Content-Type: application/grpc-web-text';
$headers[] = 'Accept: application/grpc-web-text';

curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_URL, $method);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);

$this->channel = $channel;
$this->deserialize = $deserialize;
$this->metadata = null;
$this->trailing_metadata = null;
}

/**
* @param mixed $argument The data to decode
* @return string Base64 decoded massage
*/
public function _base64encode($argument) {
$serialized_data = $argument->serializeToString();
$len = strlen($serialized_data);
$bytesArray = [0, 0, 0, 0, 0];
for ($i = 4; $i >= 1; $i--) {
$bytesArray[$i] = ($len % 256);
$len = $len >> 8;
}
$serialized_data_byte = unpack('C*', $serialized_data);
$argument_data_byte = array_merge($bytesArray, $serialized_data_byte);
$argument_data_string = implode(array_map("chr", $argument_data_byte));
return base64_encode($argument_data_string);
}

/**
* @return mixed The metadata sent by the server
*/
public function getMetadata()
{
}

/**
* @return mixed The trailing metadata sent by the server
*/
public function getTrailingMetadata()
{
}

/**
* @return string The URI of the endpoint
*/
public function getPeer()
{
}

/**
* Cancels the call.
*/
public function cancel()
{
}

/**
* Serialize a message to the protobuf binary format.
*
* @param mixed $data The Protobuf message
*
* @return string The protobuf binary format
*/
protected function _serializeMessage($data)
{
// Proto3 implementation
if (method_exists($data, 'encode')) {
return $data->encode();
} elseif (method_exists($data, 'serializeToString')) {
return $data->serializeToString();
}

// Protobuf-PHP implementation
return $data->serialize();
}

/**
* Deserialize a response value to an object.
*
* @param string $value The binary value to deserialize
*
* @return mixed The deserialized value
*/
protected function _deserializeResponse($value)
{
if ($value === null) {
return;
}

// Proto3 implementation
if (is_array($this->deserialize)) {
list($className, $deserializeFunc) = $this->deserialize;
$obj = new $className();
if (method_exists($obj, $deserializeFunc)) {
$obj->$deserializeFunc($value);
} else {
$obj->mergeFromString($value);
}

return $obj;
}

// Protobuf-PHP implementation
return call_user_func($this->deserialize, $value);
}

/**
* Set the CallCredentials for the underlying Call.
*
* @param CallCredentials $call_credentials The CallCredentials object
*/
public function setCallCredentials($call_credentials)
{
}
}
Loading