├── .gitignore
├── .github
├── PULL_REQUEST_TEMPLATE
│ ├── bug_reported.md
│ ├── bug_not_reported.md
│ └── new_feature.md
├── PULL_REQUEST_TEMPLATE.md
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── infection.json
├── tests
├── TestCase.php
├── NgrokWebServiceTest.php
├── Pest.php
├── NgrokProcessBuilderTest.php
├── NgrokCommandTest.php
└── NgrokServiceProviderTest.php
├── phpcs.xml
├── phpstan.neon
├── php-cs-fixer.php
├── phpunit.xml
├── CHANGELOG-3.x.md
├── CHANGELOG-2.x.md
├── LICENSE.md
├── CHANGELOG-1.x.md
├── phpunit-coverage.xml
├── composer.json
├── src
├── NgrokProcessBuilder.php
├── NgrokWebService.php
├── NgrokServiceProvider.php
└── NgrokCommand.php
├── README.md
└── Makefile
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /vendor
3 | composer.lock
4 | composer.phar
5 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/bug_reported.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | **Issues**
6 | List the issues numbers that are being fixed: #ISSUE_NUMBER, #ISSUE_NUMBER, ...
7 |
8 | **Describe the fix**
9 | A clear and concise description of what the fix does.
10 |
--------------------------------------------------------------------------------
/infection.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "vendor/infection/infection/resources/schema.json",
3 | "source": {
4 | "directories": [
5 | "src"
6 | ]
7 | },
8 | "timeout": 30,
9 | "logs": {
10 | "text": "build/infection/infection.log",
11 | "html": "build/infection/infection.html"
12 | },
13 | "mutators": {
14 | "@default": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | src
4 | tests
5 |
6 |
7 |
8 | error
9 |
10 |
11 | ./tests/*
12 |
13 | */vendor/*
14 |
15 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | level: max
3 | paths:
4 | - src
5 | - tests
6 | ignoreErrors:
7 | - '#Call to an undefined method Pest\\PendingCalls\\TestCall\|Pest\\Support\\HigherOrderTapProxy::#'
8 | - '#Cannot access offset .* on mixed#'
9 | - '#Cannot call method .* on Illuminate\\Testing\\PendingCommand\|int#'
10 | - '#Cannot call method .* on mixed#'
11 | - '#Call to an undefined method Prophecy\\Prophecy\\ObjectProphecy#'
12 |
--------------------------------------------------------------------------------
/php-cs-fixer.php:
--------------------------------------------------------------------------------
1 | in([
4 | __DIR__ . '/src',
5 | __DIR__ . '/tests',
6 | ]);
7 |
8 | return (new PhpCsFixer\Config())->setRules([
9 | 'no_unused_imports' => true,
10 | 'trailing_comma_in_multiline' => [
11 | 'after_heredoc' => true,
12 | 'elements' => [
13 | 'arguments',
14 | 'arrays',
15 | 'match',
16 | 'parameters',
17 | ],
18 | ],
19 | ])->setFinder($finder);
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | - Version: #.#.#
8 | - PHP Version:
9 | - Laravel Framework Version:
10 | - Ngrok Version:
11 |
12 | **Describe the bug**
13 | A clear and concise description of what the bug is.
14 |
15 | **To Reproduce**
16 | Steps to reproduce the behavior:
17 | 1. Go to '...'
18 | 2. Click on '....'
19 | 3. Scroll down to '....'
20 | 4. See error
21 |
22 | **Expected behavior**
23 | A clear and concise description of what you expected to happen.
24 |
25 | **Additional context**
26 | Add any other context or screenshots about the problem here.
27 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | tests
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/bug_not_reported.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | - Version: #.#.#
6 | - PHP Version:
7 | - Laravel Framework Version:
8 | - Ngrok Version:
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Additional context**
24 | Add any other context or screenshots about the problem here.
25 |
26 | **Describe the fix**
27 | A clear and concise description of what the fix does.
28 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/new_feature.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | **Is your new feature related to a problem? Please describe.**
6 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
7 |
8 | **Describe alternatives you've considered**
9 | A clear and concise description of any alternative solutions or features you've considered.
10 |
11 | **Describe the solution you did**
12 | A clear and concise description of what this new feature does.
13 | In addition, please describe the benefit to end users, the reasons it does not break any existing features, etc.
14 |
15 | **Additional context**
16 | Add any other context or screenshots about the new feature here.
17 |
--------------------------------------------------------------------------------
/CHANGELOG-3.x.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [Unreleased](https://github.com/jn-jairo/laravel-ngrok/compare/v3.0.3...3.x)
4 |
5 | ## [v3.0.3 (2025-02-26)](https://github.com/jn-jairo/laravel-ngrok/compare/v3.0.2...v3.0.3)
6 |
7 | ### Added
8 | - Laravel 12 support
9 |
10 | ## [v3.0.2 (2024-03-14)](https://github.com/jn-jairo/laravel-ngrok/compare/v3.0.1...v3.0.2)
11 |
12 | ### Added
13 | - Laravel 11 support
14 |
15 | ## [v3.0.1 (2023-04-12)](https://github.com/jn-jairo/laravel-ngrok/compare/v3.0.0...v3.0.1)
16 |
17 | ### Added
18 | - New ngrok domains
19 |
20 | ## [v3.0.0 (2023-02-25)](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.4...v3.0.0)
21 |
22 | ### Added
23 | - Laravel 10 support
24 | - Static analysis
25 | - Mutation testing
26 |
27 | ### Changed
28 | - Minimal PHP version 8.1
29 | - Minimal Laravel version 8.83
30 | - Tests using Pest
31 | - Code style PSR-12
32 |
--------------------------------------------------------------------------------
/CHANGELOG-2.x.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [Unreleased](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.4...2.x)
4 |
5 | ## [v2.0.4 (2023-01-13)](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.3...v2.0.4)
6 |
7 | ### Added
8 | - Ngrok 3 support
9 |
10 | ## [v2.0.3 (2022-03-03)](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.2...v2.0.3)
11 |
12 | ### Added
13 | - `--host` and `--extra` options
14 | - Allow ngrok url with region
15 |
16 | ## [v2.0.2 (2022-02-11)](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.1...v2.0.2)
17 |
18 | ### Added
19 | - Laravel 9 support
20 | - New ngrok url format
21 |
22 | ## [v2.0.1 (2021-09-01)](https://github.com/jn-jairo/laravel-ngrok/compare/v2.0.0...v2.0.1)
23 |
24 | ### Added
25 | - PHP 8 support
26 |
27 | ## [v2.0.0 (2020-09-09)](https://github.com/jn-jairo/laravel-ngrok/compare/v1.0.1...v2.0.0)
28 |
29 | ### Added
30 | - Laravel 8 support
31 |
32 | ### Changed
33 | - Minimal PHP version 7.3
34 | - Minimal Laravel version 6
35 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Jairo Correa
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CHANGELOG-1.x.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [Unreleased](https://github.com/jn-jairo/laravel-ngrok/compare/v1.0.1...1.x)
4 |
5 | ## [v1.0.1 (2020-08-13)](https://github.com/jn-jairo/laravel-ngrok/compare/v1.0.0...v1.0.1)
6 |
7 | ### Added
8 | - Travis PHP 7.4
9 | - `guzzlehttp/guzzle` version `^7.0`
10 |
11 | ## [v1.0.0 (2020-03-08)](https://github.com/jn-jairo/laravel-ngrok/compare/v0.0.4...v1.0.0)
12 |
13 | ### Added
14 | - Laravel 7 support
15 |
16 | ## [v0.0.4 (2019-09-14)](https://github.com/jn-jairo/laravel-ngrok/compare/v0.0.3...v0.0.4)
17 |
18 | ### Added
19 | - Laravel 6 support
20 | - Test using [orchestral/testbench](https://github.com/orchestral/testbench)
21 |
22 | ### Changed
23 | - Minimal PHP version 7.2
24 | - Minimal Laravel version 5.8
25 |
26 | ## [v0.0.3 (2019-03-02)](https://github.com/jn-jairo/laravel-ngrok/compare/v0.0.2...v0.0.3)
27 |
28 | ### Added
29 | - Laravel 5.8 support
30 |
31 | ## [v0.0.2 (2018-11-03)](https://github.com/jn-jairo/laravel-ngrok/compare/v0.0.1...v0.0.2)
32 |
33 | ### Fixed
34 | - Pagination url
35 |
36 | ## [v0.0.1 (2018-10-14)](https://github.com/jn-jairo/laravel-ngrok/commit/f5ffe623bd7c075c3c9eb58655e3841192f9b7d4)
37 | - Ngrok command
38 |
--------------------------------------------------------------------------------
/phpunit-coverage.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | tests
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | ./src
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jn-jairo/laravel-ngrok",
3 | "description": "Share Laravel application with ngrok.",
4 | "keywords": [
5 | "jn-jairo",
6 | "laravel-ngrok"
7 | ],
8 | "homepage": "https://github.com/jn-jairo/laravel-ngrok",
9 | "license": "MIT",
10 | "authors": [
11 | {
12 | "name": "Jairo Correa",
13 | "email": "jn.j41r0@gmail.com"
14 | }
15 | ],
16 | "require": {
17 | "php": "^8.1",
18 | "guzzlehttp/guzzle": "^6.5.8|^7.4.5",
19 | "illuminate/console": "^8.83|^9.0|^10.0|^11.0|^12.0",
20 | "illuminate/http": "^8.83|^9.0|^10.0|^11.0|^12.0",
21 | "illuminate/pagination": "^8.83|^9.0|^10.0|^11.0|^12.0",
22 | "illuminate/routing": "^8.83|^9.0|^10.0|^11.0|^12.0",
23 | "illuminate/support": "^8.83|^9.0|^10.0|^11.0|^12.0",
24 | "symfony/process": "^5.4|^6.0|^7.0"
25 | },
26 | "require-dev": {
27 | "orchestra/testbench": "^6.24|^7.0|^8.0|^9.0|^10.0",
28 | "pestphp/pest": "^1.22|^2.34|^3.7.4",
29 | "phpspec/prophecy": "^1.17",
30 | "phpspec/prophecy-phpunit": "^2.0",
31 | "webmozart/assert": "^1.11"
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "JnJairo\\Laravel\\Ngrok\\": "src"
36 | }
37 | },
38 | "autoload-dev": {
39 | "psr-4": {
40 | "JnJairo\\Laravel\\Ngrok\\Tests\\": "tests"
41 | }
42 | },
43 | "config": {
44 | "sort-packages": true,
45 | "allow-plugins": {
46 | "pestphp/pest-plugin": true
47 | }
48 | },
49 | "extra": {
50 | "laravel": {
51 | "providers": [
52 | "JnJairo\\Laravel\\Ngrok\\NgrokServiceProvider"
53 | ]
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/NgrokProcessBuilder.php:
--------------------------------------------------------------------------------
1 | setWorkingDirectory($cwd);
22 | }
23 |
24 | /**
25 | * Set the current working directory.
26 | *
27 | * @param string $cwd
28 | */
29 | public function setWorkingDirectory(string $cwd = null): void
30 | {
31 | $this->cwd = $cwd;
32 | }
33 |
34 | /**
35 | * Get the current working directory.
36 | *
37 | * @return string
38 | */
39 | public function getWorkingDirectory(): ?string
40 | {
41 | return $this->cwd;
42 | }
43 |
44 | /**
45 | * Build ngrok command.
46 | *
47 | * @param string $hostHeader
48 | * @param string $port
49 | * @param string $host
50 | * @param array $extra
51 | * @return \Symfony\Component\Process\Process
52 | */
53 | public function buildProcess(
54 | string $hostHeader = '',
55 | string $port = '80',
56 | string $host = '',
57 | array $extra = [],
58 | ): Process {
59 | $command = ['ngrok', 'http', '--log', 'stdout'];
60 |
61 | $command = array_merge($command, $extra);
62 |
63 | if ($hostHeader !== '') {
64 | $command[] = '--host-header';
65 | $command[] = $hostHeader;
66 | }
67 |
68 | if ($host !== '') {
69 | $command[] = $host . ':' . ($port ?: '80');
70 | } else {
71 | $command[] = $port ?: '80';
72 | }
73 |
74 | return new Process($command, $this->getWorkingDirectory(), null, null, null);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/tests/NgrokWebServiceTest.php:
--------------------------------------------------------------------------------
1 | 'http://0000-0000.ngrok-free.app',
14 | 'config' => ['addr' => 'localhost:80'],
15 | ],
16 | [
17 | 'public_url' => 'https://0000-0000.ngrok-free.app',
18 | 'config' => ['addr' => 'localhost:80'],
19 | ],
20 | ];
21 |
22 | $json = json_encode(['tunnels' => $tunnels]);
23 | $emptyJson = json_encode(['tunnels' => []]);
24 |
25 | $dataset = [
26 | 'valid' => [
27 | $json,
28 | $tunnels,
29 | ],
30 | 'empty' => [
31 | $emptyJson,
32 | [],
33 | ],
34 | 'invalid' => [
35 | '',
36 | [],
37 | ],
38 | ];
39 |
40 | it('can get tunnels', function (
41 | string $json,
42 | array $tunnels,
43 | ) {
44 | /**
45 | * @var \Prophecy\Prophecy\ObjectProphecy<\Psr\Http\Message\StreamInterface> $stream
46 | */
47 | $stream = prophesize(StreamInterface::class);
48 | $stream->__toString()->willReturn($json)->shouldBeCalled();
49 |
50 | /**
51 | * @var \Prophecy\Prophecy\ObjectProphecy<\GuzzleHttp\Psr7\Response> $response
52 | */
53 | $response = prophesize(Response::class);
54 | $response->getBody()->willReturn($stream->reveal())->shouldBeCalled();
55 |
56 | /**
57 | * @var \Prophecy\Prophecy\ObjectProphecy<\GuzzleHttp\Client> $httpClient
58 | */
59 | $httpClient = prophesize(Client::class);
60 | $httpClient->request(
61 | 'GET',
62 | 'http://127.0.0.1:4040/api/tunnels',
63 | )->willReturn(
64 | $response->reveal(),
65 | )->shouldBeCalled();
66 |
67 | $webService = new NgrokWebService($httpClient->reveal());
68 | expect($webService->getTunnels())
69 | ->toBe($tunnels);
70 | })->with($dataset);
71 |
--------------------------------------------------------------------------------
/src/NgrokWebService.php:
--------------------------------------------------------------------------------
1 | setHttpClient($httpClient);
30 | $this->setUrl($url);
31 | }
32 |
33 | /**
34 | * Set the web service url.
35 | *
36 | * @param string $url
37 | */
38 | public function setUrl(string $url): void
39 | {
40 | $this->url = $url;
41 | }
42 |
43 | /**
44 | * Get the web service url.
45 | *
46 | * @return string
47 | */
48 | public function getUrl(): string
49 | {
50 | return $this->url;
51 | }
52 |
53 | /**
54 | * Set the http client.
55 | *
56 | * @param \GuzzleHttp\Client $httpClient
57 | */
58 | public function setHttpClient(Client $httpClient): void
59 | {
60 | $this->httpClient = $httpClient;
61 | }
62 |
63 | /**
64 | * Get the http client.
65 | *
66 | * @return \GuzzleHttp\Client
67 | */
68 | public function getHttpClient(): Client
69 | {
70 | return $this->httpClient;
71 | }
72 |
73 | /**
74 | * Request the tunnels.
75 | *
76 | * @return array>
77 | */
78 | public function getTunnels(): array
79 | {
80 | $tunnels = [];
81 |
82 | $response = json_decode(
83 | $this->getHttpClient()->request(
84 | 'GET',
85 | $this->getUrl() . '/api/tunnels',
86 | )->getBody(),
87 | true,
88 | );
89 |
90 | if ($response !== false && isset($response['tunnels']) && ! empty($response['tunnels'])) {
91 | /**
92 | * @var array> $tunnels
93 | */
94 | $tunnels = $response['tunnels'];
95 | }
96 |
97 | return $tunnels;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/tests/Pest.php:
--------------------------------------------------------------------------------
1 | in(__DIR__);
18 |
19 | /*
20 | |--------------------------------------------------------------------------
21 | | Expectations
22 | |--------------------------------------------------------------------------
23 | |
24 | | When you're writing tests, you often need to check that values meet certain conditions. The
25 | | "expect()" function gives you access to a set of "expectations" methods that you can use
26 | | to assert different things. Of course, you may extend the Expectation API at any time.
27 | |
28 | */
29 |
30 | // expect()->extend('toBeOne', function () {
31 | // return $this->toBe(1);
32 | // });
33 |
34 | /*
35 | |--------------------------------------------------------------------------
36 | | Functions
37 | |--------------------------------------------------------------------------
38 | |
39 | | While Pest is very powerful out-of-the-box, you may have some testing code specific to your
40 | | project that you don't want to repeat in every file. Here you can also expose helpers as
41 | | global functions to help you to reduce the number of lines of code in your test files.
42 | |
43 | */
44 |
45 | /**
46 | * @param mixed ...$args
47 | * @return \Prophecy\Prophecy\ObjectProphecy