如何将HttpResponse转发到开放客户端套接字? (Java程序充当代理)

时间:2014-06-20 06:14:06

标签: java apache sockets proxy httpresponse

我正在使用apache的httpclient lib。我设法通过向服务器发送GET请求来获取HttpResponse。现在我要做的是将我得到的响应发送到clientSocket输出流。

所以基本上我想将从服务器收到的任何内容发送到开放客户端连接。由于我使用的是HttpClient,因此我以HttpResponse对象的形式获得响应。我尝试了以下方法:

private void forwardRequest(String header, String url){

    try {

    CloseableHttpClient httpclient = HttpClients.createDefault();

    HttpGet httpget = new HttpGet(url);

    CloseableHttpResponse response;

    //Adding the request headers to httpget
    String lines[] = header.split("\\n");

    for (String str : lines) {

        String parts[] = str.split(":", 2);
        httpget.addHeader(parts[0], parts[1]);

    }

    HttpResponse respone;

    response = httpclient.execute(httpget);

    //It works till here I can read from the response and print out the html page
    //But after this I don't know how to send it to client
    OutputStream bos = clientSocket.getOutputStream(); 
    PrintWriter pw = new PrintWriter(bos); 
    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

     while ((line = rd.readLine()) != null) {

            pw.println(line);

            //bos.write(line.getBytes());        //This also doesn't work
     }

     response.close();
}

此外,clientSocket是一个全局变量,它与ServerSocket关联,如:

clientSocket = serverSocket.accept();

我不期待完整的解决方案。只是指出我正确的方向..谢谢你!

修改

我根据EJP的建议尝试了以下内容..它仍然无法正常工作。我想知道它是否正确实施了?

int portNumber = 8012; // port on which the program listens

        ServerSocket serverSocket =
                new ServerSocket(portNumber); //the socket at which the program listens 
        Socket clientSocket = serverSocket.accept();  //clientSocket of the program
        Socket toServer = new Socket("localhost", 8089); //proxy server to which program connects
        PrintWriter out =
                new PrintWriter(toServer.getOutputStream(), true);
        PrintWriter outClient =
                new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
        BufferedReader inServer = new BufferedReader(
                new InputStreamReader(toServer.getInputStream()));

            ) {
        String inputLine;
            while ((inputLine = in.readLine()) != null) {
                out.println(inputLine); //Writing to proxy server
                outClient.println(inServer.readLine()); //writing back to original request sender
                System.out.println(inputLine);
            }

2 个答案:

答案 0 :(得分:0)

客户端发出HTTP请求,因此需要HTTP响应。如果全局clientSocket只是一个原始TCP套接字而不是HttpClient,那么您需要自己添加HTTP响应协议头。

你有来自服务器的内容,你要首先返回一个HTTP响应200 OK,然后用回车符+换行符(CR + LF),然后是Content-length:,然后是文件。如果您只是代理文本文档,那么您可以在这里转换为字符串,但除此之外,我只是将mime类型,字符集和实体作为Web服务器响应的原始字节传递,这样您就可以代理任何文档,包括图像或二进制文件。

看起来像这样:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: length

<html> ...
</html>

从服务器传递http标头:

HttpEntity entity = response.getEntity();
// technically you should check the HTTP response rather than assume it is a 200
int statusCode = httpResp.getStatusLine().getStatusCode();
if(statusCode != 200)
    ... // do something with non 200 responses ?

clientSocket.write("HTTP/1.1 200 OK\r\n");

Header[] responseHeaders = response.getAllHeaders();
for(Header header : responseHeaders) {
     clientSocket.write(header.toString() + "\r\n");
}

clientSocket.write("\r\n"); // empty line required

// Use BufferedInputStream to deal in bytes
BufferedInputStream input = new BufferedInputStream(entity.getContent());
byte[] buf = new byte[8192];
int bytesRead;
while ((bytesRead = input.read(buf, 8192)) > 0) {
   clientSocket.write(buf, bytesRead);
}

我说&#34;像这样的事情&#34;,不要接受这个文字,我怀疑它编译。我不会在我面前设置开发站,但这是一般的想法。

注意:由于您使用的是Apache客户端lib,因此您应该能够使用特定的HTTP客户端而不是编写原始协议。这将在某种程度上抽象出HTTP协议。如果其他人没有提供更好的答案,我会在稍后更新答案。

答案 1 :(得分:0)

如果您只是转发请求和响应,那么除了请求的第一行之外,您根本不需要参与HTTP协议。如果客户知道您是代理,您将获得包含完整网址的GET请求,或者同时获得CONNECT请求。您所要做的就是连接目标,然后同时复制两个方向的字节。