Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   WebServer (https://www.delphipraxis.net/211718-webserver.html)

lucy 26. Okt 2022 14:27

WebServer
 
Delphi Version XE 7 Starter

Hallo haben einen kleinen Webserver, der soweit ganz gut läuft (HTML).

Jetzt würde ich gerne auch (PHP Scripte einbinden). :shock:

Wer kann mir helfen?

Was für ein "ContentType:='text/html'" brauche ich für PHP ?

Hier ein Stück Quelltext:

Code:
procedure TForm1.ServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var Stream: TFileStream;
    Groesse: String;
begin
 if (CheckBox1.Checked=True) and ((ARequestinfo.AuthUsername<>Edit2.Text) or (ARequestinfo.AuthPassword<>Edit3.Text)) then
  begin
    AResponseinfo.ContentText:='Benutzername und Passwort...';
    AResponseinfo.AuthRealm:='TEST-Interface';
  end else
   begin
     if ARequestinfo.Document='/' then
      begin
        AResponseinfo.ContentType:='text/html';
        Stream:=TFileStream.Create('htdocs/index.html', fmOpenRead or fmShareDenyWrite);
        AResponseinfo.ContentStream:=Stream;
        setlength(Groesse, Stream.Size);
        Stream.Read(Groesse[1], Stream.Size);
        Memo1.Lines.Add(datetostr(date) + ' | ' + timetostr(time) + ': Client ' + ARequestinfo.RemoteIP + ' hat die Datei index.html (' + inttostr(round(Stream.Size /1024)) + 'kb) angefordert.');
      end;
   end;
end;
Quelltext komplett
Code:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.XPMan,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdCustomHTTPServer,
  IdHTTPServer, IdContext;

type
  TForm1 = class(TForm)
    TrayIcon1: TTrayIcon;
    Label1: TLabel;
    Edit1: TEdit;
    GroupBox1: TGroupBox;
    Memo1: TMemo;
    CheckBox1: TCheckBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit2: TEdit;
    Edit3: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    Server: TIdHTTPServer;
    Button4: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ServerConnect(AContext: TIdContext);
    procedure ServerDisconnect(AContext: TIdContext);
    procedure ServerCommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    procedure TrayIcon1DblClick(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  user: Integer;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Server.DefaultPort:=Strtoint(Edit1.Text);
 Server.Active:=True;

 Memo1.Lines.Add('Status: ' + datetostr(date) + ' | ' + timetostr(time) + ': Server gestartet');
 Button1.Enabled:=False;
 Button2.Enabled:=True;
 Label1.Enabled:=False;
 Edit1.Enabled:=False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Server.Active:=False;

 Memo1.Lines.Add('Status: ' + datetostr(date) + ' | ' + timetostr(time) + ': Server gestoppt');
 Button1.Enabled:=True;
 Button2.Enabled:=False;
 Label1.Enabled:=True;
 Edit1.Enabled:=True;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 Memo1.Lines.Clear;
 Memo1.Lines.Add('Server 1.0');
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  Hide();
  WindowState := wsMinimized;
  TrayIcon1.Visible := True;
  TrayIcon1.Animate := True;
  TrayIcon1.ShowBalloonHint;
end;

procedure TForm1.ServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var Stream: TFileStream;
    Groesse: String;
begin
 if (CheckBox1.Checked=True) and ((ARequestinfo.AuthUsername<>Edit2.Text) or (ARequestinfo.AuthPassword<>Edit3.Text)) then
  begin
    AResponseinfo.ContentText:='Benutzername und Passwort...';
    AResponseinfo.AuthRealm:='TEST-Interface';
  end else
   begin
     if ARequestinfo.Document='/' then
      begin
        AResponseinfo.ContentType:='text/html';
        Stream:=TFileStream.Create('htdocs/index.html', fmOpenRead or fmShareDenyWrite);
        AResponseinfo.ContentStream:=Stream;
        setlength(Groesse, Stream.Size);
        Stream.Read(Groesse[1], Stream.Size);
        Memo1.Lines.Add(datetostr(date) + ' | ' + timetostr(time) + ': Client ' + ARequestinfo.RemoteIP + ' hat die Datei index.html (' + inttostr(round(Stream.Size /1024)) + 'kb) angefordert.');
      end;
   end;
end;

procedure TForm1.ServerConnect(AContext: TIdContext);
begin
 User:=User +1;
 GroupBox1.Caption:='Log (User: ' + inttostr (user) + '):';
end;

procedure TForm1.ServerDisconnect(AContext: TIdContext);
begin
 User:=User -1;
 GroupBox1.Caption:='Log (User: ' + inttostr (user) + '):';
end;

procedure TForm1.TrayIcon1DblClick(Sender: TObject);
begin
  TrayIcon1.Visible := False;
  Show();
  WindowState := wsNormal;
  Application.BringToFront();
end;

end.

Phoenix 26. Okt 2022 14:52

AW: WebServer
 
Zitat:

Zitat von lucy (Beitrag 1513883)
Hallo haben einen kleinen Webserver, der soweit ganz gut läuft (HTML).

Jetzt würde ich gerne auch (PHP Scripte einbinden). :shock:

In der Tat :shock:

Also, der "Webserver" kann tatsächlich nur HTML ausliefern. Und zwar genau eine Datei, wenn '/' angefragt wird.
Bevor es dann mit PHP losgeht, sollte er vielleicht erstmal von einer HTML-Datei angefragte weitere Ressourcen (.css-Dateien, Bilder, ggf. JavaScript-Dateien) ausliefern können.

PHP-Scripte werden dann auch nicht einfach so von einem Webserver ausgeliefert, sondern sie werden ausgeführt.
Das heisst der Webserver muss einen PHP-Interpreter aufrufen, ihm sagen welche PHP-Datei angefragt wurde, der Interpreter führt dann das Script aus und gibt das Ergebnis (meist auch HTML) zurück. Erst das wird dann vom Webserver an den Client (meist ein Browser) gesendet.

Die Frage deutet für mich also schon ein wenig darauf hin, dass hier noch viel grundlegendes Wissen über "wie funktioniert das Web" fehlt - insbesondere wo (Browser, sonstiger Client, Server) wann (vor, während, nach einem Request) was (Javascript, Server-Side Scripte wie PHP, ASP, Perl etc.) ausgeführt wird (also z.B. der PHP-Interpreter auf dem Server, aufgerufen vom Webserver bzw. mittels CGI oder anderer Schnittstellen), und was (welche Inhalte) dann wie (Protokoll, Header etc.) "über die Leitung" geht.

Der Schritt von einem "ich kann eine einzige Datei ausliefern" zu "ich kann komplette statische Webseiten inkl. aller notwendigen Ressourcen (wie CSS, JS, Bildern in verschiedenen Formaten, Webfonts, etc.pp.) ausliefern" ist schon recht groß, und wenn man dann dynamische Inhalte (PHP) generieren will, ist das ein noch viel größerer Schritt. Zumal ein Webserver üblicherweise auch ein Serverseitiger Service (Windows Service, Linux daemon etc.) ist, und in aller Regel keine Formulare oder gar Buttons hat.

Deswegen erstmal die Frage: Was willst Du denn _eigentlich_ wirklich machen?

mytbo 26. Okt 2022 15:32

AW: WebServer
 
Zitat:

Zitat von lucy (Beitrag 1513883)
Hallo haben einen kleinen Webserver, der soweit ganz gut läuft (HTML).

In diesem Artikel findest du weitere Anregungen. Der integrierte HTML-Server beinhaltet einige Funktionen, die Phoenix aufgeworfen hat. Willst du danach dein Projekt weiterführen, schaue dir den mORMotBP an. Im GitHub Repro findest du ausreichend Sourcecode zum Studieren.

Bis bald...
Thomas

himitsu 26. Okt 2022 16:03

AW: WebServer
 
Nja, CSS, JavaScript und Bilder kann man auch direkt in eine HTML ibntegrieren und somit auch als eine Datei rausgeben.

lucy 26. Okt 2022 16:18

AW: WebServer
 
Oh, dass hört sich aber sehr kompliziert an. Hatte mir das Projekt „Eigener WebServer“ etwas einfacher vorgestellt.
Wolle mich etwas mit Delphi beschäftigen, und etwas dazulernen.

Wollte gerne Daten aus einer Datenbank (mySQL) über eine Webseite (HTML, PHP, CSS und etwas JavaScript) bearbeiten.
Diese Komponeten interessieren mich halt.

Das ganze wollte ich über einen eigenen WebServer Verwalten und local im Netzwerk laufen lassen.
Den Zugriff wollte ich über einen FIDO2 USB-Stick regeln (ein User mit Passwort).

Der Zugriff wäre somit an jedem Client-PC im Netzwerk "Webbrowser" möglich.

würde mich über jede Unterstützung freuen!

Sherlock 26. Okt 2022 16:20

AW: WebServer
 
Installier Dir nen XAMPP und mach das alles. Delphi brauchst du dafür eher weniger.

Sherlock

lucy 26. Okt 2022 16:21

AW: WebServer
 
Zitat:

Zitat von mytbo (Beitrag 1513887)
Zitat:

Zitat von lucy (Beitrag 1513883)
Hallo haben einen kleinen Webserver, der soweit ganz gut läuft (HTML).

In diesem Artikel findest du weitere Anregungen. Der integrierte HTML-Server beinhaltet einige Funktionen, die Phoenix aufgeworfen hat. Willst du danach dein Projekt weiterführen, schaue dir den mORMotBP an. Im GitHub Repro findest du ausreichend Sourcecode zum Studieren.

Bis bald...
Thomas


Vielen Dank für Deinen Hinweis! Werde ich mir gleich mal anschauen. :)

lucy 26. Okt 2022 16:25

AW: WebServer
 
Zitat:

Zitat von Sherlock (Beitrag 1513897)
Installier Dir nen XAMPP und mach das alles. Delphi brauchst du dafür eher weniger.

Sherlock


ich weiß, und Xampp kenne ich auch :-) :lol:
habe aber einfach Lust was mit Delphi zu machen.

Trozdem vielen Dank für Deine Hilfe :)

himitsu 26. Okt 2022 16:31

AW: WebServer
 
IntraWeb
Delphi4PHP ähh RadPHP ähh HTML5 Builder
TMS WEB Core
uniGUI
RADoween
Thriller
uvm.

Rollo62 26. Okt 2022 17:15

AW: WebServer
 
Zitat:

Zitat von Sherlock (Beitrag 1513897)
Installier Dir nen XAMPP und mach das alles. Delphi brauchst du dafür eher weniger.

Ok, ich weiss: Eigentlich sollte man doch bitteschön was "Docker"-mäßiges Verwenden, das ist ja sooo cool.

Ich bin aber seit geraumer Zeit auf eine Art Zwischenwelt gestoßen, nämlich "Laragon".

Das liegt gefühlt genau zwischen XAMPP / WAMP und Docker und bietet neben PHP, MySql auch Tools wie Node.js, VsCode, Heidi, etc.
Alles schön portabel und vor Allem völlig Windows-Kompatibel und Delphi-freundlich ( wenn man es richtig installiert ).

Wie gesagt, mein Endziel ist vielleicht auch Docker, aber Laragon ist echt bequem, simpel, schnell und leicht zu warten ( mehrere PHP/Mysql nebeneinander).

Damit fahre ich im Moment ganz bequem ein paar Web-Projekte ab.

himitsu 26. Okt 2022 17:26

AW: WebServer
 
Für Windows eigentlich WAMP ... hieß es mal, aber XAMPP ist dennoch gut.
Und sowieso installiert man sich natürlich den IIS.


Vor Jahren mal eine App in den Fingern gehabt ... finde sie nicht mehr ... irgendwas mit Me oder We oder :gruebel:
Egal, war sowas wie USBWebServer oder Server2Go ... halt eine Eierlegendewollmilchsauapp, wo Webbrowser, PHP und MySQL integriert waren ... eine EXE ohne Installation, z.B. für Dinge auf CD oder USB.

bernau 26. Okt 2022 19:52

AW: WebServer
 
Zitat:

Zitat von lucy (Beitrag 1513901)
habe aber einfach Lust was mit Delphi zu machen.

Das kenne ich :thumb:

Phoenix 26. Okt 2022 20:31

AW: WebServer
 
Zitat:

Zitat von Rollo62 (Beitrag 1513910)
Ok, ich weiss: Eigentlich sollte man doch bitteschön was "Docker"-mäßiges Verwenden, das ist ja sooo cool.

Eigentlich ein bissel offtopic, daher nur ganz am Rande:
Docker benutzt man nicht weil es cool ist, sondern weil es als Werkzeug für das richtige Problem angewendet echt saumäßig viel Arbeit (und damit Geld) und vor allem auch Betriebskosten einsparen kann. Das ist eher was für größere Businesses die aktuell im Betrieb mit zig VM's hantieren und wo da Patch-Management und Rollouts etc. echt kompliziert und teuer werden.
Und als Entwicklungs-Plattform für jemanden der mit vielen unterschiedlichen Kunden-Umgebungen arbeiten muss (wie z.B. für mich :stupid:) ist es auch klasse, weil ich da einfach für jeden Kunden die entsprechende SQL-Server oder Oracle-Version mit den Daten isoliert in einem Container liegen habe, und das nur mit einem Kommando hochfahren brauche wenn ich mal auf dem Projekt bin.

Wieder on-topic @Lucy:
Ein Webserver ist vielleicht nicht gerade das einfachste Projekt das man sich vorstellen kann. Vor allem nicht, wenn man ihn wirklich auf der Ebene implementieren möchte (okay, es geht natürlich noch tiefer, aber das wäre dann echt erstmal die komplette HTTP-Spezifikation durchimplementieren).

Delphi als Entwicklungsplattform hat, genau wie andere Toolsets, eine gewisse Abstraktionshöhe von der bare-metal Technik. Es macht einen Entwickler bei GUI-Anwendungen super-produktiv. Deswegen würde man in aller Regel auch z.B. keine Low-Level Treiber in Delphi schreiben sondern eher in C/C++ oder moderner in Rust oder Go.
Genauso würde man sich in C/C++ aber eher die Finger wundschreiben wenn es um Webserver oder APIs geht. Dort sind dann die Abstraktionsschickten in Rust oder Go wiederum vorhanden oder man greift zu .NET (oder Java... brrr), weil dort die vorhandenen Netzwerk-Geschichten schon so geil sind das man hier super-Produktiv ist.

Das Beispiel mit dem vollständigen Webserver (inkl. CSS, JS, Bildern, Videos, Binärformaten etc.) ist in modernem .NET 7 vermutlich irgendwas zwischen 3 und 5 Zeilen. Also wirklich Komplett, Production-Ready und sicher im Internet zu betreiben. Das kann man dann auf Linux, Windows, macOS betreiben und mit einem Dockerfile dazu auch unmittelbar containerisieren.

Kurzum: Willst Du was mit Delphi machen, dann mache vielleicht eher was, wo Delphi wirklich das richtige Tool für ist. Wenn Du Web-Sachen bauen willst, dann nimm eher Tools die einen Entwickler dort saumäßig Produktiv machen. Und: Immer mal wieder über den Tellerrand gucken :thumb:

Delphi.Narium 26. Okt 2022 21:56

AW: WebServer
 
Naja, einen WebServer von grundauf selbstmachen, ist ja vielleicht nicht die Vorstellung des Threaderstellers.

Aber bei den Indys ist eine HTTPServerkomponente bei, die einem das Grundgerüst eines Webservers liefert.

In früheren Zeiten, als bei den Indys (Indy 6) noch Demos dabei waren, hatten sie auch 'nen funktionsfähigen Webserver dabei. Den kann man bestimmt erstmal als Grundlage nehmen.

CGI-Programme kann man mit Hilfe des CGI Runner (zu finden bei GitHub) einbinden.

Alternativ schaue man sich bei SourceForge um. Da gibt's auch 'ne Version vom TIDCGIRunner und dazu auch noch den TIDIAspiRunner, um auch ISAPI.dlls nutzen zu können.

Ist zwar alles schon ein bisserl älter, aber als Herausforderung sicherlich geeignet.

Um dynamische HTML-Seiten, auch aus Datenbanken, zu erstellen, gibt es TPageProducer und TDataSetPageProducer, damit wird es (fast) banal einfach Datenbankinhalte per mit Delphi erstelltem WebServer an beliebige Clients zu liefern.

Ok, am Anfang hat man sicherlich etliches zu lernen, um zu verstehen, wie das Ganze funktioniert. Aber hat man den am Anfang sehr flachen Anstieg der Lernkurve hinter sich gebracht, wird es recht einfach.

Und das Schöne ist, man kann sich sogar 'nen WebServer mit 'ner Delphioberfläche erstellen. Es muss nicht zwingend ein Dienst sein, der über kryptische Konfigurationsdateien "gemanaged" wird oder nur über eine Weboberfläche zu bedienen ist, ...

Mein so erstellter Webserver funktioniert inzwischen seit fast 10 Jahren problemlos. Natürlich ist er nur für den lokalen Einsatz oder sehr kleine Netzwerken geeignet. Ab so als Hobbyprojekt, so einfach aus Neugier, ist's ausreichend.

PS.:

Der Quelltext im Eingangspost enthält übrigens alles wesentliche bereits.

Zur Erfüllung aller weiteren Wünsche, muss "nur" eine passende IF-Cascade um
Delphi-Quellcode:
if ARequestinfo.Document='/' then
gebaut werden.

Letztlich muss für jede mögliche Anforderung an den Webserver, von Seiten der Clients, eine entsprechender IF-Zweig implementiert werden.

Im Endeffekt muss "nur" die Methode
Delphi-Quellcode:
procedure TForm1.ServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
aufgebohrt werden.

Bilder, CSS, ... kann man auf die gleiche Weise ausliefern. Datei in 'nen Stream laden und den "rausrücken".
Man braucht halt ein bisserl Gehirnschmalz und ein sinnvolles Konzept, wie man aus den in der Url angegebenen Dateinamen und Parametern auf die physikalisch auf der Festplatte vorliegende Dateien übersetzt. Sprich: Man muss die Filestruktur, die in der Url abgebildet wird, auf eine entsprechende Filestruktur auf einem Datenträger abbilden (oder umgekehrt).

Für dynamische Seiten muss man ebenfalls die Url auswerten und dann entsprechend den dort angegebenen Paramtern den dynamischen Seiteninhalt erstellen (TPageProducer, TDatSetPageProducer). Der TDataSetPageProducer produziert aus einem beliebigen Abfrageergebnis eines SQL-Statements eine HTML-Tabelle, analog zu 'nem DBGrid. Natürlich kann man sich für dynamische Webseiten Templates hinterlegen, die man dann von den beiden genannten Komponenten zur Laufzeit um einsprechende Inhalte ergänzt. Das läuft alles ereignisgesteuert, so dass man da keine Templates selbst parsen muss, um die Inhalte an die passende Stelle zu bekommen.

Grob gesagt: WebServer mit Delphi erstellen: Geht.

DeddyH 27. Okt 2022 07:05

AW: WebServer
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1513921)
Grob gesagt: WebServer mit Delphi erstellen: Geht.

Man kann auch mit einem Hammer eine Schraube in die Wand bekommen. Die Frage ist nur, ob das das optimal geeignete Werkzeug für diese Aufgabe ist. Und wenn es schon Delphi sein muss, würde ich mich nicht selbst kasteien, sondern lieber auf entsprechende Frameworks zurückgreifen (dieses TMS-Dings, mORMot, DMVC, MARS Curiosity etc.).

hhcm 27. Okt 2022 07:33

AW: WebServer
 
Zitat:

dieses TMS-Dings
:-D

Mit dem TMS-Dings kann man aber auch keinen PHP Interpreter ersetzen. (oder doch?)

himitsu 27. Okt 2022 08:22

AW: WebServer
 
Klar kann man überall intern auch PHP aufrufen.
PHP ist diesbezüglich nichts Anderes, wie Python, PowerShell, Batch, PascalScript ........


PHP4Delphi/RadPHP (k.A. wie weit auch HTML5 Builder) war reines PHP mit JavaScript, was man im PascalStyle mit vcl-ähnlichen Komponenten nutzen konnte.

Aber wer sagt denn das es PHP sein?
Wenn man unbedingt was mit Delphi machen will, dann schreibt man den Code in der delphi-language und lässt sich davon dann HTML erzeugen/ausgeben.

Ansonsten nimmt man was Anderes, was direkt PHP kann und eben kein Delphi ... OK, abgesehn von vielleicht einem Modul (Erweiterung) im PHP-Server oder sowas wie CGI im HTTP-Server.
Nur wenn man extrem pervers masochistisch veranlagt ist, dann schreibt man seinen eigenen PHP-Interpreter.

Delphi.Narium 27. Okt 2022 10:05

AW: WebServer
 
Zitat:

Zitat von DeddyH (Beitrag 1513925)
Zitat:

Zitat von Delphi.Narium (Beitrag 1513921)
Grob gesagt: WebServer mit Delphi erstellen: Geht.

Man kann auch mit einem Hammer eine Schraube in die Wand bekommen. Die Frage ist nur, ob das das optimal geeignete Werkzeug für diese Aufgabe ist. Und wenn es schon Delphi sein muss, würde ich mich nicht selbst kasteien, sondern lieber auf entsprechende Frameworks zurückgreifen (dieses TMS-Dings, mORMot, DMVC, MARS Curiosity etc.).

Es geht doch garnicht darum ein optimales Werkzeug für was auch immer zu finden, sondern darum zu versuchen, ob es geht. Zumindest verstehe ich die Aufgabenstellung im Eingangsthread so.

Und nein, wenn man's mit reinem Delphi und den Indykomponenten macht, muss man sich nicht kasteien.
Delphi-Quellcode:
     
      sFilename := Format('%s%s',['htdocs',ARequestinfo.Document]);
      if FileExists(sFilename) then
      begin
        Stream:=TFileStream.Create(sFilename, fmOpenRead or fmShareDenyWrite);
      end
      else
      begin
        Stream:=TFileStream.Create('htdocs/index.html', fmOpenRead or fmShareDenyWrite);
      end;
      // Hier muss man noch den ContentType abhängig von dem Dateityp, setzen.
      AResponseinfo.ContentType:='text/html';
      AResponseinfo.ContentStream:=Stream;
      setlength(Groesse, Stream.Size);
      Stream.Read(Groesse[1], Stream.Size);
      Memo1.Lines.Add(datetostr(date) + ' | ' + timetostr(time) + ': Client ' + ARequestinfo.RemoteIP + ' hat die Datei ' + sFilename + ' (' + inttostr(round(Stream.Size /1024)) + 'kb) angefordert.');
Damit kann man dann auch CSS, Bilder, und was sonst noch so alles auf der Festplatte rumliegt, ausliefern.

CGI-Programme ruft man mit dem TIDCGIRunner im Prinzip in der Form auf:

Delphi-Quellcode:
CGIRunner.Execute(ARequestinfo.Document,AContext,RequestInfo,ResponseInfo,Action);


Ist also auch "nur" ein Einzeiler, geht auch mit .bat, .cmd, .pl für Perl, ..., ist ähnlich simpel wie ShellExecute.

Und ja: Als professionelle Lösung nicht geeignet, aber ist die hier gefordert?

DeddyH 27. Okt 2022 10:50

AW: WebServer
 
Sorry, mir war nicht bekannt, dass man in diesem Forum nicht mehr auf alternative Lösungen verweisen darf.

Delphi.Narium 27. Okt 2022 11:02

AW: WebServer
 
Es ging mir nicht um alternative Lösungen sondern um
Zitat:

Zitat von DeddyH
Man kann auch mit einem Hammer eine Schraube in die Wand bekommen.


DeddyH 27. Okt 2022 11:15

AW: WebServer
 
Lies Dir doch Phoenix' Beitrag noch einmal durch und vergleiche den Aufwand. Darauf wollte ich mit meinem Hammer-Vergleich hinaus. Dass diese Delphi-Programmierer immer gleich Schnappatmung bekommen müssen...

Delphi.Narium 27. Okt 2022 11:38

AW: WebServer
 
Der von Phoenix beschriebene Aufwand entspricht meiner Erfahrung nach nicht der Realität.

Man muss keine HTTP-Spezifikation durchimplementieren, ... (das ist in den INDY-Komponenten alles schon enthalten).
Zitat:

Zitat von Phoenix
Das Beispiel mit dem vollständigen Webserver (inkl. CSS, JS, Bildern, Videos, Binärformaten etc.) ist in modernem .NET 7 vermutlich irgendwas zwischen 3 und 5 Zeilen.

In meinem obigen Beispiel sind's halt keine 3 bis 5 Zeilen, sondern 13.

Man könnte es auch noch verkürzen:
Delphi-Quellcode:
sFilename := Format('%s%s',['htdocs',ARequestinfo.Document]);
if not FileExists(sFilename) then sFilename := 'htdocs/index.html';
Stream := TFileStream.Create(sFilename, fmOpenRead or fmShareDenyWrite);
// Hier muss man noch den ContentType abhängig von dem Dateityp, setzen.
AResponseinfo.ContentType := 'text/html';
AResponseinfo.ContentStream := Stream;
Delphi-Quellcode:
procedure TForm1.ServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  Stream : TFileStream;
  Filename : String;
begin
  Filename := Format('%s%s',['htdocs',ARequestinfo.Document]);
  if not FileExists(sFilename) then Filename := 'htdocs/index.html';
  Stream := TFileStream.Create(sFilename, fmOpenRead or fmShareDenyWrite);
  // Hier muss man noch den ContentType abhängig vom Dateityp, setzen.
  AResponseinfo.ContentType  := 'text/html';
  AResponseinfo.ContentStream := Stream;
  AResponseinfo.ContentLength := Stream.Size;
end;
Und damit haben wir dann auch in Delphi 'nen 14-Zeiler ;-)
Mehr ist für
Zitat:

Zitat von Phoenix
Das Beispiel mit dem vollständigen Webserver (inkl. CSS, JS, Bildern, Videos, Binärformaten etc.)

nicht erforderlich.

himitsu 27. Okt 2022 12:30

AW: WebServer
 
Ja, ich gebe hier auch über einen TidHTTPServer eine Webseite raus,
genauer geht es um das HTML/CSS/JS/Image-Zeugs, was von Help&Manual generiert wurde.

Damit aber der Browser Bilder/JS/CSS ordentlich behandelt, mußte ich dann auch teilweise Dateien umkodieren (ANSI<>UTF-8), beim Rausgeben,
und zusätzlich auch an den HTTP-Headern rumspielen, also ContentType, Charset und Dergleichen alles selbst behandeln, entsprechend der angefragten DateiEndungen.

Delphi.Narium 27. Okt 2022 12:49

AW: WebServer
 
Zitat:

Zitat von himitsu (Beitrag 1513950)
Damit aber der Browser Bilder/JS/CSS ordentlich behandelt, mußte ich dann auch teilweise Dateien umkodieren (ANSI<>UTF-8), beim Rausgeben,
und zusätzlich auch an den HTTP-Headern rumspielen, also ContentType, Charset und Dergleichen alles selbst behandeln, entsprechend der angefragten DateiEndungen.

Das ist aber (streng genommen) keine Aufgabe des Webservers, bei spezifikationkonformen Aufbau der HTML-Dateien, sollte die Umcodierung entbehrlich sein.

Und neben
Delphi-Quellcode:
AResponseinfo.ContentType
sollte man natürlich alle weiteren Werte für AResponseinfo korrekt setzen.

Z. B.:
AResponseInfo.ContentEncoding
AResponseInfo.ContentLanguage
AResponseInfo.ContentLength

und die ausgegebenen HTML-Seiten sollten auch die entsprechenden Meta-Tags im Header enthalten.

Aber auch das ist eigentlich keine Aufgabe des Webservers, sondern der Routinen, Programme, Autoren, ..., die die HTML-Seiten erstellen.

himitsu 27. Okt 2022 14:09

AW: WebServer
 
Dafür müssen diese Angaben dort auch stimmen ... tun sie aber nicht und daher hatten wir dann Hand angelegt.
* die erste Version war auch nur "prüfen des Pfades", damit ausschließlich gewünschte Dateien raus gehen
* und dann LoadFromFile und als Stream 1:1 raus zum Browser

* zerst überlegt alles wie \ und / im Pfad abzulehnen, aber sicherer fühlten wir uns dann, als wir einfach nur a-zA-Z0-9_.- zuliesen

Da Microsoft/InternetExplorer komischer Weise das Intranet z.B. von SambaShares (obwohl die ja eine ausreichende Zugangskontrolle haben) als "unsicher" einstufte,
aber wilde lokale HTTP-Server von Localhost oder irgendwo aus dem lokalen Netzwerk als sicher ....

Nja, direkt die Webseite vom Dateisystem (file:-Protokoll) wurde selten korrekt angezeigt, außer man fummelte auf jedem einzelnen Rechner an den Sicherheitseinstellungen rum,
war ein "WebServer" die einfache Lösung.

Der Hersteller (Help&Manual) hatte das auch schon lange bemerkt und stellte dafür eine EXE bereit
* erstmal nicht als Service, sondern als GUI-EXE
* und wo dann sonstwer ohne Prüfungen von Festplatte/Netzwerk JEDE Datei darüber runterladen kann (auf die Leserechte besteht, also fast alles vom Windows)

Delphi.Narium 27. Okt 2022 15:09

AW: WebServer
 
Zitat:

Zitat von himitsu
war ein "WebServer" die einfache Lösung.

In der Tat, das ist eine einfache Lösung.

Man bringt dem eigenen WebServer einfach nur das bei, was man tatsächlich abdecken will.

Und ja, die HTML-Originaldateien von diversen Systemen sind nicht zwingend spezifikationskonform, so dass man kaum umhinkommt, da vereinzelt bis grundsätzlich nachzuarbeiten.

Und das Schöne an 'nem eigenen WebServer: Er kann wirklich das und nur das, was man benötigt.

Rollo62 27. Okt 2022 17:08

AW: WebServer
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1513964)
Und das Schöne an 'nem eigenen WebServer: Er kann wirklich das und nur das, was man benötigt.

Stimmt.
Ein eigener, selbstgebauter WebServer kann aber dafür auch alle möglichen sicherheitskritischen Probleme haben, je nach Umfang,
denn da testen im Prinzip nur Wenige und nicht Millionen User in Tausenden von Einsatz-Szenarien.
Kann sein dass man das im lokalen Netz akzeptiert, aber im echten Web hätte ich da ziemliche Bauchschmerzen.

Ich glaube man sollte heutzutage nicht alles versuchen selber zu machen, es sei denn man hat das als Hobby.

himitsu 27. Okt 2022 17:18

AW: WebServer
 
Jupp, der erwähnte WebServer des Herstellers.
Wenn du den noch in der Firewall und im Router eine Portweiterleitung von außen einrichtest ... da er ja garkeine Sicherheit bietet ... könnte dann JEDER fast deine komplette Festplatte und alles zugängliche im Netzwerk runterladen.

Authentifizierung hatten ir und gespart, da unsere Hilfe zusätzlich auch nochmal online auf der über unseren richtigen WebServer (Webseite) frei zugänglich ist, war Diesbezüglich nichts mehr nötig.
Nur eben, dass "offentlich" alle Lesezugriffe außerhalb des gewünschten Verzeichnisses unterbunden werden. Und nurmal ist dieser kleine HelpServer auch nur lokal im Netz unterwegs, aber dennoch wäre es unschön, wenn er einfachen Zugriff auf das Dateisystem des Datenbankservers erlaubt hätte.

Delphi.Narium 27. Okt 2022 20:40

AW: WebServer
 
Zitat:

Zitat von Rollo62 (Beitrag 1513970)
Zitat:

Zitat von Delphi.Narium (Beitrag 1513964)
Und das Schöne an 'nem eigenen WebServer: Er kann wirklich das und nur das, was man benötigt.

Stimmt.
Ein eigener, selbstgebauter WebServer kann aber dafür auch alle möglichen sicherheitskritischen Probleme haben, je nach Umfang,
denn da testen im Prinzip nur Wenige und nicht Millionen User in Tausenden von Einsatz-Szenarien.
Kann sein dass man das im lokalen Netz akzeptiert, aber im echten Web hätte ich da ziemliche Bauchschmerzen.

Ich glaube man sollte heutzutage nicht alles versuchen selber zu machen, es sei denn man hat das als Hobby.

Ich käme nie auf die Idee, einen WebServer für das weltweite Internet zu bauen.

Es geht hier doch nur darum zu versuchen ob es geht. Zum Lernen, zum Probieren, sicherlich nicht um eine kommerzielle Software zu erstellen, die mit vorhandenen WebServeren auch nur im leisesten Ansatz konkurieren kann.

Hiermit
Delphi-Quellcode:
sFilename := Format('%s%s',['htdocs',ARequestinfo.Document]);
if not FileExists(sFilename) then sFilename := 'htdocs/index.html';
hat man schonmal keinen Zugriff mehr auf die gesamte Festplatte, sondern nur auf die Dateien, die unter htdocs liegen. Wo das physikalisch liegt, ist von außen nicht erkennbar. Sinnvollerweise macht man das konfigurierbar und sorgt dafür, dass die Rechte entsprechend eingeschränkt sind.

Über ARequestinfo bekommt man auch die IP des Anfragers heraus, hierüber kann man dann auch nochmal die Zugriffe einschränken. Ein eigener WebServer muss nicht auf Port 80 oder 8080 laufen, wie meist üblich bzw. vorgegeben.

Mögliche sicherheitskritische Probleme hat ein eigener WebServer alle die, die man sich auch sonst mit Delphiprogrammen "einfangen" kann, also z. B. auch alle die, die in den Indykomponenten enthalten sein könnten, ... und natürlich alle die, die man selbst einbaut ;-)

himitsu 27. Okt 2022 22:25

AW: WebServer
 
Code:
http://1.2.3.4:80/../../../../../../../Windows/System32/TeamViewer_Hooks.log

und mit etwas Glück hab ich deinen "Schutz" schon umgangen. :angle2:

Genau sowas war der Grund, warum ich bei uns dann die Prüfung umgekehrt hab, weil ich sorum bestimmt auch nicht jede Möglichkeit bedenke und irgendwas vergessen/übersehen hätte.


Gut, mein Webserverchen kommt unter Anderen auch in einer Firma zum Einsatz, die z.B. mit Airbus zusammenarbeitet und deren Regel unterliegt, da sind die Sicherheitsbestimmungen schon bissl böse ... und ich wollte diesbezüglich dann einfach keine keine unnötigen Sicherheitslöcher riskieren.

Delphi.Narium 27. Okt 2022 22:33

AW: WebServer
 
Nein, hast Du nicht, haben schon viele gesagt, haben schon viele versucht, sind alle gescheitert.

Auszuliefernde Dateien müssen unterhalb des für den WebServer konfigurierten Rootverzeichnisses liegen.

.. in der Url wird schlicht als ungültig erkannt und verworfen.

Delphi-Quellcode:
// Im realen Leben natürlich konfigurierbar!
const
  csRootverzeichnis = 'c:\HTTPServer\Root';

procedure TForm1.ServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  Stream : TFileStream;
  Filename : String;
begin
  Filename := Format('%s%s',[csRootverzeichnis,ARequestinfo.Document]);
  if (Pos('..',sFilename) = 0 then begin
    if not FileExists(sFilename) then Filename := Format('%s\index.html',csRootverzeichnis]);
    Stream := TFileStream.Create(sFilename, fmOpenRead or fmShareDenyWrite);
    // Hier muss man noch den ContentType abhängig vom Dateityp, setzen.
    AResponseinfo.ContentType := 'text/html';
    AResponseinfo.ContentStream := Stream;
    AResponseinfo.ContentLength := Stream.Size;
  end else begin
    // Warum sollte man hier 'nem Hacker antworten?
    // Wenn man 'ne Sperrliste für IPs (ARequestinfo.RemoteIP) implementiert hat, kommt die da rein.
    // Die wird natürlich dann auch am Anfang dieser Prozedur abgefragt ;-)
  end;
end;
Und ja: Einen simplen, anspruchslosen WebServer selbst zu bauen geht und ist einfach.
Den Bau eines Webservers für den professionellen Einsatz sollte man anderen überlassen.

Und wenn man 'nen Webserver selbst baut lernt man recht schnell, welche Fallstricke es in dem Umfeld gibt auf die geachtet werden muss.

Als Hobbyprogrammierer kann ich mir diesen Spass durchaus leisten.

Allerdings käme ich nie auf die Idee "so ein Dingen" für 'nen Kunden zu bauen und dann die ganze Welt darauf zugreifen zu lassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz