Skip to content

Commit f9a9f7d

Browse files
authored
Merge pull request #1437 from RobertBoes/feat/proxy-multiple-domains
Add support for proxying multiple domains at once
2 parents 66539bd + a3ea286 commit f9a9f7d

File tree

3 files changed

+250
-26
lines changed

3 files changed

+250
-26
lines changed

cli/Valet/Site.php

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -768,31 +768,34 @@ public function proxyCreate(string $url, string $host, bool $secure = false): vo
768768
}
769769

770770
$tld = $this->config->read()['tld'];
771-
if (! ends_with($url, '.'.$tld)) {
772-
$url .= '.'.$tld;
773-
}
774771

775-
$siteConf = $this->replaceOldLoopbackWithNew(
776-
$this->files->getStub($secure ? 'secure.proxy.valet.conf' : 'proxy.valet.conf'),
777-
'VALET_LOOPBACK',
778-
$this->valetLoopback()
779-
);
772+
foreach (explode(',', $url) as $proxyUrl) {
773+
if (! ends_with($proxyUrl, '.'.$tld)) {
774+
$proxyUrl .= '.'.$tld;
775+
}
780776

781-
$siteConf = str_replace(
782-
['VALET_HOME_PATH', 'VALET_SERVER_PATH', 'VALET_STATIC_PREFIX', 'VALET_SITE', 'VALET_PROXY_HOST'],
783-
[$this->valetHomePath(), VALET_SERVER_PATH, VALET_STATIC_PREFIX, $url, $host],
784-
$siteConf
785-
);
777+
$siteConf = $this->replaceOldLoopbackWithNew(
778+
$this->files->getStub($secure ? 'secure.proxy.valet.conf' : 'proxy.valet.conf'),
779+
'VALET_LOOPBACK',
780+
$this->valetLoopback()
781+
);
786782

787-
if ($secure) {
788-
$this->secure($url, $siteConf);
789-
} else {
790-
$this->put($url, $siteConf);
791-
}
783+
$siteConf = str_replace(
784+
['VALET_HOME_PATH', 'VALET_SERVER_PATH', 'VALET_STATIC_PREFIX', 'VALET_SITE', 'VALET_PROXY_HOST'],
785+
[$this->valetHomePath(), VALET_SERVER_PATH, VALET_STATIC_PREFIX, $proxyUrl, $host],
786+
$siteConf
787+
);
788+
789+
if ($secure) {
790+
$this->secure($proxyUrl, $siteConf);
791+
} else {
792+
$this->put($proxyUrl, $siteConf);
793+
}
792794

793-
$protocol = $secure ? 'https' : 'http';
795+
$protocol = $secure ? 'https' : 'http';
794796

795-
info('Valet will now proxy ['.$protocol.'://'.$url.'] traffic to ['.$host.'].');
797+
info('Valet will now proxy ['.$protocol.'://'.$proxyUrl.'] traffic to ['.$host.'].');
798+
}
796799
}
797800

798801
/**
@@ -801,14 +804,17 @@ public function proxyCreate(string $url, string $host, bool $secure = false): vo
801804
public function proxyDelete(string $url): void
802805
{
803806
$tld = $this->config->read()['tld'];
804-
if (! ends_with($url, '.'.$tld)) {
805-
$url .= '.'.$tld;
806-
}
807807

808-
$this->unsecure($url);
809-
$this->files->unlink($this->nginxPath($url));
808+
foreach (explode(',', $url) as $proxyUrl) {
809+
if (! ends_with($proxyUrl, '.'.$tld)) {
810+
$proxyUrl .= '.'.$tld;
811+
}
810812

811-
info('Valet will no longer proxy [https://'.$url.'].');
813+
$this->unsecure($proxyUrl);
814+
$this->files->unlink($this->nginxPath($proxyUrl));
815+
816+
info('Valet will no longer proxy [https://'.$proxyUrl.'].');
817+
}
812818
}
813819

814820
/**

tests/CliTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,23 @@ public function test_proxy_command()
462462
$tester->assertCommandIsSuccessful();
463463
}
464464

465+
public function test_proxy_command_with_multiple_domains()
466+
{
467+
[$app, $tester] = $this->appAndTester();
468+
469+
$site = Mockery::mock(RealSite::class);
470+
$site->shouldReceive('proxyCreate')->with('my-app,subdomain.my-app', 'http://127.0.0.1:8000', false)->once();
471+
472+
$nginx = Mockery::mock(Nginx::class);
473+
$nginx->shouldReceive('restart')->once();
474+
475+
swap(Nginx::class, $nginx);
476+
swap(RealSite::class, $site);
477+
478+
$tester->run(['command' => 'proxy', 'domain' => 'my-app,subdomain.my-app', 'host' => 'http://127.0.0.1:8000']);
479+
$tester->assertCommandIsSuccessful();
480+
}
481+
465482
public function test_unproxy_command()
466483
{
467484
[$app, $tester] = $this->appAndTester();

tests/SiteTest.php

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,49 @@ public function test_add_proxy()
406406
], $site->proxies()->all());
407407
}
408408

409+
public function test_add_multiple_proxies()
410+
{
411+
$config = Mockery::mock(Configuration::class);
412+
$config->shouldReceive('read')
413+
->andReturn(['tld' => 'test', 'loopback' => VALET_LOOPBACK]);
414+
415+
swap(Configuration::class, $config);
416+
417+
swap(CommandLine::class, resolve(CommandLineFake::class));
418+
419+
/** @var FixturesSiteFake $site */
420+
$site = resolve(FixturesSiteFake::class);
421+
422+
$site->useOutput();
423+
424+
$site->assertCertificateNotExists('my-new-proxy.com.test');
425+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
426+
$site->assertNginxNotExists('my-new-proxy.com.test');
427+
$site->assertNginxNotExists('my-other-new-proxy.com.test');
428+
429+
$site->proxyCreate('my-new-proxy.com,my-other-new-proxy.com', 'https://127.0.0.1:9443', true);
430+
431+
$site->assertCertificateExistsWithCounterValue('my-new-proxy.com.test', 0);
432+
$site->assertCertificateExistsWithCounterValue('my-other-new-proxy.com.test', 1);
433+
$site->assertNginxExists('my-new-proxy.com.test');
434+
$site->assertNginxExists('my-other-new-proxy.com.test');
435+
436+
$this->assertEquals([
437+
'my-new-proxy.com' => [
438+
'site' => 'my-new-proxy.com',
439+
'secured' => ' X',
440+
'url' => 'https://my-new-proxy.com.test',
441+
'path' => 'https://127.0.0.1:9443',
442+
],
443+
'my-other-new-proxy.com' => [
444+
'site' => 'my-other-new-proxy.com',
445+
'secured' => ' X',
446+
'url' => 'https://my-other-new-proxy.com.test',
447+
'path' => 'https://127.0.0.1:9443',
448+
],
449+
], $site->proxies()->all());
450+
}
451+
409452
public function test_add_non_secure_proxy()
410453
{
411454
$config = Mockery::mock(Configuration::class);
@@ -439,6 +482,49 @@ public function test_add_non_secure_proxy()
439482
], $site->proxies()->all());
440483
}
441484

485+
public function test_add_multiple_non_secure_proxies()
486+
{
487+
$config = Mockery::mock(Configuration::class);
488+
$config->shouldReceive('read')
489+
->andReturn(['tld' => 'test', 'loopback' => VALET_LOOPBACK]);
490+
491+
swap(Configuration::class, $config);
492+
493+
swap(CommandLine::class, resolve(CommandLineFake::class));
494+
495+
/** @var FixturesSiteFake $site */
496+
$site = resolve(FixturesSiteFake::class);
497+
498+
$site->useOutput();
499+
500+
$site->assertCertificateNotExists('my-new-proxy.com.test');
501+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
502+
$site->assertNginxNotExists('my-new-proxy.com.test');
503+
$site->assertNginxNotExists('my-other-new-proxy.com.test');
504+
505+
$site->proxyCreate('my-new-proxy.com,my-other-new-proxy.com', 'http://127.0.0.1:9443', false);
506+
507+
$site->assertCertificateNotExists('my-new-proxy.com.test');
508+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
509+
$site->assertNginxExists('my-new-proxy.com.test');
510+
$site->assertNginxExists('my-other-new-proxy.com.test');
511+
512+
$this->assertEquals([
513+
'my-new-proxy.com' => [
514+
'site' => 'my-new-proxy.com',
515+
'secured' => '',
516+
'url' => 'http://my-new-proxy.com.test',
517+
'path' => 'http://127.0.0.1:9443',
518+
],
519+
'my-other-new-proxy.com' => [
520+
'site' => 'my-other-new-proxy.com',
521+
'secured' => '',
522+
'url' => 'http://my-other-new-proxy.com.test',
523+
'path' => 'http://127.0.0.1:9443',
524+
],
525+
], $site->proxies()->all());
526+
}
527+
442528
public function test_add_proxy_clears_previous_proxy_certificate()
443529
{
444530
$config = Mockery::mock(Configuration::class);
@@ -565,6 +651,121 @@ public function test_remove_proxy()
565651
$this->assertEquals([], $site->proxies()->all());
566652
}
567653

654+
public function test_remove_multiple_proxies()
655+
{
656+
$config = Mockery::mock(Configuration::class);
657+
$config->shouldReceive('read')
658+
->andReturn(['tld' => 'test', 'loopback' => VALET_LOOPBACK]);
659+
660+
swap(Configuration::class, $config);
661+
662+
swap(CommandLine::class, resolve(CommandLineFake::class));
663+
664+
/** @var FixturesSiteFake $site */
665+
$site = resolve(FixturesSiteFake::class);
666+
667+
$site->useOutput();
668+
669+
$site->assertCertificateNotExists('my-new-proxy.com.test');
670+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
671+
$site->assertNginxNotExists('my-new-proxy.com.test');
672+
$site->assertNginxNotExists('my-other-new-proxy.com.test');
673+
674+
$this->assertEquals([], $site->proxies()->all());
675+
676+
$site->proxyCreate('my-new-proxy.com,my-other-new-proxy.com', 'https://127.0.0.1:9443', true);
677+
678+
$this->assertEquals([
679+
'my-new-proxy.com' => [
680+
'site' => 'my-new-proxy.com',
681+
'secured' => ' X',
682+
'url' => 'https://my-new-proxy.com.test',
683+
'path' => 'https://127.0.0.1:9443',
684+
],
685+
'my-other-new-proxy.com' => [
686+
'site' => 'my-other-new-proxy.com',
687+
'secured' => ' X',
688+
'url' => 'https://my-other-new-proxy.com.test',
689+
'path' => 'https://127.0.0.1:9443',
690+
],
691+
], $site->proxies()->all());
692+
693+
$site->assertCertificateExists('my-new-proxy.com.test');
694+
$site->assertCertificateExists('my-other-new-proxy.com.test');
695+
$site->assertNginxExists('my-new-proxy.com.test');
696+
$site->assertNginxExists('my-other-new-proxy.com.test');
697+
698+
$site->proxyDelete('my-new-proxy.com,my-other-new-proxy.com');
699+
700+
$site->assertCertificateNotExists('my-new-proxy.com.test');
701+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
702+
$site->assertNginxNotExists('my-new-proxy.com.test');
703+
$site->assertNginxNotExists('my-other-new-proxy.com.test');
704+
705+
$this->assertEquals([], $site->proxies()->all());
706+
}
707+
708+
public function test_remove_single_proxy_from_multiple_proxies()
709+
{
710+
$config = Mockery::mock(Configuration::class);
711+
$config->shouldReceive('read')
712+
->andReturn(['tld' => 'test', 'loopback' => VALET_LOOPBACK]);
713+
714+
swap(Configuration::class, $config);
715+
716+
swap(CommandLine::class, resolve(CommandLineFake::class));
717+
718+
/** @var FixturesSiteFake $site */
719+
$site = resolve(FixturesSiteFake::class);
720+
721+
$site->useOutput();
722+
723+
$site->assertCertificateNotExists('my-new-proxy.com.test');
724+
$site->assertCertificateNotExists('my-other-new-proxy.com.test');
725+
$site->assertNginxNotExists('my-new-proxy.com.test');
726+
$site->assertNginxNotExists('my-other-new-proxy.com.test');
727+
728+
$this->assertEquals([], $site->proxies()->all());
729+
730+
$site->proxyCreate('my-new-proxy.com,my-other-new-proxy.com', 'https://127.0.0.1:9443', true);
731+
732+
$this->assertEquals([
733+
'my-new-proxy.com' => [
734+
'site' => 'my-new-proxy.com',
735+
'secured' => ' X',
736+
'url' => 'https://my-new-proxy.com.test',
737+
'path' => 'https://127.0.0.1:9443',
738+
],
739+
'my-other-new-proxy.com' => [
740+
'site' => 'my-other-new-proxy.com',
741+
'secured' => ' X',
742+
'url' => 'https://my-other-new-proxy.com.test',
743+
'path' => 'https://127.0.0.1:9443',
744+
],
745+
], $site->proxies()->all());
746+
747+
$site->assertCertificateExists('my-new-proxy.com.test');
748+
$site->assertCertificateExists('my-other-new-proxy.com.test');
749+
$site->assertNginxExists('my-new-proxy.com.test');
750+
$site->assertNginxExists('my-other-new-proxy.com.test');
751+
752+
$site->proxyDelete('my-new-proxy.com');
753+
754+
$site->assertCertificateNotExists('my-new-proxy.com.test');
755+
$site->assertCertificateExists('my-other-new-proxy.com.test');
756+
$site->assertNginxNotExists('my-new-proxy.com.test');
757+
$site->assertNginxExists('my-other-new-proxy.com.test');
758+
759+
$this->assertEquals([
760+
'my-other-new-proxy.com' => [
761+
'site' => 'my-other-new-proxy.com',
762+
'secured' => ' X',
763+
'url' => 'https://my-other-new-proxy.com.test',
764+
'path' => 'https://127.0.0.1:9443',
765+
],
766+
], $site->proxies()->all());
767+
}
768+
568769
public function test_gets_site_url_from_directory()
569770
{
570771
$config = Mockery::mock(Configuration::class);

0 commit comments

Comments
 (0)