fix(application): enhance domain handling by replacing both dots and dashes with underscores for HTML form binding

This commit is contained in:
Andras Bacsai 2025-09-25 13:19:12 +02:00
parent 2eef83f072
commit 708a08fdd6
4 changed files with 65 additions and 38 deletions

View file

@ -210,10 +210,10 @@ public function mount()
} }
} }
$this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : []; $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
// Convert service names with dots to use underscores for HTML form binding // Convert service names with dots and dashes to use underscores for HTML form binding
$sanitizedDomains = []; $sanitizedDomains = [];
foreach ($this->parsedServiceDomains as $serviceName => $domain) { foreach ($this->parsedServiceDomains as $serviceName => $domain) {
$sanitizedKey = str($serviceName)->slug('_')->toString(); $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$sanitizedDomains[$sanitizedKey] = $domain; $sanitizedDomains[$sanitizedKey] = $domain;
} }
$this->parsedServiceDomains = $sanitizedDomains; $this->parsedServiceDomains = $sanitizedDomains;
@ -305,10 +305,10 @@ public function loadComposeFile($isInit = false, $showToast = true)
// Refresh parsedServiceDomains to reflect any changes in docker_compose_domains // Refresh parsedServiceDomains to reflect any changes in docker_compose_domains
$this->application->refresh(); $this->application->refresh();
$this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : []; $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
// Convert service names with dots to use underscores for HTML form binding // Convert service names with dots and dashes to use underscores for HTML form binding
$sanitizedDomains = []; $sanitizedDomains = [];
foreach ($this->parsedServiceDomains as $serviceName => $domain) { foreach ($this->parsedServiceDomains as $serviceName => $domain) {
$sanitizedKey = str($serviceName)->slug('_')->toString(); $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$sanitizedDomains[$sanitizedKey] = $domain; $sanitizedDomains[$sanitizedKey] = $domain;
} }
$this->parsedServiceDomains = $sanitizedDomains; $this->parsedServiceDomains = $sanitizedDomains;
@ -334,7 +334,7 @@ public function generateDomain(string $serviceName)
$uuid = new Cuid2; $uuid = new Cuid2;
$domain = generateUrl(server: $this->application->destination->server, random: $uuid); $domain = generateUrl(server: $this->application->destination->server, random: $uuid);
$sanitizedKey = str($serviceName)->slug('_')->toString(); $sanitizedKey = str($serviceName)->replace('-', '_')->replace('.', '_')->toString();
$this->parsedServiceDomains[$sanitizedKey]['domain'] = $domain; $this->parsedServiceDomains[$sanitizedKey]['domain'] = $domain;
// Convert back to original service names for storage // Convert back to original service names for storage
@ -344,7 +344,7 @@ public function generateDomain(string $serviceName)
$originalServiceName = $key; $originalServiceName = $key;
if (isset($this->parsedServices['services'])) { if (isset($this->parsedServices['services'])) {
foreach ($this->parsedServices['services'] as $originalName => $service) { foreach ($this->parsedServices['services'] as $originalName => $service) {
if (str($originalName)->slug('_')->toString() === $key) { if (str($originalName)->replace('-', '_')->replace('.', '_')->toString() === $key) {
$originalServiceName = $originalName; $originalServiceName = $originalName;
break; break;
} }

View file

@ -1479,14 +1479,14 @@ public function loadComposeFile($isInit = false)
if ($this->docker_compose_domains) { if ($this->docker_compose_domains) {
$json = collect(json_decode($this->docker_compose_domains)); $json = collect(json_decode($this->docker_compose_domains));
foreach ($json as $key => $value) { foreach ($json as $key => $value) {
if (str($key)->contains('-')) { if (str($key)->contains('-') || str($key)->contains('.')) {
$key = str($key)->replace('-', '_')->replace('.', '_'); $key = str($key)->replace('-', '_')->replace('.', '_');
} }
$json->put((string) $key, $value); $json->put((string) $key, $value);
} }
$services = collect(data_get($parsedServices, 'services', [])); $services = collect(data_get($parsedServices, 'services', []));
foreach ($services as $name => $service) { foreach ($services as $name => $service) {
if (str($name)->contains('-')) { if (str($name)->contains('-') || str($name)->contains('.')) {
$replacedName = str($name)->replace('-', '_')->replace('.', '_'); $replacedName = str($name)->replace('-', '_')->replace('.', '_');
$services->put((string) $replacedName, $service); $services->put((string) $replacedName, $service);
$services->forget((string) $name); $services->forget((string) $name);
@ -1503,6 +1503,7 @@ public function loadComposeFile($isInit = false)
} else { } else {
$this->docker_compose_domains = null; $this->docker_compose_domains = null;
} }
ray($this->docker_compose_domains);
$this->save(); $this->save();
} }

View file

@ -385,21 +385,34 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
'is_preview' => false, 'is_preview' => false,
]); ]);
if ($resource->build_pack === 'dockercompose') { if ($resource->build_pack === 'dockercompose') {
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]); // Check if a service with this name actually exists
$domainExists = data_get($domains->get($fqdnFor), 'domain'); $serviceExists = false;
$envExists = $resource->environment_variables()->where('key', $key->value())->first(); foreach ($services as $serviceName => $service) {
if (str($domainExists)->replace('http://', '')->replace('https://', '')->value() !== $envExists->value) { $transformedServiceName = str($serviceName)->replace('-', '_')->replace('.', '_')->value();
$envExists->update([ if ($transformedServiceName === $fqdnFor) {
'value' => $url, $serviceExists = true;
]); break;
}
} }
if (is_null($domainExists)) {
// Put URL in the domains array instead of FQDN // Only add domain if the service exists
$domains->put((string) $fqdnFor, [ if ($serviceExists) {
'domain' => $url, $domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]);
]); $domainExists = data_get($domains->get($fqdnFor), 'domain');
$resource->docker_compose_domains = $domains->toJson(); $envExists = $resource->environment_variables()->where('key', $key->value())->first();
$resource->save(); if (str($domainExists)->replace('http://', '')->replace('https://', '')->value() !== $envExists->value) {
$envExists->update([
'value' => $url,
]);
}
if (is_null($domainExists)) {
// Put URL in the domains array instead of FQDN
$domains->put((string) $fqdnFor, [
'domain' => $url,
]);
$resource->docker_compose_domains = $domains->toJson();
$resource->save();
}
} }
} }
} elseif ($command->value() === 'URL') { } elseif ($command->value() === 'URL') {
@ -418,20 +431,33 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
'is_preview' => false, 'is_preview' => false,
]); ]);
if ($resource->build_pack === 'dockercompose') { if ($resource->build_pack === 'dockercompose') {
$domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]); // Check if a service with this name actually exists
$domainExists = data_get($domains->get($urlFor), 'domain'); $serviceExists = false;
$envExists = $resource->environment_variables()->where('key', $key->value())->first(); foreach ($services as $serviceName => $service) {
if ($domainExists !== $envExists->value) { $transformedServiceName = str($serviceName)->replace('-', '_')->replace('.', '_')->value();
$envExists->update([ if ($transformedServiceName === $urlFor) {
'value' => $url, $serviceExists = true;
]); break;
}
} }
if (is_null($domainExists)) {
$domains->put((string) $urlFor, [ // Only add domain if the service exists
'domain' => $url, if ($serviceExists) {
]); $domains = collect(json_decode(data_get($resource, 'docker_compose_domains'))) ?? collect([]);
$resource->docker_compose_domains = $domains->toJson(); $domainExists = data_get($domains->get($urlFor), 'domain');
$resource->save(); $envExists = $resource->environment_variables()->where('key', $key->value())->first();
if ($domainExists !== $envExists->value) {
$envExists->update([
'value' => $url,
]);
}
if (is_null($domainExists)) {
$domains->put((string) $urlFor, [
'domain' => $url,
]);
$resource->docker_compose_domains = $domains->toJson();
$resource->save();
}
} }
} }
} else { } else {
@ -910,7 +936,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
$preview = $resource->previews()->find($preview_id); $preview = $resource->previews()->find($preview_id);
$docker_compose_domains = collect(json_decode(data_get($preview, 'docker_compose_domains'))); $docker_compose_domains = collect(json_decode(data_get($preview, 'docker_compose_domains')));
if ($docker_compose_domains->count() > 0) { if ($docker_compose_domains->count() > 0) {
$found_fqdn = data_get($docker_compose_domains, "$serviceName.domain"); $found_fqdn = data_get($docker_compose_domains, "$changedServiceName.domain");
if ($found_fqdn) { if ($found_fqdn) {
$fqdns = collect($found_fqdn); $fqdns = collect($found_fqdn);
} else { } else {

View file

@ -50,8 +50,8 @@
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<x-forms.input <x-forms.input
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. " helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "
label="Domains for {{ str($serviceName)->headline() }}" label="Domains for {{ $serviceName }}"
id="parsedServiceDomains.{{ str($serviceName)->slug('_') }}.domain" id="parsedServiceDomains.{{ str($serviceName)->replace('-', '_')->replace('.', '_') }}.domain"
x-bind:disabled="shouldDisable()"></x-forms.input> x-bind:disabled="shouldDisable()"></x-forms.input>
@can('update', $application) @can('update', $application)
<x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate <x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate