Giter VIP home page Giter VIP logo

server's Introduction

Introduction

Latest Version on Packagist GitHub Tests Action Status codecov Total Downloads

Sajya is an open-source project that makes it easy to implement the JSON-RPC 2.0 server specification for Laravel. With Sajya, you can quickly and easily set up a JSON-RPC server that supports all of the features of the specification, including validation of parameters, support for batch and notification requests, and more.

Official Documentation

You can find the complete documentation for Sajya on its website. The documentation includes detailed instructions on how to install and use Sajya, as well as a reference guide for all of its features.

Changelog

To learn about the latest updates and changes to Sajya, please see the CHANGELOG. The changelog includes a list of all the changes made to Sajya in each release, along with the corresponding version number.

Contributing

We welcome contributions to Sajya. Contributions can include bug fixes, new features, and improvements to the documentation.

Maintainers

Sajya is developed and maintained by Alexandr Chernyaev. Alexandr is the main author and maintainer of Sajya, and is responsible for coordinating the development and release of new versions.

License

Sajya is released under the MIT License. Please see the License File for more information.

server's People

Contributors

akki-io avatar dependabot[bot] avatar laravel-shift avatar sadelephant avatar simonmacintyre avatar tabuna avatar vanodevium avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

server's Issues

[Discussion] Should we remove the assumed assertOk() in ProceduralRequests trait?

Consider this use case:

Authentication happens in headers with api tokens. I'd like to test through a procedure call attempt, that the headers successfully require auth, and thus return a 401 HTTP code.

I know I could bypass the trait methods and make my own setup that rips out the assertOk, but specifically I'd like to use the original callProcedure method to test all my procedures. It would just be nice if I could use the same calling of a procedure test, to test the auth for the procedure routes as well.

Maybe enlighten me if I am missing a bit of the philosophy behind this. I understand that jrpc must return http 200, and error key for application errors. However I thought it is reasonable to want to test the procedure call, and fail auth, and thus have a http response code that is not 200 (this is not a failure/error or mistake of JRPC, but of the authentication in the headers trying to POST to hit a procedure).

Please let me know! I didn't make the PR yet just because I wanted to see & understand if it was a desired change for the package.

[Security] Workflow run-tests.yml is using vulnerable action actions/checkout

The workflow run-tests.yml is referencing action actions/checkout using references v1. However this reference is missing the commit a6747255bd19d7a757dbdda8c654a9f84db19839 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.

Internal exception when procedure method not exists

When calling to a method which procedure doesn't have, it turns out into an internal exception.

local.ERROR: Method App\Http\Procedures\TennisProcedure::pinga() does not exist {"exception":"[object] (ReflectionException(code: 0): Method App\Http\Procedures\TennisProcedure::pinga() does not exist at /app/vendor/sajya/server/src/Guide.php:144)

Procedure Class

<?php
declare(strict_types=1);

namespace App\Http\Procedures;

use Illuminate\Http\Request;
use Sajya\Server\Procedure;

class TennisProcedure extends Procedure
{
    public static string $name = 'tennis';

    public function ping(): string
    {
        return 'pong';
    }
}

Call a method not exists

<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Http;
use Sajya\Client\Client;

class TennisController extends Controller
{
    public function index(): mixed
    {
        $request = Http::withoutVerifying()
            ->baseUrl(route('rpc.endpoint'));
        $client = new Client($request);
        $response = $client->execute('tennis@pinga');
        return $response->result();
    }
}

How do certain methods in the process preclude middleware validation?

过程中的某些方法如何排除中间件验证?
How do certain methods in the process preclude middleware validation?

例如AccountsProcedure过程类中有loginlogout等方法,需将login排除身份验证中间件。
For example, the AccountsProcedure procedure class has methods such as login, logout, etc., and login needs to be excluded from the authentication middleware.

请问在sajya/server中如何实现?
How can I implement this in sajya/server?

在此,感谢您的回答!
I would like to thank you for your answer!

adding params to request give me an error

Hi,
as described in the example on the docs all works for basic, but if I add some params to curl request, ive an error that i cannot understand:

{"id":null,"error":{"code":-32700,"message":"Parse error","data":null,"file":"/home/natty/workspace/farmacie/vendor/sajya/server/src/Http/Parser.php","line":133,"trace":"#0 /home/natty/workspace/farmacie/vendor/sajya/server/src/Http/Parser.php(104): Sajya\Server\Http\Parser->checkValidation()\n#1 /home/natty/workspace/farmacie/vendor/sajya/server/src/Guide.php(49): Sajya\Server\Http\Parser->makeRequests()\n#2 /home/natty/workspace/farmacie/vendor/sajya/server/src/JsonRpcController.php(27): Sajya\Server\Guide->handle()\n#3 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(48): Sajya\Server\JsonRpcController->__invoke()\n#4 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Route.php(255): Illuminate\Routing\ControllerDispatcher->dispatch()\n#5 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Route.php(197): Illuminate\Routing\Route->runController()\n#6 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Router.php(691): Illuminate\Routing\Route->run()\n#7 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Routing\Router->Illuminate\Routing\{closure}()\n#8 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#9 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Routing\Middleware\SubstituteBindings->handle()\n#10 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(127): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#11 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(103): Illuminate\Routing\Middleware\ThrottleRequests->handleRequest()\n#12 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(55): Illuminate\Routing\Middleware\ThrottleRequests->handleRequestUsingNamedLimiter()\n#13 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Routing\Middleware\ThrottleRequests->handle()\n#14 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#15 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Router.php(693): Illuminate\Pipeline\Pipeline->then()\n#16 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Router.php(668): Illuminate\Routing\Router->runRouteWithinStack()\n#17 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Router.php(634): Illuminate\Routing\Router->runRoute()\n#18 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Routing/Router.php(623): Illuminate\Routing\Router->dispatchToRoute()\n#19 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(166): Illuminate\Routing\Router->dispatch()\n#20 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}()\n#21 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#22 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()\n#23 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#24 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle()\n#25 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#26 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle()\n#27 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(87): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#28 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle()\n#29 /home/natty/workspace/farmacie/vendor/fruitcake/laravel-cors/src/HandleCors.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#30 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fruitcake\Cors\HandleCors->handle()\n#31 /home/natty/workspace/farmacie/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#32 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fideloper\Proxy\TrustProxies->handle()\n#33 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}()\n#34 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(141): Illuminate\Pipeline\Pipeline->then()\n#35 /home/natty/workspace/farmacie/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(110): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter()\n#36 /home/natty/workspace/farmacie/public/index.php(52): Illuminate\Foundation\Http\Kernel->handle()\n#37 /home/natty/workspace/farmacie/server.php(21): require_once('/home/natty/wor...')\n#38 {main}"},"jsonrpc":"2.0"}

[Enhancement]Support for framework exception handler

All exceptions are catched by Sajya\Server\HandleProcedure::handle without reporting. It will be a better way to use Illuminate\Contracts\Debug\ExceptionHandler to deal with exceptions.

As a benifit of this, all exceptions will be reported, such as logging and instant messaging, most useful for debugging. On the other hand, we can transform them into json-rpc format.

Overwrite Method name ?

Hi , Thanks for your work !

I'm using your package for simulate another rpc-endpoint , like i have another system who send json rpc request with method "ping" but since the method start with producer name its fail with

 "error": {
    "code": -32601,
    "message": "Method not found",

I have try to overwrite the method name by middleware like this


use Illuminate\Http\Request
 public function handle(Request $request, Closure $next)
    {
        $input = $request->all();
        Log::info("Request method ", [$input["method"], $request->method]); // Shows original request
        $request->merge([
            'method' =>  "message@" . $input['method']
        ]);
        $input = $request->all();
        $request->setMethod("message@" . $input['method']);
        Log::info("After Request method ", [$input["method"], $request->method]); // Shows modified request




        return $next($request);
    }

Bur i think its been ignored at all ..

Do you have any clues ?

Thanks

support for laravel LTS?

Hey guys, im currently working on a small L6 application, to replace an old PHP app which uses jsonrpc... in order to add backward compatibility I would like to use your lib, but it requires L8 or at least L7... just seeing on the Laravel release notes page, seems to me like the guaranteed support for L6 is longer, so I would prefer to keep the version...
its possible to set the requirements of this project less rectrictive? or could you tell me which components are using L7/8 features exclusively? ...then I could create a fork and maybe make a PR here

request->id validation and request->method delimiter

Hello @tabuna
Thanks for this awesome package!

I have two simple questions

  1. According to the specification, id in RPC request described as
id
An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]
The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects.

[1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling.

[2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions.

What is the reason for the current validation rule, which is

'id'      => 'regex:/^\d*(\.\d{2})?$/|nullable',
  1. method delimiter
    How can I change default @ to the . (dot) or : (colon)?

it don't work with quickstart, it return 404 not found, my route not correct ?

class TennisProcedure extends Procedure
{
    /**
     * The name of the procedure that will be
     * displayed and taken into account in the search
     *
     * @var string
     */
    public static string $name = 'tennis';

    /**
     * Execute the procedure.
     *
     * @param Request $request
     *
     * @return array|string|integer
     */
    public function ping(Request $request)
    {
        return "pong";
    }
}

and my route in api.php

Route::rpc('/v1/endpoint', [TennisProcedure::class])->name('rpc.endpoint');

and my request:

request url:
http://127.0.0.1:8006/api/v1/endpoint

request  body
{
    "jsonrpc": "2.0",
    "method": "tennis@ping",
    "id": 1
}

Problem with request with big payload

Smaller request works well, but larger ones (10MB+ payload, for example large email sets) hangs on processing side.
The problem caused by the Arr::dot() call in \Sayja\Server\Binding bindResolve() function line 76

How to exclude or use middleware for a procedure

How to exclude or use middleware for a procedure

Hello, I have a problem when using the sajya/server package. How to exclude middleware for a specified Procedure.

For example, System.Account.login needs to exclude auth:sanctum middleware, while System.Account.getProfile requires auth:sanctum middleware protection.

I am trying to use laravel/sanctum and spatie/laravel-permission to implement user authentication and permission verification for Procedure.

php artisan route:clear command throws InvalidArgumentException

whenever I try to clear the route caches with rpc endpoint, i get the InvalidArgumentException exception


   InvalidArgumentException 

  Attribute [rpc] does not exist.

  at vendor/laravel/framework/src/Illuminate/Routing/RouteRegistrar.php:107
    103▕      */
    104▕     public function attribute($key, $value)
    105▕     {
    106▕         if (! in_array($key, $this->allowedAttributes)) {
  ➜ 107▕             throw new InvalidArgumentException("Attribute [{$key}] does not exist.");
    108▕         }
    109▕ 
    110▕         if ($key === 'middleware') {
    111▕             foreach ($value as $index => $middleware) {

      +2 vendor frames 
  3   routes/api.php:28
      Illuminate\Support\Facades\Facade::__callStatic()

      +4 vendor frames 
  8   app/Providers/RouteServiceProvider.php:46
      Illuminate\Routing\RouteRegistrar::group()

JSON-RPC forwarding

Let's try to imagine a proxy service that receives a request or requests as input and forwards them to other third-party services, depending on the request parameters. As a result, it returns a list of responses that third-party services returned.

Some example of idea:

Input request into RPC-proxy:

[
  {
    "jsonrpc": "2.0",
    "method": "service1:procedure@sum", // this request will be forwarded to the service1 as procedure@sum
    "params": [
      1,
      2,
      3
    ],
    "id": 2
  },
  {
    "jsonrpc": "2.0",
    "method": "service2:procedure@avg", // this request will be forwarded to the service2 as procedure@avg
    "params": [
      1,
      2,
      3
    ],
    "id": 3
  },
  {
    "jsonrpc": "2.0",
    "method": "service3:procedure@min, // this request will be forwarded to the service3 as procedure@min,
    "params": [
      1,
      2,
      3
    ],
    "id": 4
  }
]

And response from RPC-proxy:

[
  {
    "id": "2",
    "result": {"sum":6}, // this is response from the service1 for procedure@sum
    "jsonrpc": "2.0",
    "method": "procedure@sum"
  },
  {
    "id": "3",
    "result": {"avg":2}, // this is response from the service2 for procedure@avg
    "jsonrpc": "2.0",
    "method": "procedure@avg"
  },
  {
    "id": "4",
    "result": {"min":1}, // this is response from the service3 for procedure@min,
    "jsonrpc": "2.0",
    "method": "procedure@min"
  }
]

The main question is this: is it possible to parse all input requests using the Sajya\Server\Http\Parser and forward them through the Guzzle as is?

Maybe you can give some advice or point me in the right direction?

Result for call in batchmode combined with notification

I am experiencing issues combining a notification and a call in the same batch.

I expected to get one result, ( id 1 ) and no response for the notification at all.
Below you can see 2 tests,
the first test gets 2 responses for each call.
The second is the same, except for the last in the batch, its a notification without id. it shouldn't give a response. but the first in the batch should.

Am i missing something here?

Test without notification:

$ curl -s 'http://127.0.0.1:80/api/v1' --data-binary '[{"jsonrpc":"2.0","method":"Resource@get","params":{"id":2},"id":1}, "jsonrpc":"2.0","method":"Resource@get","params":{"id":2},"id":1}]' | jq
[
  {
    "id": "1",
    "result": {
      "id": 2,
      "name": "Dr. Sheldon Nikolaus",
      "attribute1": "morgMoa64F",
      "attribute2": "Dh3dN11Jbf",
      "created_at": "2021-08-13T12:39:49.000000Z",
      "updated_at": "2021-08-13T12:39:49.000000Z"
    },
    "jsonrpc": "2.0"
  },
  {
    "id": "1",
    "result": {
      "id": 2,
      "name": "Dr. Sheldon Nikolaus",
      "attribute1": "morgMoa64F",
      "attribute2": "Dh3dN11Jbf",
      "created_at": "2021-08-13T12:39:49.000000Z",
      "updated_at": "2021-08-13T12:39:49.000000Z"
    },
    "jsonrpc": "2.0"
  }
]

Test with notification:

$ curl -s 'http://127.0.0.1:80/api/v1' --data-binary\
 '[{"jsonrpc":"2.0","method":"Resource@get","params":{"id":2},"id":1},{"jsonrpc":"2.0","method":"Resource@get","params":{"id":2}}]' | jq
[
  {
    "id": "1",
    "result": null,
    "jsonrpc": "2.0"
  },
  {
    "id": null,
    "result": null,
    "jsonrpc": "2.0"
  }
]

[Security] Workflow run-tests.yml is using vulnerable action codecov/codecov-action

The workflow run-tests.yml is referencing action codecov/codecov-action using references v1.0.5. However this reference is missing the commit c6a36d2dbbf6a734e6ef75af344acdf122fcd9f9 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.

[Feature Request]Dynamic procedure name support

Maybe procedure name can be set from class name and relative namespace.

<?php

declare(strict_types=1);

namespace Sajya\Server;

use Illuminate\Support\Str;

abstract class Procedure
{
    public static function guessProcedureName(): string
    {
        return Str::snake(substr(class_basename(static::class), 0, -strlen('Procedure')));
    }

405 Method not allowed on production

Hi,

Currently I'm running "laravel/framework": "^8.10" with "sajya/server": "^2.0". When I'm on my local machine(windows) the rpc endpoint works fine when posting. When I do the same post to the production environment via Postman I get the error The server returned a "405 Method Not Allowed". I have cleared the routes and cached them again. The production systen is running Ubuntu

Example usage with Laravel Sanctum auth

Could you provide a simple example on how to protect the api endpoints with Laravel Sanctum session-based auth?

I currently have this code in ./routes/api.php:

// user api
Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) {
    return $request->user();
});

// rpc api
Route::rpc('/v1/endpoint', [TennisProcedure::class])->name('rpc.endpoint');

...I can't figure out how to inject sanctum in the rpc api.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.