2013年5月4日土曜日

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

0 件のコメント:

コメントを投稿