2

私はJavaで小さなプロキシを作成しています。このプロキシは、基本的に2つの特定のファイルを選択し、それらに対していくつかの追加処理を実行します。1つのURLは、コンテンツから情報を取得してから渡します。応答コンテンツをフィルタリングしたいもう1つのファイルは、xml deflateでエンコードされています(いくつかの子要素を削除したい)。

これで、すべてのコンテンツを通過するだけでプロキシが正常に機能します。ただし、xmlファイルをフィルタリングしようとすると、実際にはコンテンツがクライアントに送信されません。

ここにいくつかのコードがあります:

ソケット接続を受け入れるときに生成されるThreadrun()メソッド内で、要求がフィルター処理するファイルに対するものであると判断したら、次のように呼び出します。

filterRaceFile(serverIn, clientOut);     // This won't send content     
//streamHTTPData(serverIn, clientOut, true); // This passes through fine (but all content of course).

フィルタリング方法自体は次のとおりです。

private void filterRaceFile(InputStream is, OutputStream os) {
    // Pass through headers before using deflate and filtering xml
    processHeader(is, os, new StringBuilder(), new StringBuilder());        

    // Seems to be 1 line left, inflater doesn't like it if we don't do this anyway...?
    try {
        os.write(readLine(is, false).getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }       

    InflaterInputStream inflate = new InflaterInputStream(is);
    DeflaterOutputStream deflate = new DeflaterOutputStream(os);
    int c = 0;
    try {
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document xdoc = db.parse(inflate);
        Node id = xdoc.getElementsByTagName("id").item(0);
        Node msg = xdoc.getElementsByTagName("message").item(0);
        StringBuilder xml_buf = new StringBuilder("<race>\n");

        xml_buf.append("<id>").append(id.getTextContent()).append("</id>\n");
        xml_buf.append("<message>").append(msg.getTextContent()).append("</message>\n");
        xml_buf.append("<boats>\n");

        NodeList allBoats = xdoc.getElementsByTagName("boat");
        int N = allBoats.getLength();

        for (int i = 0; i < N; ++i)
        {
            Node boat = allBoats.item(i);
            Element boat_el = (Element)boat;                
            double lat = Double.parseDouble(boat_el.getElementsByTagName("lat").item(0).getTextContent());
            double lon = Double.parseDouble(boat_el.getElementsByTagName("lon").item(0).getTextContent());
            double dist = Geodesic.vincenty_earth_dist(proxy.userLat, proxy.userLon, lat, lon)[0];
            if (dist <= LOS_DIST)
            {
                String boatXML = xmlToString(boat);
                //<?xml version="1.0" encoding="UTF-8"?> is prepended to the xml
                int pos = boatXML.indexOf("?>")+2;
                boatXML = boatXML.substring(pos);
                xml_buf.append(boatXML);
                ++c;
            }
        }
        System.out.printf("%d boats within LOS distance\n", c);

        xml_buf.append("</boats>\n");
        xml_buf.append("</race>");

        byte[] xml_bytes = xml_buf.toString().getBytes("UTF-8");
        deflate.write(xml_bytes);

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

    // flush the OutputStream and return
    try {
        os.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
    }

また、サーバーのInputStreamをクライアントのOutputStreamに書き込むだけの単純なパススルーメソッドもあり、readLineも使用して正常に機能します。つまり、他のURLは問題なくブラウザーに表示されるため、readLineは問題ありません。ブールパラメータは、マークと読み取りを内部的に使用するため、デフレートストリームから読み取っていることを通知します。これは、デフレートストリームではサポートされていません。

XMLは非常に単純です。

<race> 
  {some data to always pass thru}
    <boats>
       <boat>
          <id>1234</id>
          ....
          <lat>-23.3456</lat>
          <lon>17.2345</lon>
       </boat>
       {more boat elements}
     </boats>
   </race>

そして、クライアントに送信したいxmlを生成しますが、クライアントはそれを受信しません(元の応答にもContent-Lengthヘッダーがないにもかかわらず、Webデバッガーにcontent-lengthが0と表示されます) )。

何が起こっているのか、または私がしていないことを私が何をすべきかについてのアイデアはありますか?

4

2 に答える 2

0

エラーは表示されませんが、既に を使用している場合はDocument、ドキュメントを変更してから、XML ライブラリを使用してドキュメント全体を書き出すことはできませんか? これは、手動の XML フォーマットよりも堅牢なようです。

于 2011-02-08T23:18:43.300 に答える
-1

出力をフラッシュしてストリームを正しく閉じるには、 deflate.write() の後に deflate.close() への呼び出しを追加する必要があります。

于 2014-12-05T18:25:21.807 に答える