@@ -1394,6 +1394,145 @@ public function __invoke(Call $call, array $options)
13941394 $ this ->assertTrue ($ m2Called );
13951395 }
13961396
1397+ public function testPrependMiddleware ()
1398+ {
1399+ list ($ client , $ transport ) = $ this ->buildClientToTestModifyCallMethods ();
1400+
1401+ $ callOrder = [];
1402+ $ middleware1 = function (callable $ handler ) use (&$ callOrder ) {
1403+ return new class ($ handler , $ callOrder ) implements MiddlewareInterface {
1404+ private $ handler ;
1405+ private array $ callOrder ;
1406+ public function __construct (
1407+ callable $ handler ,
1408+ array &$ callOrder
1409+ ) {
1410+ $ this ->handler = $ handler ;
1411+ $ this ->callOrder = &$ callOrder ;
1412+ }
1413+ public function __invoke (Call $ call , array $ options )
1414+ {
1415+ $ this ->callOrder [] = 'middleware1 ' ;
1416+ return ($ this ->handler )($ call , $ options );
1417+ }
1418+ };
1419+ };
1420+ $ middleware2 = function (callable $ handler ) use (&$ callOrder ) {
1421+ return new class ($ handler , $ callOrder ) implements MiddlewareInterface {
1422+ private $ handler ;
1423+ private array $ callOrder ;
1424+ public function __construct (
1425+ callable $ handler ,
1426+ array &$ callOrder
1427+ ) {
1428+ $ this ->handler = $ handler ;
1429+ $ this ->callOrder = &$ callOrder ;
1430+ }
1431+ public function __invoke (Call $ call , array $ options )
1432+ {
1433+ $ this ->callOrder [] = 'middleware2 ' ;
1434+ return ($ this ->handler )($ call , $ options );
1435+ }
1436+ };
1437+ };
1438+ $ client ->addMiddleware ($ middleware1 );
1439+ $ client ->prependMiddleware ($ middleware2 );
1440+
1441+ $ transport ->startUnaryCall (
1442+ Argument::type (Call::class),
1443+ [
1444+ 'transportOptions ' => [
1445+ 'custom ' => ['addModifyUnaryCallableOption ' => true ]
1446+ ],
1447+ 'headers ' => AgentHeader::buildAgentHeader ([]),
1448+ 'credentialsWrapper ' => CredentialsWrapper::build ([
1449+ 'keyFile ' => __DIR__ . '/testdata/json-key-file.json '
1450+ ])
1451+ ]
1452+ )
1453+ ->shouldBeCalledOnce ()
1454+ ->willReturn (new FulfilledPromise (new Operation ()));
1455+
1456+ $ client ->startCall (
1457+ 'simpleMethod ' ,
1458+ 'decodeType ' ,
1459+ [],
1460+ new MockRequest (),
1461+ )->wait ();
1462+
1463+ $ this ->assertEquals (['middleware1 ' , 'middleware2 ' ], $ callOrder );
1464+ }
1465+
1466+ public function testPrependMiddlewareOrder ()
1467+ {
1468+ list ($ client , $ transport ) = $ this ->buildClientToTestModifyCallMethods ();
1469+
1470+ $ callOrder = [];
1471+ $ middleware1 = function (callable $ handler ) use (&$ callOrder ) {
1472+ return new class ($ handler , $ callOrder ) implements MiddlewareInterface {
1473+ private $ handler ;
1474+ private array $ callOrder ;
1475+ public function __construct (
1476+ callable $ handler ,
1477+ array &$ callOrder
1478+ ) {
1479+ $ this ->handler = $ handler ;
1480+ $ this ->callOrder = &$ callOrder ;
1481+ }
1482+ public function __invoke (Call $ call , array $ options )
1483+ {
1484+ $ this ->callOrder [] = 'middleware1 ' ;
1485+ return ($ this ->handler )($ call , $ options );
1486+ }
1487+ };
1488+ };
1489+ $ middleware2 = function (callable $ handler ) use (&$ callOrder ) {
1490+ return new class ($ handler , $ callOrder ) implements MiddlewareInterface {
1491+ private $ handler ;
1492+ private array $ callOrder ;
1493+ public function __construct (
1494+ callable $ handler ,
1495+ array &$ callOrder
1496+ ) {
1497+ $ this ->handler = $ handler ;
1498+ $ this ->callOrder = &$ callOrder ;
1499+ }
1500+ public function __invoke (Call $ call , array $ options )
1501+ {
1502+ $ this ->callOrder [] = 'middleware2 ' ;
1503+ return ($ this ->handler )($ call , $ options );
1504+ }
1505+ };
1506+ };
1507+
1508+ $ client ->prependMiddleware ($ middleware1 );
1509+ $ client ->prependMiddleware ($ middleware2 );
1510+
1511+ $ transport ->startUnaryCall (
1512+ Argument::type (Call::class),
1513+ [
1514+ 'transportOptions ' => [
1515+ 'custom ' => ['addModifyUnaryCallableOption ' => true ]
1516+ ],
1517+ 'headers ' => AgentHeader::buildAgentHeader ([]),
1518+ 'credentialsWrapper ' => CredentialsWrapper::build ([
1519+ 'keyFile ' => __DIR__ . '/testdata/json-key-file.json '
1520+ ])
1521+ ]
1522+ )
1523+ ->shouldBeCalledOnce ()
1524+ ->willReturn (new FulfilledPromise (new Operation ()));
1525+
1526+ $ client ->startCall (
1527+ 'simpleMethod ' ,
1528+ 'decodeType ' ,
1529+ [],
1530+ new MockRequest (),
1531+ )->wait ();
1532+
1533+ $ this ->assertEquals (['middleware2 ' , 'middleware1 ' ], $ callOrder );
1534+ }
1535+
13971536 public function testInvalidClientOptionsTypeThrowsExceptionForV2SurfaceOnly ()
13981537 {
13991538 // v1 client
0 commit comments