├── src ├── Exceptions │ └── WebhookGroupNameNotFoundException.php ├── Providers │ ├── ProviderInterface.php │ ├── DefaultProvider.php │ └── Discord.php ├── Facades │ └── RequestForwarder.php ├── RequestForwarderMiddleware.php ├── ProcessRequestForwarder.php ├── RequestForwarderServiceProvider.php └── RequestForwarder.php ├── CHANGELOG.md ├── config └── request-forwarder.php ├── LICENSE.md ├── composer.json └── README.md /src/Exceptions/WebhookGroupNameNotFoundException.php: -------------------------------------------------------------------------------- 1 | client 21 | ->send($webhook['method'] ?? 'POST', $webhook['url']); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Providers/Discord.php: -------------------------------------------------------------------------------- 1 | client 24 | ->send('POST', $webhook['url'], [ 25 | 'json' => ['content' => $content], 26 | ]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/RequestForwarderMiddleware.php: -------------------------------------------------------------------------------- 1 | requestForwarder->sendAsync($request, $name); 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /config/request-forwarder.php: -------------------------------------------------------------------------------- 1 | 'default', 7 | 8 | 'webhooks' => [ 9 | 'default' => [ 10 | 'targets' => [ 11 | [ 12 | 'url' => 'https://some-domain.com/webhook', 13 | 'method' => 'POST', 14 | ], 15 | [ 16 | 'url' => 'https://discord.com/api/webhooks/1209955556656291860/LAaczT-Pg785d5OzBmi6ivx2Vl7wAoruOwcVnZpb2eE2x8tf7fMi6R7_sr0IV0WoK83S', 17 | 'method' => 'POST', 18 | 'provider' => \Moneo\RequestForwarder\Providers\Discord::class, 19 | ], 20 | ], 21 | ], 22 | ], 23 | 24 | 'queue_name' => '', 25 | 26 | 'queue_class' => Moneo\RequestForwarder\ProcessRequestForwarder::class, 27 | ]; 28 | -------------------------------------------------------------------------------- /src/ProcessRequestForwarder.php: -------------------------------------------------------------------------------- 1 | triggerHooks($this->url, $this->params, $this->webhookName); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) moneo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/RequestForwarderServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('laravel-request-forwarder') 20 | ->hasConfigFile(); 21 | } 22 | 23 | public function registeringPackage(): void 24 | { 25 | $this->app->bind('laravel_request_forwarder.client', function ($app): Factory { 26 | return $app[Factory::class]; 27 | }); 28 | 29 | $this->app->singleton(RequestForwarder::class, function ($app): RequestForwarder { 30 | return new RequestForwarder( 31 | $app->make('laravel_request_forwarder.client'), 32 | config('request-forwarder.webhooks'), 33 | ); 34 | }); 35 | 36 | app('router')->aliasMiddleware('request-forwarder', RequestForwarderMiddleware::class); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/RequestForwarder.php: -------------------------------------------------------------------------------- 1 | url(), $request->toArray(), $webhookGroupName) 24 | ->onQueue(config('request-forwarder.queue_name')); 25 | } 26 | 27 | /** 28 | * @throws WebhookGroupNameNotFoundException 29 | */ 30 | public function triggerHooks(string $url, array $params, ?string $webhookGroupName = null): void 31 | { 32 | foreach ($this->getWebhookTargets($webhookGroupName) as $webhook) { 33 | try { 34 | /** @var ProviderInterface $provider */ 35 | $providerClass = $webhook['provider'] ?? DefaultProvider::class; 36 | $provider = new $providerClass($this->client); 37 | $provider->send($url, $params, $webhook); 38 | } catch (\Exception $e) { 39 | } 40 | } 41 | } 42 | 43 | /** 44 | * @throws WebhookGroupNameNotFoundException 45 | */ 46 | private function getWebhookInfo(?string $webhookGroupName = null): array 47 | { 48 | if ($webhookGroupName === null || trim($webhookGroupName) === '') { 49 | $webhookGroupName = config('request-forwarder.default_webhook_group_name'); 50 | } 51 | 52 | return $this->webhooks[$webhookGroupName] ?? throw new WebhookGroupNameNotFoundException('Webhook Group Name called '.$webhookGroupName.' is not defined in the config file'); 53 | } 54 | 55 | /** 56 | * // todo: DTO for return type 57 | * 58 | * @throws WebhookGroupNameNotFoundException 59 | */ 60 | private function getWebhookTargets(?string $webhookGroupName = null): array 61 | { 62 | return $this->getWebhookInfo($webhookGroupName)['targets']; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "moneo/laravel-request-forwarder", 3 | "description": "Laravel Request Forwarder allows you to forward incoming requests to another addresses.", 4 | "keywords": [ 5 | "moneo", 6 | "laravel", 7 | "laravel-request-forwarder" 8 | ], 9 | "homepage": "https://github.com/moneo/laravel-request-forwarder", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "Emre Dipi", 14 | "email": "mail@emredipi.com", 15 | "role": "Developer" 16 | } 17 | ], 18 | "require": { 19 | "php": "^8.1", 20 | "guzzlehttp/guzzle": "^7.8", 21 | "spatie/laravel-package-tools": "^1.14.0", 22 | "illuminate/contracts": "^10.0|^11.0" 23 | }, 24 | "require-dev": { 25 | "laravel/pint": "^1.0", 26 | "nunomaduro/collision": "^7.8|^8.0", 27 | "larastan/larastan": "^2.0.1", 28 | "orchestra/testbench": "^8.8|^9.0", 29 | "pestphp/pest": "^2.20", 30 | "pestphp/pest-plugin-arch": "^2.5", 31 | "pestphp/pest-plugin-laravel": "^2.0", 32 | "phpstan/extension-installer": "^1.1", 33 | "phpstan/phpstan-deprecation-rules": "^1.0", 34 | "phpstan/phpstan-phpunit": "^1.0", 35 | "spatie/laravel-ray": "^1.26" 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Moneo\\RequestForwarder\\": "src/" 40 | } 41 | }, 42 | "autoload-dev": { 43 | "psr-4": { 44 | "Moneo\\RequestForwarder\\Tests\\": "tests/", 45 | "Workbench\\App\\": "workbench/app/" 46 | } 47 | }, 48 | "scripts": { 49 | "post-autoload-dump": "@composer run prepare", 50 | "clear": "@php vendor/bin/testbench package:purge-laravel-request-forwarder --ansi", 51 | "prepare": "@php vendor/bin/testbench package:discover --ansi", 52 | "build": [ 53 | "@composer run prepare", 54 | "@php vendor/bin/testbench workbench:build --ansi" 55 | ], 56 | "start": [ 57 | "Composer\\Config::disableProcessTimeout", 58 | "@composer run build", 59 | "@php vendor/bin/testbench serve" 60 | ], 61 | "analyse": "vendor/bin/phpstan analyse", 62 | "test": "vendor/bin/pest", 63 | "test-coverage": "vendor/bin/pest --coverage", 64 | "format": "vendor/bin/pint" 65 | }, 66 | "config": { 67 | "sort-packages": true, 68 | "allow-plugins": { 69 | "pestphp/pest-plugin": true, 70 | "phpstan/extension-installer": true 71 | } 72 | }, 73 | "extra": { 74 | "laravel": { 75 | "providers": [ 76 | "Moneo\\RequestForwarder\\RequestForwarderServiceProvider" 77 | ], 78 | "aliases": { 79 | "RequestForwarder": "Moneo\\RequestForwarder\\Facades\\RequestForwarder" 80 | } 81 | } 82 | }, 83 | "minimum-stability": "dev", 84 | "prefer-stable": true 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://banners.beyondco.de/Laravel%20Request%20Forwarder.png?theme=light&packageManager=composer+require&packageName=moneo%2Flaravel-request-forwarder&pattern=architect&style=style_1&description=Forward+incoming+requests+to+another+addresses&md=1&showWatermark=0&fontSize=100px&images=server) 2 | 3 | # Laravel Request Forwarder 4 | 5 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/moneo/laravel-request-forwarder.svg?style=flat-square)](https://packagist.org/packages/moneo/laravel-request-forwarder) 6 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/moneo/laravel-request-forwarder/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/moneo/laravel-request-forwarder/actions?query=workflow%3Arun-tests+branch%3Amain) 7 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/moneo/laravel-request-forwarder/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/moneo/laravel-request-forwarder/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) 8 | [![Total Downloads](https://img.shields.io/packagist/dt/moneo/laravel-request-forwarder.svg?style=flat-square)](https://packagist.org/packages/moneo/laravel-request-forwarder) 9 | 10 | Sometimes we need to redirect requests to our application to other addresses. The best example of this is webhooks. Some service providers only send webhooks to a single address. With this package, you can post the requests coming to your application to another address as it is. 11 | 12 | In addition to sending to a single URL, you can also send to different destinations by typing a custom provider. In our package you can see an example that sends notifications to Discord! 13 | 14 | ![](https://raw.githubusercontent.com/moneo/laravel-request-forwarder/main/workflow.png) 15 | 16 | 17 | ## Installation 18 | 19 | You can install the package via composer: 20 | 21 | ```bash 22 | composer require moneo/laravel-request-forwarder 23 | ``` 24 | 25 | You can publish the config file with: 26 | 27 | ```bash 28 | php artisan vendor:publish --tag="request-forwarder-config" 29 | ``` 30 | 31 | This is the contents of the published config file: 32 | 33 | ```php 34 | return [ 35 | // decides which webhook to use if no webhook group name is specified while use middleware 36 | 'default_webhook_group_name' => 'default', 37 | 38 | 'webhooks' => [ 39 | 'default' => [ 40 | 'targets' => [ 41 | [ 42 | 'url' => 'https://some-domain.com/webhook', 43 | 'method' => 'POST', 44 | ], 45 | [ 46 | 'url' => 'https://discord.com/api/webhooks/1209955556656291860/LAaczT-Pg785d5OzBmi6ivx2Vl7wAoruOwcVnZpb2eE2x8tf7fMi6R7_sr0IV0WoK83S', 47 | 'method' => 'POST', 48 | 'provider' => \Moneo\RequestForwarder\Providers\Discord::class, 49 | ], 50 | ], 51 | ], 52 | ], 53 | 54 | 'queue_name' => '', 55 | 56 | 'queue_class' => Moneo\RequestForwarder\ProcessRequestForwarder::class, 57 | ]; 58 | ``` 59 | 60 | ## Usage 61 | 62 | Add middleware to your routes which will be forwarded 63 | ```php 64 | Route::middleware('request-forwarder') // default group 65 | ->get('/endpoint', fn () => 'Some Response'); 66 | 67 | Route::middleware('request-forwarder:another-group-in-config') // customize targets with group name parameter 68 | ->get('/endpoint', fn () => 'Some Response'); 69 | ``` 70 | 71 | ## Testing 72 | 73 | ```bash 74 | composer test 75 | ``` 76 | 77 | ## Changelog 78 | 79 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 80 | 81 | ## Contributing 82 | 83 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 84 | 85 | ## Security Vulnerabilities 86 | 87 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 88 | 89 | ## Credits 90 | 91 | - [Emre Dipi](https://github.com/emredipi) 92 | - [Mücahit Cücen](https://github.com/mcucen) 93 | - [Semih Keskin](https://github.com/semihkeskindev) 94 | - [Taha Çalışkan](https://github.com/Tahaknd) 95 | - [All Contributors](../../contributors) 96 | 97 | ## License 98 | 99 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 100 | --------------------------------------------------------------------------------