mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-30 22:15:54 +03:00
fix(web-info, web-publish): Listen с адресом привязки
web-info брал первое число строки Listen: при `Listen 127.0.0.1:19081` порт выходил 127, URL и проверка TCP были ложными. Теперь разбирается `Listen [host:]port [proto]` (включая IPv6 в скобках), сначала в своём глобальном блоке; явный адрес идёт в URL и в пробу порта. web-publish при перезаписи глобального блока сохраняет адрес привязки, вписанный вручную, — повторная публикация больше не открывает loopback на все интерфейсы; URL в выводе строятся по нему. Стандартный Listen комментируется целой строкой (раньше `Listen 0.0.0.0:80` превращался в мусор, а `Listen [::]:80` оставался активным). Refs #107 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
614206bc5c
commit
933414f2e6
@@ -1,4 +1,4 @@
|
|||||||
# web-info v1.5 — Apache & 1C publication status
|
# web-info v1.6 — Apache & 1C publication status
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
@@ -77,17 +77,34 @@ if (-not (Test-Path $confFile)) {
|
|||||||
|
|
||||||
$confContent = [System.IO.File]::ReadAllText($confFile)
|
$confContent = [System.IO.File]::ReadAllText($confFile)
|
||||||
|
|
||||||
# Extract port from global block
|
# Extract Listen from global block (fallback — whole file): "Listen [host:]port [proto]"
|
||||||
$port = "—"
|
$port = "—"
|
||||||
if ($confContent -match '(?m)^Listen\s+(\d+)') {
|
$listenHost = ""
|
||||||
$port = $Matches[1]
|
$listenScope = $confContent
|
||||||
|
if ($confContent -match '(?s)# --- 1C: global ---(.*?)# --- End: global ---') {
|
||||||
|
$listenScope = $Matches[1]
|
||||||
}
|
}
|
||||||
|
if ($listenScope -match '(?m)^[ \t]*Listen[ \t]+(?:(\[[^\]]+\]|[^\s:\[\]]+):)?(\d+)\b') {
|
||||||
|
$port = $Matches[2]
|
||||||
|
if ($Matches[1] -and @('0.0.0.0', '*', '[::]') -notcontains $Matches[1]) {
|
||||||
|
$listenHost = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Адрес привязки явный — по нему и URL, и проба; иначе все интерфейсы → localhost
|
||||||
|
$urlHost = if ($listenHost) { $listenHost } else { "localhost" }
|
||||||
|
$probeHost = if ($listenHost) { $listenHost.Trim('[', ']') } else { "127.0.0.1" }
|
||||||
# Проверяем именно TCP-порт: запрос к публикации поднял бы сеанс 1С и занял лицензию
|
# Проверяем именно TCP-порт: запрос к публикации поднял бы сеанс 1С и занял лицензию
|
||||||
$portState = ""
|
$portState = ""
|
||||||
if ($port -ne "—") {
|
if ($port -ne "—") {
|
||||||
$client = New-Object System.Net.Sockets.TcpClient
|
# Конструктор по умолчанию — только IPv4: для IPv6-литерала нужно семейство адреса
|
||||||
|
$probeAddr = $null
|
||||||
|
if ([System.Net.IPAddress]::TryParse($probeHost, [ref]$probeAddr)) {
|
||||||
|
$client = New-Object System.Net.Sockets.TcpClient($probeAddr.AddressFamily)
|
||||||
|
} else {
|
||||||
|
$client = New-Object System.Net.Sockets.TcpClient
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$async = $client.BeginConnect("127.0.0.1", [int]$port, $null, $null)
|
$async = $client.BeginConnect($probeHost, [int]$port, $null, $null)
|
||||||
if ($async.AsyncWaitHandle.WaitOne(1000) -and $client.Connected) {
|
if ($async.AsyncWaitHandle.WaitOne(1000) -and $client.Connected) {
|
||||||
$portState = " (слушается)"
|
$portState = " (слушается)"
|
||||||
} else {
|
} else {
|
||||||
@@ -99,7 +116,8 @@ if ($port -ne "—") {
|
|||||||
$client.Close()
|
$client.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-Host "Port: $port$portState"
|
$portLabel = if ($listenHost) { "${listenHost}:$port" } else { $port }
|
||||||
|
Write-Host "Port: $portLabel$portState"
|
||||||
|
|
||||||
# Extract wsap24 path
|
# Extract wsap24 path
|
||||||
if ($confContent -match 'LoadModule\s+_1cws_module\s+"([^"]+)"') {
|
if ($confContent -match 'LoadModule\s+_1cws_module\s+"([^"]+)"') {
|
||||||
@@ -149,7 +167,7 @@ if ($pubMatches.Count -eq 0) {
|
|||||||
}
|
}
|
||||||
$svcLabel = if ($svcTags.Count -gt 0) { " [" + ($svcTags -join " ") + "]" } else { "" }
|
$svcLabel = if ($svcTags.Count -gt 0) { " [" + ($svcTags -join " ") + "]" } else { "" }
|
||||||
|
|
||||||
$url = "http://localhost:$port/$appName"
|
$url = "http://${urlHost}:$port/$appName"
|
||||||
Write-Host " $appName" -ForegroundColor White -NoNewline
|
Write-Host " $appName" -ForegroundColor White -NoNewline
|
||||||
Write-Host " $url" -ForegroundColor Gray -NoNewline
|
Write-Host " $url" -ForegroundColor Gray -NoNewline
|
||||||
Write-Host " $ibInfo" -ForegroundColor DarkGray -NoNewline
|
Write-Host " $ibInfo" -ForegroundColor DarkGray -NoNewline
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# web-info v1.5 — Apache & 1C publication status
|
# web-info v1.6 — Apache & 1C publication status
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -110,20 +110,31 @@ def main():
|
|||||||
with open(conf_file, 'r', encoding='utf-8-sig') as f:
|
with open(conf_file, 'r', encoding='utf-8-sig') as f:
|
||||||
conf_content = f.read()
|
conf_content = f.read()
|
||||||
|
|
||||||
# Extract port from global block
|
# Extract Listen from global block (fallback — whole file): "Listen [host:]port [proto]"
|
||||||
port = '\u2014'
|
port = '\u2014'
|
||||||
m = re.search(r'(?m)^Listen\s+(\d+)', conf_content)
|
listen_host = ''
|
||||||
|
listen_scope = conf_content
|
||||||
|
m = re.search(r'(?s)# --- 1C: global ---(.*?)# --- End: global ---', conf_content)
|
||||||
if m:
|
if m:
|
||||||
port = m.group(1)
|
listen_scope = m.group(1)
|
||||||
|
m = re.search(r'(?mi)^[ \t]*Listen[ \t]+(?:(\[[^\]]+\]|[^\s:\[\]]+):)?(\d+)\b', listen_scope)
|
||||||
|
if m:
|
||||||
|
port = m.group(2)
|
||||||
|
if m.group(1) and m.group(1) not in ('0.0.0.0', '*', '[::]'):
|
||||||
|
listen_host = m.group(1)
|
||||||
|
# Адрес привязки явный — по нему и URL, и проба; иначе все интерфейсы → localhost
|
||||||
|
url_host = listen_host if listen_host else 'localhost'
|
||||||
|
probe_host = listen_host.strip('[]') if listen_host else '127.0.0.1'
|
||||||
# Проверяем именно TCP-порт: запрос к публикации поднял бы сеанс 1С и занял лицензию
|
# Проверяем именно TCP-порт: запрос к публикации поднял бы сеанс 1С и занял лицензию
|
||||||
port_state = ''
|
port_state = ''
|
||||||
if port != '—':
|
if port != '—':
|
||||||
try:
|
try:
|
||||||
with socket.create_connection(('127.0.0.1', int(port)), timeout=1):
|
with socket.create_connection((probe_host, int(port)), timeout=1):
|
||||||
port_state = ' (слушается)'
|
port_state = ' (слушается)'
|
||||||
except OSError:
|
except OSError:
|
||||||
port_state = ' (не отвечает)'
|
port_state = ' (не отвечает)'
|
||||||
print(f'Port: {port}{port_state}')
|
port_label = f'{listen_host}:{port}' if listen_host else port
|
||||||
|
print(f'Port: {port_label}{port_state}')
|
||||||
|
|
||||||
# Extract wsap24 path
|
# Extract wsap24 path
|
||||||
m = re.search(r'LoadModule\s+_1cws_module\s+"([^"]+)"', conf_content)
|
m = re.search(r'LoadModule\s+_1cws_module\s+"([^"]+)"', conf_content)
|
||||||
@@ -170,7 +181,7 @@ def main():
|
|||||||
svc_tags.append('OData')
|
svc_tags.append('OData')
|
||||||
svc_label = ' [' + ' '.join(svc_tags) + ']' if svc_tags else ''
|
svc_label = ' [' + ' '.join(svc_tags) + ']' if svc_tags else ''
|
||||||
|
|
||||||
url = f'http://localhost:{port}/{app_name}'
|
url = f'http://{url_host}:{port}/{app_name}'
|
||||||
print(f' {app_name} {url} {ib_info}{svc_label}')
|
print(f' {app_name} {url} {ib_info}{svc_label}')
|
||||||
|
|
||||||
# --- Error log ---
|
# --- Error log ---
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# web-publish v1.11 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
|
# web-publish v1.12 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
@@ -349,9 +349,20 @@ $vrdPathFwd = $vrdPath -replace '\\','/'
|
|||||||
# --- Global block (Listen + LoadModule) ---
|
# --- Global block (Listen + LoadModule) ---
|
||||||
$globalMarkerStart = "# --- 1C: global ---"
|
$globalMarkerStart = "# --- 1C: global ---"
|
||||||
$globalMarkerEnd = "# --- End: global ---"
|
$globalMarkerEnd = "# --- End: global ---"
|
||||||
|
# Адрес привязки, вписанный в наш блок руками (Listen 127.0.0.1:port), при перезаписи сохраняем
|
||||||
|
$listenHost = ""
|
||||||
|
$globalPattern = [regex]::Escape($globalMarkerStart) + '([\s\S]*?)' + [regex]::Escape($globalMarkerEnd)
|
||||||
|
if ($confContent -match $globalPattern -and
|
||||||
|
$Matches[1] -match '(?m)^[ \t]*Listen[ \t]+(?:(\[[^\]]+\]|[^\s:\[\]]+):)?(\d+)\b') {
|
||||||
|
if ($Matches[1] -and @('0.0.0.0', '*', '[::]') -notcontains $Matches[1]) {
|
||||||
|
$listenHost = $Matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$listenArg = if ($listenHost) { "${listenHost}:$Port" } else { "$Port" }
|
||||||
|
$urlHost = if ($listenHost) { $listenHost } else { "localhost" }
|
||||||
$globalBlock = @"
|
$globalBlock = @"
|
||||||
$globalMarkerStart
|
$globalMarkerStart
|
||||||
Listen $Port
|
Listen $listenArg
|
||||||
LoadModule _1cws_module "$wsapDllFwd"
|
LoadModule _1cws_module "$wsapDllFwd"
|
||||||
$globalMarkerEnd
|
$globalMarkerEnd
|
||||||
"@
|
"@
|
||||||
@@ -362,7 +373,7 @@ if ($confContent -match [regex]::Escape($globalMarkerStart)) {
|
|||||||
$confContent = [regex]::Replace($confContent, $pattern, $globalBlock)
|
$confContent = [regex]::Replace($confContent, $pattern, $globalBlock)
|
||||||
} else {
|
} else {
|
||||||
# Comment out default Listen to avoid port conflict
|
# Comment out default Listen to avoid port conflict
|
||||||
$confContent = $confContent -replace '(?m)^(Listen\s+\d+)', '#$1 # commented by web-publish'
|
$confContent = $confContent -replace '(?m)^([ \t]*Listen\b[^\r\n]*)', '#$1 # commented by web-publish'
|
||||||
# Append global block
|
# Append global block
|
||||||
$confContent = $confContent.TrimEnd() + "`n`n" + $globalBlock + "`n"
|
$confContent = $confContent.TrimEnd() + "`n`n" + $globalBlock + "`n"
|
||||||
}
|
}
|
||||||
@@ -460,7 +471,7 @@ if ($httpdCheck) {
|
|||||||
# --- Result ---
|
# --- Result ---
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "=== Публикация готова ===" -ForegroundColor Green
|
Write-Host "=== Публикация готова ===" -ForegroundColor Green
|
||||||
Write-Host "URL: http://localhost:$Port/$AppName" -ForegroundColor Cyan
|
Write-Host "URL: http://${urlHost}:$Port/$AppName" -ForegroundColor Cyan
|
||||||
Write-Host "OData: http://localhost:$Port/$AppName/odata/standard.odata" -ForegroundColor Cyan
|
Write-Host "OData: http://${urlHost}:$Port/$AppName/odata/standard.odata" -ForegroundColor Cyan
|
||||||
Write-Host "HTTP-сервисы: http://localhost:$Port/$AppName/hs/<RootUrl>/..." -ForegroundColor Cyan
|
Write-Host "HTTP-сервисы: http://${urlHost}:$Port/$AppName/hs/<RootUrl>/..." -ForegroundColor Cyan
|
||||||
Write-Host "Web-сервисы: http://localhost:$Port/$AppName/ws/<Имя>?wsdl" -ForegroundColor Cyan
|
Write-Host "Web-сервисы: http://${urlHost}:$Port/$AppName/ws/<Имя>?wsdl" -ForegroundColor Cyan
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# web-publish v1.11 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
|
# web-publish v1.12 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -408,9 +408,19 @@ def main():
|
|||||||
# --- Global block (Listen + LoadModule) ---
|
# --- Global block (Listen + LoadModule) ---
|
||||||
global_marker_start = '# --- 1C: global ---'
|
global_marker_start = '# --- 1C: global ---'
|
||||||
global_marker_end = '# --- End: global ---'
|
global_marker_end = '# --- End: global ---'
|
||||||
|
# Адрес привязки, вписанный в наш блок руками (Listen 127.0.0.1:port), при перезаписи сохраняем
|
||||||
|
listen_host = ''
|
||||||
|
global_pattern = re.escape(global_marker_start) + r'([\s\S]*?)' + re.escape(global_marker_end)
|
||||||
|
m = re.search(global_pattern, conf_content)
|
||||||
|
if m:
|
||||||
|
m = re.search(r'(?mi)^[ \t]*Listen[ \t]+(?:(\[[^\]]+\]|[^\s:\[\]]+):)?(\d+)\b', m.group(1))
|
||||||
|
if m and m.group(1) and m.group(1) not in ('0.0.0.0', '*', '[::]'):
|
||||||
|
listen_host = m.group(1)
|
||||||
|
listen_arg = f'{listen_host}:{port}' if listen_host else f'{port}'
|
||||||
|
url_host = listen_host if listen_host else 'localhost'
|
||||||
global_block = (
|
global_block = (
|
||||||
f'{global_marker_start}\n'
|
f'{global_marker_start}\n'
|
||||||
f'Listen {port}\n'
|
f'Listen {listen_arg}\n'
|
||||||
f'LoadModule _1cws_module "{wsap_dll_fwd}"\n'
|
f'LoadModule _1cws_module "{wsap_dll_fwd}"\n'
|
||||||
f'{global_marker_end}'
|
f'{global_marker_end}'
|
||||||
)
|
)
|
||||||
@@ -421,7 +431,7 @@ def main():
|
|||||||
conf_content = re.sub(pattern, global_block, conf_content)
|
conf_content = re.sub(pattern, global_block, conf_content)
|
||||||
else:
|
else:
|
||||||
# Comment out default Listen to avoid port conflict
|
# Comment out default Listen to avoid port conflict
|
||||||
conf_content = re.sub(r'(?m)^(Listen\s+\d+)', r'#\1 # commented by web-publish', conf_content)
|
conf_content = re.sub(r'(?mi)^([ \t]*Listen\b[^\r\n]*)', r'#\1 # commented by web-publish', conf_content)
|
||||||
# Append global block
|
# Append global block
|
||||||
conf_content = conf_content.rstrip() + '\n\n' + global_block + '\n'
|
conf_content = conf_content.rstrip() + '\n\n' + global_block + '\n'
|
||||||
|
|
||||||
@@ -536,10 +546,10 @@ def main():
|
|||||||
# --- Result ---
|
# --- Result ---
|
||||||
print('')
|
print('')
|
||||||
print('=== Публикация готова ===')
|
print('=== Публикация готова ===')
|
||||||
print(f'URL: http://localhost:{port}/{app_name}')
|
print(f'URL: http://{url_host}:{port}/{app_name}')
|
||||||
print(f'OData: http://localhost:{port}/{app_name}/odata/standard.odata')
|
print(f'OData: http://{url_host}:{port}/{app_name}/odata/standard.odata')
|
||||||
print(f'HTTP-сервисы: http://localhost:{port}/{app_name}/hs/<RootUrl>/...')
|
print(f'HTTP-сервисы: http://{url_host}:{port}/{app_name}/hs/<RootUrl>/...')
|
||||||
print(f'Web-сервисы: http://localhost:{port}/{app_name}/ws/<Имя>?wsdl')
|
print(f'Web-сервисы: http://{url_host}:{port}/{app_name}/ws/<Имя>?wsdl')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ Listen 8081
|
|||||||
|
|
||||||
Порт для веб-клиента. По умолчанию `8081` (стандартный `80` может быть занят).
|
Порт для веб-клиента. По умолчанию `8081` (стандартный `80` может быть занят).
|
||||||
|
|
||||||
|
Адрес привязки, вписанный в глобальный блок вручную (`Listen 127.0.0.1:8081`, `Listen [::1]:8081`), при повторной публикации сохраняется — меняется только порт; URL в выводе `web-publish` и `web-info` строятся по этому адресу. `0.0.0.0`, `*`, `[::]` считаются «все интерфейсы» → `localhost`.
|
||||||
|
|
||||||
### Alias + Directory
|
### Alias + Directory
|
||||||
|
|
||||||
Для каждой публикации добавляется блок:
|
Для каждой публикации добавляется блок:
|
||||||
|
|||||||
Reference in New Issue
Block a user