this post başlayarak HTTP GET/POST isteğinden veri alışverişi yapamıyor (hemen altında birer Handler
sınıfını değiştirin):Java Vekil - Ben de <code>GET</code> ve <code>POST</code> isteklerini işleyen küçük bir proxy sunucusu uygulamaya çalışmıştır düzgün
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN
= Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
public static final Pattern GET_POST_PATTERN
= Pattern.compile("(GET|POST) (?:http)://([^/:]*)(?::([^/]*))?(/.*) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
String request = readLine(clientSocket, Integer.MAX_VALUE);
Matcher connectMatcher = CONNECT_PATTERN.matcher(request);
Matcher getNpostMatcher = GET_POST_PATTERN.matcher(request);
System.out.println("Request: " +request);
if (connectMatcher.matches()) {
// ...
} else if (getNpostMatcher.matches()) {
String method = getNpostMatcher.group(1);
String hostString = getNpostMatcher.group(2);
String portString = getNpostMatcher.group(3);
String lengthString = null;
String line;
ArrayList<String> buffer = new ArrayList<String>();
Integer port = portString == null || "".equals(portString) ? 80 : Integer.parseInt(portString);
Integer length = null;
buffer.add(request);
while ((line = readLine(clientSocket, Integer.MAX_VALUE)) != null) {
buffer.add(line);
if ("".equals(line)) break;
if (lengthString == null && line.startsWith("Content-Length: ")) {
lengthString = line.substring(16);
length = Integer.parseInt(lengthString);
}
}
try {
final Socket forwardSocket;
try {
forwardSocket = new Socket(hostString, port);
System.out.println(" " + forwardSocket);
} catch (IOException | NumberFormatException e) {
OutputStreamWriter outputStreamWriter
= new OutputStreamWriter(clientSocket.getOutputStream(), "ISO-8859-1");
e.printStackTrace();
outputStreamWriter.write("HTTP/" + connectMatcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
PrintWriter printWriter = new PrintWriter(forwardSocket.getOutputStream());
for (String bufferedLine : buffer) {
printWriter.println(bufferedLine);
}
printWriter.flush();
if ("POST".equals(method) && length > 0) {
System.out.println ("Posting data ...");
if (previousWasR) { // skip \n if existing
int read = clientSocket.getInputStream().read();
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(threadId, clientSocket, forwardSocket, length, true); // only forward "Content-length" bytes
} else {
forwardData(threadId, clientSocket, forwardSocket, length, true); // only forward "Content-length" bytes
}
}
System.out.println ("Forwarding response ...");
forwardData(threadId, forwardSocket, clientSocket, null, false);
if (forwardSocket != null) {
forwardSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void forwardData(int threadId, Socket inputSocket, Socket outputSocket, Integer length, boolean isPost) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
if (length == null || length > 0) {
do {
if ((read = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
if (length != null) {
length = length - read;
}
}
} while (read >= 0 && (length == null || length > 0));
}
} finally {
if (!outputSocket.isOutputShutdown()) {
if (!isPost) {
outputSocket.shutdownOutput();
}
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private String readLine(Socket socket, Integer noOfBytes) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while (noOfBytes-- > 0 && (next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
POST istekleriyle ilgili bazı sorunlar yaşadıktan sonra, akışları doğru şekilde kapatmanın önemli olduğunu anladım. Sonunda Internet Explorer kullanırken yukarıdaki kod oldukça iyi çalışıyor.
Diğer tarayıcıları kullanmakla birlikte, akışların/soketlerin düzgün şekilde kapatılmadığı anlaşılıyor, çünkü içerikler zaten yüklenmiş gibi görünse de, yükleme göstergeleri oldukça uzun bir süredir çalışıyor. Bazen, siteler tamamen forwardData(...)
yılında ...
if ((read = inputStream.read(buffer)) > 0) {
yüklenir ve ipler de asmak gibi görünüyor değildir. Akışın bazı veriler sağlayıp sağlayamayacağını ya da read
'un bu engelleme çağrısının nasıl önleneceğini nasıl anlayabileceğimi bilmiyorum.
Neyi yanlış yaptığımı ve verileri düzgün bir şekilde nasıl iletebileceğimi bilen var mı? Böylece tüm tarayıcılar gereksiz gecikmeler olmadan içeriği doğru bir şekilde yüklerler mi?
Bu beni kesinlikle ileriye doğru büyük bir adım attı. Yardım ettiğin için teşekkür ederim! – Trinimon