java - 尝试创建代理,不起作用

标签 java http proxy httpwebrequest

我有一项任务是编写代理服务器。简单测试有效,但是当我将 firefox 配置为使用代理时,响应输入流从未准备好。你能帮忙吗?

ProxyServer(重要方法)

public void start() {
        while (true) {
            Socket serverSocket;
            Socket clientSocket;
            BufferedWriter toClient;
            BufferedWriter toServer;
            try {
                //The client is meant to put data on the port, read the socket.
                clientSocket = listeningSocket.accept();
                Request request = new Request(clientSocket.getInputStream());
                System.out.println("Accepted a request!\n" + request);
                while(request.busy);
                //Make a connection to a real proxy.
                //Host & Port - should be read from the request
                URL url = null;
                try {
                    url = new URL(request.getRequestURL());
                } catch (MalformedURLException e){
                    url = new URL("http:\\"+request.getRequestHost()+request.getRequestURL());
                }

                //remove entry from cache if needed
                if (!request.getCacheControl().equals(CacheControl.CACHE) && cache.containsRequest(request)) {
                    cache.remove(request);
                }

                Response response = null;

                if (request.getRequestType() == RequestType.GET && request.getCacheControl().equals(CacheControl.CACHE) && cache.containsRequest(request)) {
                    response = cache.get(request);
                } else {
                    //Get the response from the destination
                    int remotePort = (url.getPort() == -1) ? 80 : url.getPort();
                    System.out.println("I am going to try to connect to: " + url.getHost() + " at port " + remotePort);
                    serverSocket = new Socket(url.getHost(), remotePort);
                    System.out.println("Connected.");

                    //write to the server - keep it open.
                    System.out.println("Writing to the server's buffer...");
                    toServer = new BufferedWriter(new OutputStreamWriter(serverSocket.getOutputStream()));
                    toServer.write(request.getFullRequest());
                    toServer.flush();
                    System.out.println("flushed.");

                    System.out.println("Getting a response...");
                    response = new Response(serverSocket.getInputStream());
                    System.out.println("Got a response!\n" + response);
                    //wait for the response
                    while(response.isBusy());   
                }

                if (request.getRequestType() == RequestType.GET && request.getCacheControl().equals(CacheControl.CACHE)) {
                    cache.put(request, response);
                }

                response = filter.filter(response);

                // Return the response to the client
                toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
                toClient.write(response.getFullResponse());
                toClient.flush();
                toClient.close();

            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }

ResponseRequest 类只是非常简单的 HTTP 请求/响应解析器。当我尝试通过代理加载网站时,我得到:


编辑 2

这是另一个尝试。我在 toClient.write(response.getFullResponse());

行之前添加了调试打印
Accepted a request!
Request
==============================

GET http://t2.technion.ac.il/~srachum/ HTTP/1.1
Host: t2.technion.ac.il
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20100101 Firefox/4.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Proxy-Connection: keep-alive


I am going to try to connect to: t2.technion.ac.il at port 80
Connected.
Writing to the server's buffer...
flushed.
Getting a response...
Got a response!
Response
==============================

HTTP/1.1 200 OK
Date: Sat, 23 Apr 2011 15:54:08 GMT
Server: Apache/2.0.52 (Red Hat)
Last-Modified: Fri, 18 Mar 2011 23:45:24 GMT
ETag: "14928fc-877-49eca5f29cd00"
Accept-Ranges: bytes
Content-Length: 2167
Connection: close
Content-Type: text/html
X-Pad: avoid browser bug

<html>
    ...
</html>


I am going to write the following response:

HTTP/1.1 200 OK
Date: Sat, 23 Apr 2011 15:54:08 GMT
Server: Apache/2.0.52 (Red Hat)
Last-Modified: Fri, 18 Mar 2011 23:45:24 GMT
ETag: "14928fc-877-49eca5f29cd00"
Accept-Ranges: bytes
Content-Length: 2167
Connection: close
Content-Type: text/html
X-Pad: avoid browser bug

<html>
    ...
</html>

编辑 3:

请求

package cs236369.proxy;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import cs236369.proxy.types.CacheControl;
import cs236369.proxy.types.HttpPatterns;
import cs236369.proxy.types.RequestHeader;
import cs236369.proxy.types.RequestType;


public class Request {
    private String fullRequest = "";
    private BufferedReader reader;
    private RequestHeader requestHeader;
    private String requestHost;
    boolean busy = true;
    private CacheControl cacheControl = CacheControl.CACHE;

    public CacheControl getCacheControl() {
        return cacheControl;
    }

    Request(String request) {
        this(new ByteArrayInputStream(request.getBytes()));
    }

    Request(InputStream input){
        reader = new BufferedReader(new InputStreamReader(input));
        try {
            while(!reader.ready()); //wait for initialization.

            String line;
            while ((line = reader.readLine()) != null) {
                fullRequest += "\r\n" + line;

                if (HttpPatterns.CACHE_CONTROL.matches(line)) {
                    cacheControl = (CacheControl) HttpPatterns.RESPONSE_CODE.process(line);
                } else if (HttpPatterns.REQUEST_HEADER.matches(line)) {
                    requestHeader = (RequestHeader) HttpPatterns.REQUEST_HEADER.process(line);
                } else if (HttpPatterns.HOST.matches(line)) {
                    requestHost = (String) HttpPatterns.HOST.process(line);
                }
            }
            fullRequest = "\r\n" + fullRequest.trim() + "\r\n\r\n";
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        busy = false;
    }

    public String getFullRequest() {
        return fullRequest;
    }

    public RequestType getRequestType() {
        return requestHeader.type;
    }

    public String getRequestURL() {
        return requestHeader.url;
    }

    public String getRequestProtocol() {
        return requestHeader.protocol;
    }

    public String getRequestHost() {
        return requestHost;
    }

    public boolean isBusy() {
        return busy;
    }

    @Override
    public String toString() {
        return "Request\n==============================\n" + fullRequest;
    }
}

响应

package cs236369.proxy;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import cs236369.proxy.types.CacheControl;
import cs236369.proxy.types.HttpPatterns;

public class Response {
    private String fullResponse = "";
    private BufferedReader reader;
    private boolean busy = true;
    private int responseCode;
    private CacheControl cacheControl;

    public Response(String input) {
        this(new ByteArrayInputStream(input.getBytes()));
    }

    public Response(InputStream input) {
        reader = new BufferedReader(new InputStreamReader(input));
        try {
            while (!reader.ready());//wait for initialization.

            String line;
            while ((line = reader.readLine()) != null) {
                fullResponse += "\r\n" + line;

                if (HttpPatterns.RESPONSE_CODE.matches(line)) {
                    responseCode = (Integer) HttpPatterns.RESPONSE_CODE.process(line);
                } else if (HttpPatterns.CACHE_CONTROL.matches(line)) {
                    cacheControl = (CacheControl) HttpPatterns.CACHE_CONTROL.process(line);
                }
            }
            reader.close();
            fullResponse = "\r\n" + fullResponse.trim() + "\r\n\r\n";
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        busy = false;
    }

    public CacheControl getCacheControl() {
        return cacheControl;
    }

    public String getFullResponse() {
        return fullResponse;
    }

    public boolean isBusy() {
        return busy;
    }

    public int getResponseCode() {
        return responseCode;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((fullResponse == null) ? 0 : fullResponse.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof Response))
            return false;
        Response other = (Response) obj;
        if (fullResponse == null) {
            if (other.fullResponse != null)
                return false;
        } else if (!fullResponse.equals(other.fullResponse))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Response\n==============================\n" + fullResponse;
    }
}

最佳答案

有一次我写了一个发送 HTTP 请求的程序……我的代码是这样的:

String host="www.google.com";
String request="GET / HTTP/1.0\r\nHost: "+host+"\r\nAccept-Encoding: gzip\r\n\r\n";
System.out.println(request);
Socket sock=new Socket(host,80);
InputStream inp=sock.getInputStream();
OutputStream outp=sock.getOutputStream();
outp.write(request.getBytes());
byte[] buff=new byte[999];
while(true){
    int n=inp.read(buff);
    if(n<0) break;
    System.out.println(new String(buff,0,n));
}
inp.close();
outp.close();
sock.close();

此代码有效。乍一看,它看起来像你的。您可以尝试将两者结合起来,观察问题何时开始出现。也许您的 Response 解析器有问题?

附言您确定您从浏览器收到的原始请求以两个换行符结尾吗?在您发布的日志中,似乎只有一个空行...

编辑: 我编译了您的代码并稍作修改,它运行良好。我做的事情:

  • 注释掉有关 CacheControl、过滤和 RequestHeader 的所有内容,因为我没有这些类的源代码;
  • 添加了 URL 和主机的简单解析,因为没有它们就无法工作;
  • 添加了一项检查以删除 Accept-Encoding,因为许多服务器使用的 gzip 在此程序中已损坏;
  • 添加了检查以在两次换行后停止解析请求。

此程序用作 Firefox 的代理服务器,并且可以很好地处理 HTML 代码。请编译我的版本并尝试它是否适合你。可能与 Firefox 设置有关?

请注意,此代理服务器正在破坏二进制数据,例如图像和 gzip 压缩的 HTML。这一定是InputStreamReader和OutputStreamWriter的使用引起的;它们将字节转换为字符,反之亦然,这对文本很有用,但对于二进制数据,您最好“按原样”使用 InputStream 和 OutputStream。

public class AmirRachum {

    public static void main(String[] args) {
        try{
            int port=38824;

            ServerSocket listeningSocket=new ServerSocket(port);
            System.out.println("Socket created");

            while (true) {
                Socket serverSocket;
                Socket clientSocket;
                BufferedWriter toClient;
                BufferedWriter toServer;
                try {
                    //The client is meant to put data on the port, read the socket.
                    clientSocket = listeningSocket.accept();
                    Request request = new Request(clientSocket.getInputStream());
                    System.out.println("Accepted a request!\n" + request);
                    while(request.busy);
                    //Make a connection to a real proxy.
                    //Host & Port - should be read from the request
                    URL url = null;
                    try {
                        url = new URL(request.getRequestURL());
                    } catch (MalformedURLException e){
                        url = new URL("http:\\"+request.getRequestHost()+request.getRequestURL());
                    }

                    //remove entry from cache if needed
             /*       if (!request.getCacheControl().equals(CacheControl.CACHE) && cache.containsRequest(request)) {
                        cache.remove(request);
                    }*/

                    Response response = null;

             /*       if (request.getRequestType() == RequestType.GET && request.getCacheControl().equals(CacheControl.CACHE) && cache.containsRequest(request)) {
                        response = cache.get(request);
                    } else*/ {
                        //Get the response from the destination
                        int remotePort = (url.getPort() == -1) ? 80 : url.getPort();
                        System.out.println("I am going to try to connect to: " + url.getHost() + " at port " + remotePort);
                        serverSocket = new Socket(url.getHost(), remotePort);
                        System.out.println("Connected.");

                        //write to the server - keep it open.
                        System.out.println("Writing to the server's buffer...");
                        toServer = new BufferedWriter(new OutputStreamWriter(serverSocket.getOutputStream()));
                        toServer.write(request.getFullRequest());
                        toServer.flush();
                        System.out.println("flushed.");

                        System.out.println("Getting a response...");
                        response = new Response(serverSocket.getInputStream());
                        System.out.println("Got a response!\n" + response);
                        //wait for the response
                        while(response.isBusy());   
                    }

            /*        if (request.getRequestType() == RequestType.GET && request.getCacheControl().equals(CacheControl.CACHE)) {
                        cache.put(request, response);
                    }

                    response = filter.filter(response);*/

                    // Return the response to the client
                    toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
                    toClient.write(response.getFullResponse());
                    toClient.flush();
                    toClient.close();

                } catch (IOException e) {
                    e.printStackTrace();
                    continue;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class Request {
        private String fullRequest = "";
        private BufferedReader reader;
    //    private RequestHeader requestHeader;
        private String requestHost;
        private String requestURL;
        boolean busy = true;
    //    private CacheControl cacheControl = CacheControl.CACHE;

     /*   public CacheControl getCacheControl() {
            return cacheControl;
        }*/

        Request(String request) {
            this(new ByteArrayInputStream(request.getBytes()));
        }

        Request(InputStream input){
            reader = new BufferedReader(new InputStreamReader(input));
            try {
                while(!reader.ready()); //wait for initialization.

                String line;
                while ((line = reader.readLine()) != null) {
                    if(!line.startsWith("Accept-Encoding:")) fullRequest += "\r\n" + line;

                /*    if (HttpPatterns.CACHE_CONTROL.matches(line)) {
                        cacheControl = (CacheControl) HttpPatterns.RESPONSE_CODE.process(line);
                    } else if (HttpPatterns.REQUEST_HEADER.matches(line)) {
                        requestHeader = (RequestHeader) HttpPatterns.REQUEST_HEADER.process(line);
                    } else if (HttpPatterns.HOST.matches(line)) {
                        requestHost = (String) HttpPatterns.HOST.process(line);
                    }*/
                    if(line.startsWith("GET ")){requestURL=line.split(" ")[1];System.out.println("url \""+requestURL+"\"");}
                    if(line.startsWith("Host:")){requestHost=line.substring(6);System.out.println("Host \""+requestHost+"\"");}
                    if(line.length()==0){System.out.println("empty line");break;}
                }
                fullRequest = "\r\n" + fullRequest.trim() + "\r\n\r\n";
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            busy = false;
        }

        public String getFullRequest() {
            return fullRequest;
        }

    /*    public RequestType getRequestType() {
            return requestHeader.type;
        }*/

        public String getRequestURL() {
            return requestURL;
        }

    /*    public String getRequestProtocol() {
            return requestHeader.protocol;
        }*/

        public String getRequestHost() {
            return requestHost;
        }

        public boolean isBusy() {
            return busy;
        }

        //@Override
        public String toString() {
            return "Request\n==============================\n" + fullRequest;
        }
    }

    public static class Response {
        private String fullResponse = "";
        private BufferedReader reader;
        private boolean busy = true;
    //    private int responseCode;
    //    private CacheControl cacheControl;

        public Response(String input) {
            this(new ByteArrayInputStream(input.getBytes()));
        }

        public Response(InputStream input) {
            reader = new BufferedReader(new InputStreamReader(input));
            try {
                while (!reader.ready());//wait for initialization.

                String line;
                while ((line = reader.readLine()) != null) {
                    fullResponse += "\r\n" + line;

               /*     if (HttpPatterns.RESPONSE_CODE.matches(line)) {
                        responseCode = (Integer) HttpPatterns.RESPONSE_CODE.process(line);
                    }/* else if (HttpPatterns.CACHE_CONTROL.matches(line)) {
                        cacheControl = (CacheControl) HttpPatterns.CACHE_CONTROL.process(line);
                    }*/
                }
                reader.close();
                fullResponse = "\r\n" + fullResponse.trim() + "\r\n\r\n";
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
            busy = false;
        }

    /*    public CacheControl getCacheControl() {
            return cacheControl;
        }*/

        public String getFullResponse() {
            return fullResponse;
        }

        public boolean isBusy() {
            return busy;
        }

     /*   public int getResponseCode() {
            return responseCode;
        }*/

        //@Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result
                    + ((fullResponse == null) ? 0 : fullResponse.hashCode());
            return result;
        }

        //@Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof Response))
                return false;
            Response other = (Response) obj;
            if (fullResponse == null) {
                if (other.fullResponse != null)
                    return false;
            } else if (!fullResponse.equals(other.fullResponse))
                return false;
            return true;
        }

        //@Override
        public String toString() {
            return "Response\n==============================\n" + fullResponse;
        }
    }

}

关于java - 尝试创建代理,不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5763704/

相关文章:

java - 在具有动态内存大小的机器中设置 java 堆大小

json - 如何使用 express.js 传递 API url JSON http.get res.json(data)

http - haproxy:获取主机名

c# - Vista 上的 WebProxy 和身份验证

java - 空指针异常检查

java - 如何从矩形和点绘制矩形?

java - @RequestParam 和@PathVariable 封装

swift - 使用 Alamofire 4 下载 MP4 文件,同时附加自定义 header

java - 通过代理执行 ant scp 任务

internet-explorer - 如何在 IE 中以编程方式设置代理异常?