Charles で HTTP レスポンスの書き換え
転職して、すっかりサーバサイドのプログラミングをしなくなりました。このブログを久々に見ました。
さて、デモや検証などの目的で、お客さんのウェブサイト上で勝手にJavaScript を動かしたい... という時に、Charles Web Proxy というツールがとても便利です。 もともとは HTTP モニタリング/デバッグツールですが、もっぱら HTTP レスポンスの書き換え用途にのみ使っています。
基本的に有償のツールで、私は会社の保有するライセンスを登録して使っています。無償でも使えますが、起動して15分間までしか使えないので、デモなどは難しいです。
リライト設定
Tools > Rewite で Enable Rewrite にチェックを入れて、Sets から新たなルールを Add します。 Type = Body を選択 (紛らわしいのですが、これは HTML body の意味ではなく、HTML のペイロードを書き換える時には head であっても必ず Body を選択するようです)、Where では Response にチェック。
JS を挿入したい時によくやるのは、<head> の閉じタグの直前に <script> を挿入する方法。</head> を <script>...</script></head> に置換 (=Replace All) すれば設定完了です。
SSL Proxy の設定
書き換えをしたいサイトが SSL の場合、Proxy > SSL Proxy Settings... から、Enable SSL Proxying にチェックを入れておきます。Host には対象サイトの URL, Port は * と入力。
証明書のインストールと信頼
このままではブラウザでアクセスする際に、信頼できる証明書がないということでプライバシーエラーが出てしまいます。
Help > SSL Proxying > Install Charles Root Certificate を選択し、ルート証明書をインストールします。その後 Mac のキーチェーンアクセスツールを開き、Charles で検索。証明書が信頼されていないことを示す赤い×マークが出てくるので、そこをクリック。"信頼" セクションから、"常に信頼" を選択しておきます。
その後 Charles を再起動すると、リライトが始まります。
以上です。
一番簡単な WebLogic データソースのテスト
11g, 12c 以降の WebLogic データソースでは色々な機能が追加されており、データソースの設定をいじり回すことが多いです。
これまで WebLogic にデータソースを作成してテストをする際はわざわざ Web アプリにしてデプロイしていましたが、データソースがデプロイされている WebLogic Server の weblogic.jar をクラスパスに指定すれば、スタンドアロンの Java プロセスからルックアップできることに今さらながら気がつきました。
1. WebLogic データソースの作成
ここでは jdbc/GridLinkDS という JNDI 名で、GridLink データソースを作成しています。
2. テスト用の main クラスを記述&コンパイル
"jdbc/GridLinkDS" で普通にルックアップしています。
public class MultiDSTest {
public static void main(String args[]) {
String serverHost = "localhost";
String serverPort = "7001";
String dbusername = "system";
String dbpassword = "oracle";
String dsname = "jdbc/GridLinkDS";
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://" + serverHost + ":" + serverPort);
env.put("user", dbusername);
env.put("password", dbpassword);
String information = "";
try {
Context context = new InitialContext(env);
javax.sql.DataSource ds =
(javax.sql.DataSource) context.lookup(dsname);
Connection connection = ds.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet;
String sql;
System.out.println("Got a connection from...");
sql = "select sys_context('userenv', 'instance_name'), sys_context('userenv', 'server_host'), sys_context('userenv', 'service_name') from dual";
resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
information = resultSet.getString(1) + " " + resultSet.getString(2) + " " + resultSet.getString(3);
}
System.out.println(information);
statement.close();
resultSet.close();
connection.close();
} catch (Exception e) {
System.out.println("Error:" + e);
}
}
}
3. 実行
クラスパスに weblogic.jar を追加してから java コマンドで上記クラスファイルを実行すると、 "jdbc/GridLinkDS" が普通にルックアップできます。
weblogic.jar は 12.1.3 の場合、<MiddlewareHome>/wlserver/server/libweblogic.jar に存在します。
わざわざ WebApp の形にしてデプロイしなくても良いんですね。
WebLogic 管理サーバの起動に失敗
BEA-090870 The realm "myrealm" failed to be loaded:
新しく構築した仮想サーバ (OracleLinux 6U5) に WebLogic Server 12.1.2 をインストール、ドメイン作成して起動したところ、上記のエラーメッセージが出て起動できない。
原因は /etc/hosts にホスト名を書き忘れていたことでした。
WLS はホスト名を基準として IP アドレスをバインドするので、起動時に IP アドレスが取得できず、このようにセキュリティレルムのエラーが出力されるみたいです。これは、Configuration Wizard でドメイン構成時のリスン・アドレスに DNS 名ではなく IP アドレスを指定していても、同じことがおこりました。
RMI server port を明示的に指定する(7u4 and later)
JMX over RMI で JMX モニタリングを行う際、サーバー側は「RMI registry port」(クライアントが接続時に指定するポート)と「RMI server port」(内部で使われるポート)と2つのポートを使います。後者の RMI server はデフォルトではランダムに振られるので、ssh tunnel で監視したいようなときは困ってしまうけど、Java7u4 以降は明示的に指定できるようになっているらしいのでメモ。
- RMI registry port
デフォルトなし。かならず -Dcom.sun.management.jmxremote.port=$PORT で指定が必要。
- RMI server port
デフォルトではランダムに振られる。明示的に固定したいときは、-Dcom.sun.management.jmxremote.rmi.port=$PORT を指定。
特定プロセスのプロセスメモリ使用量の推移をとりつづけるワンライナー
while [ 1 ]; do ps alx | grep <PID> | grep -v 'grep' | awk '{printf ("%d\t%s\n", $8,$13)}' ; sleep 5; done
DOM ドキュメントから XML 形式 String に変換する
Jdk1.4 では SOAPBody.toString() で全体が xml 形式で取得できていたのが、6ではルートエレメントしかとれなくなったという事象を確認。回避策として。
Document doc = soapBody.extractContentAsDocument(); StringWriter sw = new StringWriter(); TransformerFactory tfac = TransformerFactory.newInstance(); Transformer transformer = tfac.newTransformer(); transformer.transform( new DOMSource(doc), new StreamResult(sw) ); String xml = sw.toString(); System.out.println( xml );
追記 - SOAPBody.extractContentAsDocument についての注意点
SOAPBody.extractContentAsDocument メソッドを実行することで DOM Document として SOAPBody の全内容は取得できるのですが、これを実施すると大本の SOAPBody の中身が抜き出されてしまいます。
http://java.sun.com/javase/ja/6/docs/ja/api/javax/xml/soap/SOAPBody.htm
ので、xml として出力したあとは、SOAPBody.addDocument を使用して SOAPBody に DOM Document の中身を戻してあげる必要があります。しかし、こうも変換変換を繰り返さないといかんのは心配ですね。どうしてこういう仕様になってるのかな。
vncserver の使用ポート
VNCserverは、デフォルトポート 5900 に、VNCサービス起動時のディスプレイ番号を加えた数字が接続ポートとして使用されるようです。
vncserver :2
として起動した場合、ポートは5902。