Socket Java HTTP-Proxy

Tion

Mitglied
Guten Abend,

Wie ich euch leider berichten muss, führt mich ein Problem zu euch ...
Ich hwäre euch sehr dankbar, würdet ihr mir helfen können:

Ich habe ( rein aus langeweile ) einen HTTP-Proxy geschrieben ( habe mir Hilfe aus dem Internet geholt, da ich ja nicht weiß wie ein Proxy funktioniert ).
Der öffnet auf dem lokalem Rechner einen Port ( ich glaube es war 9900 ) und leitet die "Socket-ID" an einen Thread weiter. Der Thread sieht folgendermaßen aus:
Java:
package de.tionsys.proxy.client;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.LinkedList;

public class ProxyClient extends Thread implements Runnable
{
	Socket Client = null;
	BufferedInputStream clientIn = null;
	PrintStream clientOut = null;
	
	String query = null;
	String request = null;
	
	String domain = null;
	int serverport = 80;

	// OS-Unabhängig
	final String LineFeed = new String(""+((char) 13)+((char) 10));
	
	public ProxyClient(Socket client) throws IOException
	{
		Client = client;
		System.out.println("Proxy: Eine neue Verbindung von Client "+ Client);
	}
	
	public void run()
	{
		try
		{
			ClientLoop();
		}
		catch(Exception e)
		{
			
		}
	}
	
	private void ClientLoop() throws IOException
	{
		// Streams definieren
		clientIn = new BufferedInputStream(Client.getInputStream());
		clientOut = new PrintStream(Client.getOutputStream(), true);
		// Temporär zum Trennen host:port
		int in1 = 0;
		// Die Headers
		LinkedList<String> requestStrings	= new LinkedList<String>();
		// Und ab "in die Loop" :D
		while(true)
		{
			// Den Request lesen
			query = readLine(clientIn);
			
			// Ressource extrahieren
			request = query.substring(0, query.indexOf(" ")+1) + query.substring(query.indexOf("/", query.indexOf("//") + 2));
			
			// Domain und Port extrahieren
			domain = query.substring(query.indexOf("//") + 2);
			domain = domain.substring(0, domain.indexOf("/"));
			if ((in1 = domain.indexOf((int)':')) > -1)
			{
				serverport = Integer.parseInt(domain.substring(in1 + 1));
				domain = domain.substring(0, in1);
			}
			else
			{
				serverport = 80;
			}
			
			// Die restlichen Header holen
			requestStrings.clear();
			do {
				query = readLine(clientIn);
				requestStrings.add(query);
			} while (!query.equals(LineFeed));
			
			// Noch einmal zum debuggen
			System.out.println("Proxy: Client '"+ Client +"' startet Request an Server "+ domain +":"+ serverport +".");
			
			// Und ab an den Server mit dem Request:
			
			Socket server = new Socket(domain, serverport);
			server.setSoTimeout(2500);
			BufferedInputStream serverIn = new BufferedInputStream(server.getInputStream());
			PrintStream serverOut = new PrintStream(server.getOutputStream(), true);
			serverOut.print(request);
			// ( Noch mal schnell die Header "optimieren" )
			String header = null;
			Iterator<String> iter = requestStrings.iterator();
			while (iter.hasNext())
			{
				header = (String) iter.next();
				System.out.println("Proxy: Client '"+ Client +"' sendet Header: "+ header);
				if(header.startsWith("Proxy-Connection"))
				{
					serverOut.print("Connection: close"+ LineFeed);
				}
				else if(header.startsWith("Transfer-Encoding"))
				{
					serverOut.print("Transfer-Encoding: identity"+ LineFeed);
				}
				else if(header.startsWith("Accept-Encoding"))
				{
					
					header = header.substring(0,(header.length()-2)).concat(",identity"+ LineFeed);
					serverOut.print(header);
				}
				else if(!(header.startsWith("X-Forwarded-For")))
				{
					serverOut.print(header);
				}
			}
			
			// Jetzt holen wir uns die Antwort vom Server
			try
			{				
				// Server auslesen und weitermachen
				request = readLine(serverIn);
				int linefeeds = 0;
				
				while(linefeeds < 2)
				{
					System.out.println("Proxy: Client '"+ Client +"' bekommt Antwort: "+ request);
					clientOut.print(request);
					request = readLine(serverIn);
					if(request.equals(LineFeed))
						linefeeds++;
					continue;
				}
				
				System.out.println("Proxy: Client '"+ Client +"' hat die Antwort von "+ domain +":"+ serverport +" erhalten.");
				// Verbindung werden nach catches geschlossen
			}
			catch (SocketTimeoutException ste)
			{
				System.out.println("Proxy: Connection Timeout");
				clientOut.print("HTTP/1.0 500\nContent Type: text/plain\n\nServertimeout bei der Verbindung zu "+domain+"<br />"+ ste.getMessage() +"\n");	
			}		
			catch (ConnectException ce)
			{
				System.out.println("Proxy: Connection Timeout");
				clientOut.print("HTTP/1.0 500\nContent Type: text/plain\n\nFehler bei der Verbindung zu "+domain+"<br />"+ ce.getMessage() +"\n");				
			}	
			
			// Verbindung zum anderen Server schließen
			serverIn.close();
			serverOut.close();
			server.close();
			
			// Die Verbindung zu unserem Server schließen
			Client.close();
		} // end while
	}
	
	// altes Proxysystem
	public void reply(int code, String text)
	{
		return;
	}

	public String readLine(InputStream in) throws IOException
	{
		StringBuffer lineBuffer = new StringBuffer(600);
		int i;
		lineBuffer.setLength(0);
		
		while (((i = in.read()) > 0) && (i != 13)){
			lineBuffer.append((char) i);
		}
		
	
		// Bei HTTP 1.1 bestanden die Zeilenenden aus #13#10
		if (i == 13) {
			
			lineBuffer.append((char) 13);
			in.mark(1);

			if (in.read() != 10)
				in.reset();
			else
				lineBuffer.append((char) 10);
		}
		
		return lineBuffer.toString();
	}
}
( Ich hoffe, er ist nicht zu lang :O )

Sieht alles nett aus, funktiniert leider nur bei den Headern >.<
Danach werden entweder "Leerstrings" oder total unlesbare ASCII-Zeichen, die dem Inhalt der JAR-Datei, wenn man sie mit dem Texteditor öffnet, gleichen, übermittelt.

Mein Tipp ist, dass der Fehler bei

Java:
while(linefeeds < 2)
{
	System.out.println("Proxy: Client '"+ Client +"' bekommt Antwort: "+ request);
	clientOut.print(request);
	request = readLine(serverIn);
	if(request.equals(LineFeed))
		linefeeds++;
	continue; // <= Nur zur Deko, sieht sonst hässlich aus
}

liegt.

Ich bitte euch, dass ihr mir helft 😉

Tino

/Edit 1:

Firefox gibt mir den Fehler

Content-Encoding-Fehler
Die Webseite, die Sie öffnen möchten, kann nicht angezeigt werden, da sie eine ungültige oder unbekannte Form der Kompression verwendet.

aus. Ich denke, dass liegt an diesen Sonderzeichen 😉
 
FALSCH

es liegt daran das du einen binär-daten über einen string-reader laufen lässt was zwangsläufig zu encoding fehlern führt ... und das in beide richtungen *z.b. wenn du binär-daten hochladen willst*

baue deinen proxy einfach so um das er mit byte-streams *also dierekt Input/OutputStream* arbeitet anstatt mit string-readern/-writern ...
 
Guten Abend,

FALSCH

es liegt daran das du einen binär-daten über einen string-reader laufen lässt was zwangsläufig zu encoding fehlern führt ... und das in beide richtungen *z.b. wenn du binär-daten hochladen willst*

baue deinen proxy einfach so um das er mit byte-streams *also dierekt Input/OutputStream* arbeitet anstatt mit string-readern/-writern ...

Das geht direkt ?
Könntest du ( oder jemand anderes ) mir dafür ein Beispiel geben ?
Ich kenne es nur über Buffered-Reader / Mir wurde es nur über Buffered-Reader beigebracht :O

Tion
 
Guten Abend noch einmal,

nachdem ich nun während ich auf eine Antwort gewartet habe ( selbstständig ) nach einer Antwort gesucht habe, bin ich zu folgenden Code gekommen:
Java:
	// Header auslesen und weitergeben
	do
	{
		request = readLine(serverIn);
		System.out.println("Proxy: Client '"+ Client +"' bekommt Header: "+ request);
		clientOut.print(request);
	} while(!request.equals(LineFeed));

	System.out.println("Proxy: Client '"+ Client +"' wird nun der Inhalt gesendet");

	// Nun wird der Body gesendet
	in1 = 0;
	buffer = null;
	while((in1 = serverIn.read(buffer)) > 0)
	{
		System.out.println(buffer, 0, in1);						
		clientOut.write(buffer, 0, in1);
	}
		
	System.out.println("Proxy: Client '"+ Client +"' hat die Antwort von "+ domain +":"+ serverport +" erhalten.");
Noch vor dem
[JAVA=5]System.out.println("Proxy: Client '"+ Client +"' bekommt Header: "+ request);[/code]
kommt ein "Connection-Timeout", das sieht in etwa so aus:
Proxy: Client 'Socket[addr=/0:0:0:0:0:0:0:1,port=49841,localport=9900]' sendet Header: Cache-Control: no-cache
Proxy: Client 'Socket[addr=/0:0:0:0:0:0:0:1,port=49841,localport=9900]' sendet Header:
Proxy: Connection Timeout
Der Code steht im ersten Beitrag, jedoch kann ich diesesmal nicht tippen, woran das liegt...
Ich hoffe, ihr könnt mir wiederum helfen,

Tion

/E1: Zu früh "Enter" gedrückt ...
 

Zurück
Oben