2013年5月26日日曜日

LittleProxyでフィルターする。

http://wakalambda.blogspot.jp/2013/05/clojurejettyproxyservlet.html

をやったあとに、ホスト名とコンテントタイプが指定したものだったときだけ
コンテンツを表示するようにしようとしたらどこを拡張していいかわからなかった。

あきらめてLittleProxyでやってみたら簡単にできた。
(defproject littleproxy-filter-example "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.littleshoot/littleproxy "0.5.1"]]
  )
(ns littleproxy-filter-example.core)

(import '(org.littleshoot.proxy DefaultHttpProxyServer
                                HttpResponseFilters
                                HttpRequestFilter
                                HttpFilter))

(use 'clojure.java.io)

(def ^:dynamic *log-file* "/tmp/proxy-log.txt")

(defn write-log [request response]
  (let [host (.getHeader request "Host")
        uri (.getUri request)
        content-type (.getHeader response "Content-Type")]
    (if (.startsWith (str content-type) "text/html")
      (try
        (spit *log-file*
              (str
               "new response  -----------------------------------------------------------\n"
               uri "\n"
               content-type "\n"
               (.toString (.getContent response) "UTF-8") "\n"
               )
              :append true)
        (catch Exception e
          (spit *log-file* (str e) :append true))
        ))))

(defn get-filter [host-and-port]
  (proxy [HttpFilter] []
    (filterResponses [request]
      true
      ;(.endsWith (.getHeader request "Host") "clojure.org")
      )
    (filterResponse [request response]
      (write-log request response)
      response)
    (getMaxResponseSize []
      Integer/MAX_VALUE)))

(defn create-response-filters []
  (proxy [HttpResponseFilters] []
    (getFilter [host-and-port]
      (get-filter host-and-port))))

(defn create-request-filter []
  (proxy [HttpRequestFilter] []
    (filter [http-request]
      ;; some ops
      )))

(def ^:dynamic *server* (DefaultHttpProxyServer. 8888 (create-request-filter) (create-response-filters)))
(.start *server*)
;; (.stop *server*)

2013年5月20日月曜日

swank-jsを動かしてみた

https://github.com/swank-js/swank-jsのREADMEを参考に。

nodejsはyum install nodejs

npmはgit clone https://github.com/isaacs/npm.git
でmake install

npm install -g swank-js
swank-jsで起動

js2-modeが上手く動かなかったので、横道にそれてemacs24にした。
color-themeみたいのとpackageが標準で入ってて便利になってた。

packageからslime, slime-js, js2-modeをいれた。

ウェブブラウザで
http://IP:8009/swank-js/test.htmlを開く


javascriptファイルを開いてjs2-modeとslime-js-minor-modeを実行。
slime-connect
, select-remoteでブラウザ選択

C-M-xで関数を送る。
slime-eval-regionでリージョンを送る。


$('head').append('<link rel="stylesheet" href="http://IP/a.css" type="text/css" />');
とかするとheadタグの中にcssを追加させられる。
 
cssファイルを変更してから、slime-js-refresh-cssで変更が反映される。

時間がないので、設定のメモだけ、使いこなせたらよさそうなのだけど。
swank-jsのREADMEに書いてあるキーバインドが使えないことがあったりして、
うまく設定できてない気もする。

http://emacsrocks.com/e11.html
みたいなことできたらかっこいい。

2013年5月4日土曜日

emacsをdaemon化してみた。

LinuxをVirtualBoxで動かしてるけど、接続しっぱなしにしたままホストOSのスリープをするとゲストOSがフリーズする可能性が高かったので、スリープ前に閉じても復帰しやすくするために。

こんな感じのスクリプトで、daemonがいなければ作って、ログイン元のIPアドレスのXサーバに表示させる。
ログイン元のIPアドレスの抽出が適当なので駄目なケースもあるのかも。同じユーザで別の場所から入ってるとか。


#!/bin/sh
ret=`pgrep -f 'emacs --daemon'`
if [ -z $ret ]; then
        emacs --daemon
fi

name=`whoami`
addr=`w -h -s | grep "^$name" | awk '{print $3}' | grep '^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$' | head -n 1`

emacsclient -c -n -d $addr:0.0

ClojureでJettyのProxyServletを使う

細かく挙動を変更させられるプロキシサーバが欲しかったので、Clojureでできないか調べた。

 http://grepcode.com/file/repo1.maven.org/maven2/org.eclipse.jetty/example-jetty-embedded/8.1.1.v20120215/org/eclipse/jetty/embedded/ProxyServer.java

基本的にはこれをClojureに書き直しただけ。

ProxyServletまではJettyサーバにインスタンスが保存されてしまうのでREPLで変更しても反映されない。
REPLで動作を変更させるためにはProxyServletから他の関数を呼ぶようにしてそこを変更するようにすれば良い。
下のコードではprocess-customize-exchangeとprocess-customize-continuationへの変更は動的に反映される。

core.clj
(ns jetty-proxy.core)

(import '(org.eclipse.jetty.server Server)
        '(org.eclipse.jetty.server.nio SelectChannelConnector)
        '(org.eclipse.jetty.servlet ServletContextHandler ServletHolder ServletHandler)
        '(org.eclipse.jetty.servlets ProxyServlet)
        '(javax.servlet.http HttpServletRequest))

(defn process-customize-exchange [exchange ^HttpServletRequest request]
  (println "customize-exchange")
  (println (str "requestURL: " (. request getRequestURL)))
  )

(defn process-customize-continuation [continuation]
  (println "customize-continuation")
  )

(defn create-proxy-servlet []
  (proxy [ProxyServlet] []
    (customizeExchange [exchange request]
      (process-customize-exchange exchange request)
      (proxy-super customizeExchange exchange request))
    (customizeContinuation [continuation]
      (process-customize-continuation continuation)
      (proxy-super customizeContinuation continuation))
    ))

(defn create-server []
  (let [server (Server.)
        handler (ServletHandler.)
        connector (SelectChannelConnector.)]
    (. connector setPort 8888)
    ;;(. handler addServletWithMapping ProxyServlet "/*")
    (. handler addServletWithMapping (ServletHolder. (create-proxy-servlet)) "/*")
    (. server addConnector connector)
    (. server setHandler handler)
    server))

(def *server* (create-server))
(. *server* start)
;; (. *server* stop)


project.clj
(defproject jetty-proxy "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.eclipse.jetty/jetty-server "8.1.9.v20130131"]
                 [org.eclipse.jetty/jetty-servlet "8.1.9.v20130131"]
                 [org.eclipse.jetty/jetty-servlets "8.1.9.v20130131"]
                 [org.clojure/clojure-contrib "1.2.0"]
                 ])


これくらいだとRubyでWEBrick使う方が簡単だし手軽に見えるけど、 clojureで書くことが目的の半分なので。

参考:http://jp.rubyist.net/magazine/?0002-WEBrickProxy