# Servlets oder cgi in Server einbinden



## Yogi (26. Jul 2006)

Hallo,

ich habe einen Http Server selber geschrieben. Der kann nun Post und Get Requests verarbeiten. Nun ist die Frage, wie kann ich auf eine einfache weiße meinen Server so erweitern, dass er Servlets verarbeiten kann? Kann mir das nicht ganz vorstellen. Und wenn cgi einbinden leichter wäre, wie sollte ich da vorangehen?


----------



## foobar (26. Jul 2006)

> Und wenn cgi einbinden leichter wäre, wie sollte ich da vorangehen?


Das ist ziemlich einfach. Du mußt nur die Requests auf das cgi-bin an  den Perlinterpreter übergeben und das Ergbnis an den Client senden.


----------



## gekkonier (26. Jul 2006)

CGI ist nicht gleich Perl!
CGI kann auch z.b. (jaja) ein bash script sein


----------



## foobar (26. Jul 2006)

@Gekkonier Da hast du natürlich Recht. 

D.h. du mußt zuerst die Shebang auslesen und dann einen entsprechenden Interpreter laden.


----------



## gekkonier (26. Jul 2006)

stimmt, Shebang.

d.h. erste zeile vom script = #!/pfad/zum/interpretermitdemjenedateinterpretiertwerdensoll

und die Scriptdatei selber ausführbar machen, und ohne Extension (oder *.cgi) verwenden. Dann kann man auch einfach mal z.B. ein anderes Script anderer Sprache, gleicher Funktion dort reinhängen, ohne dass man die Konsitenz zerstört.
Natürlich kann man an dieser Stelle dann z.B. auch ein compiliertes Programm einsetzen, wenns nötig ist.


----------



## Yogi (26. Jul 2006)

ok, irgendwie alles grad ein bisschen konfus für mich. Mit interpreter, ok, check ich, aber ich steh völlig an, wie ich das in java umsetzen soll, dass er mir das cgi verarbeitet.
weil ich hab ja auf meinen Server ein paar html files liegen, dort gibts dann halt a mal a post request, dass halt ein cgi skript verwendet, aber wie mach ich dass, dass der server weiß, was er mit dem cgi machen muss und vor allem wie er das cgi handeln soll?


----------



## gekkonier (26. Jul 2006)

Erstmal musst du rausfinden wie dein Server konfiguriert ist und wie Dein CGI Pfad gemappt ist.
Könnte z.b. so aussehen:
http://www.meineseite.xy/cgi-bin/blabla.cgi
INTERN im Filesystem könnten die CGI's irgendwo liegen.
Auf einem meiner Server liegen die CGI's z.B. da:
/usr/lib/cgi-bin

und in meiner Apache Konfiguration (die richtige Stelle dafür müsstest du noch suchen )


```
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin
<Directory /usr/lib/cgi-bin/>
  AllowOverride None
  Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
  Order allow,deny
  Allow from all
</Directory
```

Diesbezüglich schau aber noch die Dokus durch! Die obige Konfiguration ist in meinem Heimnetzwerk, weis ned genau ob das die _sichere_ Produktionstaugliche CGI Konfiguration ist.
Wie man jetzt explizit Java-Programm dort ausführen kann weis ich selber ned. Ich führe dort nur Ruby und Perl Skripte aus.


----------



## foobar (26. Jul 2006)

@gekkonier Nix Apoache. Yogi will einen eigenen Webserver entwickeln.

@Yogi Du mußt einfach über Runtime den Interpreter aufrufen und das Ergebnis an den Client senden. Du mußt nur etnscheiden wann ein Request ein CGI aufruft und wann eine html-Seite. Am besten machst du das über das cgi-bin. D.h. alle Request die auf das cgi-bin kommen werden an einen Interpreter übergeben und das Ergebnis davon (Outpustream) an den Client gesendet.


----------



## Leroy42 (26. Jul 2006)

Yogi hat gesagt.:
			
		

> ich habe einen Http Server selber geschrieben. Der kann nun Post und Get Requests verarbeiten



Wenn ich das richtig verstehe, soll dein selbstgestrickter Server JSP-Seiten verarbeiten.
Dazu müßtest du dir auch einen richtigen Servlet-Container dazustricken. 

Das wird mit Sicherheit alles andere als einfach werden...


----------



## gekkonier (26. Jul 2006)

Das ist mir entfleucht, dass er einen eigenen Server schreiben will. Tschuldigung.
(Vielleicht hilfts aber den Mechanismus zu verstehen, der erfolgreich implementiert wurde?)


----------



## foobar (26. Jul 2006)

> Das wird mit Sicherheit alles andere als einfach werden...


Es gibt aber schon genug kleine Httpserver mit Servletcontainer im Opensourcebereich, bei denen man etwas abgucken kann ;-)

Man muß ja auch nicht alles implementieren. Es würde ja schon reichen, wenn man ein paar Strings zurück geben kann.


----------



## Yogi (27. Jul 2006)

Danke für die vielen Antworten, hoff es wird jetzt dann klappen


----------



## Yogi (27. Jul 2006)

Und nein, ich bekomms einfach nicht hin, ist zum verzweifeln. Wie kann ich den Perl Interpreter starten. Das ich dazu die Runtime und Process Klassen brauche ist mir klar. Nur irgendwie check ichs trotzdem nicht und googel ist dieses mal nicht mein freund, der liefert mir nicht wirklich was vernünftiges. Also, ich brauche mal die cgi-lib.pl. Hoffe dass passt. Und diese muss ich ja dann starten, und da hängts dann völlig bei mir.


----------



## foobar (27. Jul 2006)

Du brauchst keine cgi-lib.pl zu laden, das macht der Interpreter für dich.

Also mal angenommen du bekommst einen Request auf die Ressource /cgi-bin/hello.pl. Dann rufst du Runtime.exec ungefähr so auf:


```
Process p = Runtime.exec("perl.exe /foo/bar/cgi-bin/hello.pl");
```

Von dem Process holst du dir dann den Outputstream und gibst den als Response wieder raus. Du mußt jetzt nur noch darauf achten das die Pfade zum Perlinterpreter und zu dem Script stimmen. Das ist alles.


----------



## Yogi (28. Jul 2006)

Also ich hab das jetzt so gemacht, dass ich eine eigene Klasse fürs CGI gemacht habe, die schaut ganz einfach so aus:


```
public class StartCgi {
	OutputStream os;
	public StartCgi(String cgi){
		Process p = null;
		try {
			System.out.println("Perl is starting");
			p = Runtime.getRuntime().exec("cgi\\perl.exe cgi\\" + cgi);
			this.os = p.getOutputStream();
		} catch (IOException e) {
			System.out.println("Perl does not start");
			e.printStackTrace();
		}
	}
	public OutputStream getOutputStream(){
		return this.os;
	}

}
```

Und dann halt in der Getmethode folgender maßen vorgegangen bin


```
if(file.startsWith("cgi", 1)){
			System.out.println("CGI");
			
                        //suche wo Variablen in file hinten angehaengt sind, damit ich
                       //an Klasse StartCGI den richtigen Filenamen uebergebe
			for(i = 0; i < file.length(); i++){
				if(file.substring(i, i+1).equals("?")){
					System.out.println("BREAK " + i);
					break;
				}
			}
                        //Interpreter Starten und os (PrintStream) neu setzen
			StartCgi cgi = new StartCgi(file.substring(5, i));
			os = new PrintStream(cgi.getOutputStream());
			try{
							
				File theFile = new File("F:\\workspace\\NWS\\cgi", file.substring(5, i));
				FileInputStream fis = new FileInputStream(theFile);
				byte[] theData = new byte[(int) theFile.length()];
							
				//need to check the number of bytes read here
				fis.read(theData);
				fis.close();

				if(version.startsWith("HTTP/")){//send a MIME header
					os.print("HTTP/1.0 200 OK\r\n");
					Date now = new Date();
					os.print("Date: " + now + "\r\n");
					os.print("Server: jhttp 1.0\r\n");
					os.print("Content-length: " + theData.length + "\r\n");
					os.print("Content-type: " + ct + "\r\n\r\n");
				}

				os.write(theData);
				os.close();
			}//end try
```

aber jetzt wird mir einfach eine leere Seite zurückgelierfert, bzw IE schreit, dass Seite nicht angezeigt werden kann. Was muss ich anders machen? Bzw muss ich einen bestimmten Content-type setzen?


----------



## foobar (28. Jul 2006)

```
p = Runtime.getRuntime().exec("cgi\\perl.exe cgi\\" + cgi);
```
Was machen denn die Slashes und der String cgi am Anfang da? Warum schreibst du nicht?


```
p = Runtime.getRuntime().exec("perl.exe " + cgi);
```



> aber jetzt wird mir einfach eine leere Seite zurückgelierfert


Wie sieht der Response denn aus? Bekommst du das Resultat vom CGI geliefert? Poste mal bitte den Response von einem Hello World Script.

Als Contenttype kannst du zum testen erstmal text/plain verwenden.


----------



## Yogi (28. Jul 2006)

Bin schon total verwirrt, was für einen Response meinst du, bzw wo soll ich ihn her holen.


----------



## Yogi (28. Jul 2006)

Ach und ohne die Slashes bekomm ich ne Exception, dass er nix findet


----------



## Yogi (28. Jul 2006)

Ok, also es scheint so, als ob das Skript einfach beim Response hinten angehängt wird.
Bei einem Get Request, ohne dass Werte mitgegeben werden, schreit er not Implemented, bei einem Get Request, wo Werte in der Url mitgegeben werden, zeigt er mir das Skript an


----------



## foobar (28. Jul 2006)

> Ach und ohne die Slashes bekomm ich ne Exception, dass er nix findet


Wer finde was nicht? Exception?


Du mußt zuerst mal dafür sorgen, daß das Script ausgeführt wird und du das Ergebnis als String speicherst. Dann mußt du es einfach im Body des Http-Responses zurück geben.


----------



## foobar (28. Jul 2006)

Also bei mir läuft das ohne Probleme:


```
import java.io.*;

public class ExecutePerl
{
    public static void main(String[] args)
    {
        try
        {
            Process p =  Runtime.getRuntime().exec("perl /home/steffen/hello.pl");
            
            StringBuilder buffer = new StringBuilder();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null )
            {
                buffer.append(line);
            }
            System.out.println("Response: " + buffer.toString());
            
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
```

hello.pl

```
#! /usr/bin/perl
print "hello \n";
```


Wenn die Shebag korrekt ist kannst du dir expliziten Aufruf von Perl auch sparen. Das Einlesen des Inputstreams sollte man vielleicht etwas abwandeln, damit man auch Responses lesen kann die nicht mit einem Zeilenendezeichen enden.


----------



## Yogi (28. Jul 2006)

ha, jetzt funkt des auch. Aber nur solange keine Variablen übergeben werden( zB in der Url) da gibt er mir dann null zurück im Response. des cgi-lib.pl sollte ja eigentlich dafür sorgen, dass die Variablen geholt werden


----------



## foobar (28. Jul 2006)

> ha, jetzt funkt des auch. Aber nur solange keine Variablen übergeben werden( zB in der Url) da gibt er mir dann null zurück im Response. des cgi-lib.pl sollte ja eigentlich dafür sorgen, dass die Variablen geholt werden


Das mußt du alles selber implementieren, ist doch dein Server ;-) 

Das Parsen der Requests und das zur Verfügung stellen der CGI-Variablen ist alles Sache des Servers.


----------

