in development funktionieren Steckdosen, Prod: baseURL fehler

This commit is contained in:
2025-03-12 15:01:18 +01:00
parent 7f818f5463
commit bf4043004b
9 changed files with 272 additions and 21 deletions
+3
View File
@@ -67,6 +67,9 @@
"defaultConfiguration": "production"
},
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
},
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
+30
View File
@@ -0,0 +1,30 @@
<IfModule mod_headers.c>
# Globale CORS-Einstellungen
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
# OPTIONS Requests behandeln
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
</IfModule>
# Spezifische Konfiguration für Tasmota-Endpoints
<Location "/tasmota1">
ProxyPass "http://10.0.0.31"
ProxyPassReverse "http://10.0.0.31"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
<Location "/tasmota2">
ProxyPass "http://10.0.0.32"
ProxyPassReverse "http://10.0.0.32"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
+143
View File
@@ -0,0 +1,143 @@
ServerRoot "/usr/local/etc/apache24"
Listen 127.0.0.1:915
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_owner_module modules/mod_authz_owner.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule log_config_module modules/mod_log_config.so
#LoadModule logio_module modules/mod_logio.so
LoadModule env_module modules/mod_env.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule asis_module modules/mod_asis.so
LoadModule cgid_module modules/mod_cgid.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
LoadModule unixd_module modules/mod_unixd.so
<IfModule unixd_module>
User http
Group http
</IfModule>
ErrorLog /run/apache24-error_log
TraceEnable off
LogLevel error
<IfModule log_config_module>
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog /dev/null combined
#CustomLog /run/apache24-access_log combined
</IfModule>
<IfModule cgid_module>
ScriptSock /run/httpd/user-cgisock
</IfModule>
<IfModule mime_module>
TypesConfig conf/mime.types
AddEncoding x-compress Z
AddEncoding x-gzip gz tgz
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType image/x-icon .ico
AddHandler cgi-script .cgi
</IfModule>
MIMEMagicFile conf/magic
EnableMMAP off
# TODO: AllowOverride of root directory to All ??
<Directory />
Options FollowSymLinks
AllowOverride All
</Directory>
# TODO: should apache handle this or nginx?
<IfModule deflate_module>
DeflateCompressionLevel 2
AddOutputFilterByType DEFLATE text/html text/plain text/xml
AddOutputFilter DEFLATE js css
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.[0678] no-gzip
BrowserMatch \bMSIE\s7 !no-gzip !gzip-only-text/html
</IfModule>
# TODO: should apache handle this or nginx
<Files ~ "^\.([Hh][Tt]|[Dd][Ss]_[Ss])">
<IfModule authz_core_module>
Require all denied
</IfModule>
</Files>
<VirtualHost _default_:80 _default_:443>
DocumentRoot "/var/services/web"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
# Tasmota Proxy Konfiguration
ProxyRequests Off
ProxyPreserveHost On
<Location "/tasmota1">
ProxyPass "http://10.0.0.31"
ProxyPassReverse "http://10.0.0.31"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
<Location "/tasmota2">
ProxyPass "http://10.0.0.32"
ProxyPassReverse "http://10.0.0.32"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
# Logging
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
IncludeOptional conf-enabled/alias.*.conf
</VirtualHost>
# TODO: Should apapche handle FileETag
# For CVE-2003-1418
FileETag MTime Size
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-autoindex.conf
Include conf/extra/httpd-languages.conf
Include conf/extra/mod_xsendfile.conf
Include conf/extra/mod_rpaf.conf
IncludeOptional sites-enabled/*.conf
+35
View File
@@ -0,0 +1,35 @@
<VirtualHost *:80>
ServerName your-nas-domain.com
DocumentRoot "/var/services/web/"
# CORS Headers
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
# Tasmota Proxy Konfiguration
ProxyRequests Off
ProxyPreserveHost On
<Location "/tasmota1">
ProxyPass "http://10.0.0.31"
ProxyPassReverse "http://10.0.0.31"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
<Location "/tasmota2">
ProxyPass "http://10.0.0.32"
ProxyPassReverse "http://10.0.0.32"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Origin, Content-Type, Accept, Authorization"
</Location>
# Logging
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
</VirtualHost>
+18
View File
@@ -0,0 +1,18 @@
{
"/tasmota1": {
"target": "http://10.0.0.31",
"secure": false,
"changeOrigin": true,
"pathRewrite": {
"^/tasmota1": ""
}
},
"/tasmota2": {
"target": "http://10.0.0.32",
"secure": false,
"changeOrigin": true,
"pathRewrite": {
"^/tasmota2": ""
}
}
}
@@ -18,13 +18,13 @@ export class TasmotaControlComponent implements OnInit {
}
updateSocketStatuses(): void {
this.tasmotaService.getSocketStatus(this.tasmotaService.socket1IP)
this.tasmotaService.getSocketStatus(this.tasmotaService.socket1Path)
.subscribe({
next: (status) => this.socket1Status = status,
error: (error) => console.error('Fehler beim Abrufen des Status von Steckdose 1:', error)
});
this.tasmotaService.getSocketStatus(this.tasmotaService.socket2IP)
this.tasmotaService.getSocketStatus(this.tasmotaService.socket2Path)
.subscribe({
next: (status) => this.socket2Status = status,
error: (error) => console.error('Fehler beim Abrufen des Status von Steckdose 2:', error)
@@ -32,7 +32,7 @@ export class TasmotaControlComponent implements OnInit {
}
toggleSocket1(): void {
this.tasmotaService.toggleSocket(this.tasmotaService.socket1IP, this.socket1Status)
this.tasmotaService.toggleSocket(this.tasmotaService.socket1Path, this.socket1Status)
.subscribe({
next: (status) => this.socket1Status = status,
error: (error) => console.error('Fehler beim Schalten von Steckdose 1:', error)
@@ -40,7 +40,7 @@ export class TasmotaControlComponent implements OnInit {
}
toggleSocket2(): void {
this.tasmotaService.toggleSocket(this.tasmotaService.socket2IP, this.socket2Status)
this.tasmotaService.toggleSocket(this.tasmotaService.socket2Path, this.socket2Status)
.subscribe({
next: (status) => this.socket2Status = status,
error: (error) => console.error('Fehler beim Schalten von Steckdose 2:', error)
+28 -17
View File
@@ -1,39 +1,50 @@
// tasmota.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from '../environments/environment';
@Injectable({
providedIn: 'root'
})
export class TasmotaService {
private SOCKET1_IP = '10.0.0.31'; // Ändere zu deiner ersten Tasmota IP
private SOCKET2_IP = '10.0.0.32'; // Ändere zu deiner zweiten Tasmota IP
private baseUrl = environment.production
? ''
: '';
private SOCKET1_PATH = this.baseUrl + '/tasmota1';
private SOCKET2_PATH = this.baseUrl + '/tasmota2';
private httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
// Weitere Header falls nötig
})
};
constructor(private http: HttpClient) { }
toggleSocket(socketIP: string, currentStatus: boolean): Observable<boolean> {
getSocketStatus(socketPath: string): Observable<boolean> {
return this.http.get<any>(`${socketPath}/cm?cmnd=Power`, this.httpOptions)
.pipe(
map(response => response.POWER === 'ON')
);
}
toggleSocket(socketPath: string, currentStatus: boolean): Observable<boolean> {
const command = currentStatus ? 'Power%20Off' : 'Power%20On';
return this.http.get<any>(`http://${socketIP}/cm?cmnd=${command}`)
return this.http.get<any>(`${socketPath}/cm?cmnd=${command}`, this.httpOptions)
.pipe(
map(response => response.POWER === 'ON')
);
}
getSocketStatus(socketIP: string): Observable<boolean> {
return this.http.get<any>(`http://${socketIP}/cm?cmnd=Power`)
.pipe(
map(response => response.POWER === 'ON')
);
get socket1Path(): string {
return this.SOCKET1_PATH;
}
get socket1IP(): string {
return this.SOCKET1_IP;
}
get socket2IP(): string {
return this.SOCKET2_IP;
get socket2Path(): string {
return this.SOCKET2_PATH;
}
}
+5
View File
@@ -0,0 +1,5 @@
// environments/environment.prod.ts
export const environment = {
production: true,
apiUrl: '' // Produktions-URL (leer wenn gleicher Server)
};
+6
View File
@@ -0,0 +1,6 @@
// environments/environment.ts
export const environment = {
production: false,
apiUrl: 'http://localhost:4200' // Entwicklungs-URL
};