Я недавно наткнулся на статью, описывающую простейший грувлет, позволяющий исполнить любой код на Groovy у Вас на сервере. Мне это показалось очень удобным для организации отладочного бэкдора.
Проблема в то, что грувлеты — это всё таки сервер, а у нас есть еще толстый клиент на Swing. Для него мне хотелось бы сделать нечто похожее, но встраивание какого нибудь embedded Jetty или Tomcat только для этого в клиент выглядело как то слишком.
По счастью, мне попалась на глаза и другая статья — про наличие в стандартной библиотеке Java простейшего веб сервера. Вот им то я и решил воспользоваться.
Пишем Main:
Продолжаем писать на груви, так легче :)
Теперь сам обработчик HTTP запросов:
Запускаем, работает!

Проблема в то, что грувлеты — это всё таки сервер, а у нас есть еще толстый клиент на Swing. Для него мне хотелось бы сделать нечто похожее, но встраивание какого нибудь embedded Jetty или Tomcat только для этого в клиент выглядело как то слишком.
По счастью, мне попалась на глаза и другая статья — про наличие в стандартной библиотеке Java простейшего веб сервера. Вот им то я и решил воспользоваться.
Пишем Main:
public class Main { public static void main(String[] args) { // Порт может задаваться аргументом комадной строки, или как нибудь еще HttpBackdoorRunner runner = new HttpBackdoorRunner(18999, true); runner.start(); } }
Продолжаем писать на груви, так легче :)
import com.sun.net.httpserver.HttpServer import java.util.concurrent.Executors /** * Класс для запуска сервера с нашим хендлером (встроенный сервер - он не сервлет контейнер!) */ class HttpBackdoorRunner { final int port final boolean silent HttpBackdoorRunner(int port, boolean silent) { this.port = port this.silent = silent } def start() { try { InetSocketAddress addr = new InetSocketAddress(port); HttpServer server = HttpServer.create(addr, 0); server.createContext("/", new BackdoorHandler()); server.setExecutor(Executors.newCachedThreadPool( )); server.start(); } catch(Exception e) { if (silent) { // Ignore } else throw new RuntimeException(e) } } }
Теперь сам обработчик HTTP запросов:
/** * Этот уровень абстракции мне нужен чтобы его же вызывать и из грувлета - для бэкдора на сервере * В грувлете способ получения текста скипта, URI и стрима на вывод будут иные, а обработка скрипта - та же */ class BackdoorScriptRunner { void runScript(script, responseBody, uri) { def scriptOutput = new ByteArrayOutputStream() if (script) { // Redirect output def saveOut = System.out def stream = new PrintStream(scriptOutput) System.out = stream try{ def result = new GroovyShell().run(script, "dynamic.groovy"); } catch (Throwable e) { e.printStackTrace(stream); } System.out = saveOut } responseBody.println createHTML(uri, script, scriptOutput) responseBody.close(); } String createHTML(uri, script, scriptOutput) { """ <form action="${uri}" method="post"> <h2>BackDoor</h2> Code comes here: <br> <textarea cols="120" rows="5" name="groovyscript"> ${script ? script : ""}</textarea> <br> <input type="submit" value="Go!" /> </form> <br> ${scriptOutput.toString() ? "<h2>Output</h2><pre>${scriptOutput}</pre>" : ""} """ } }
Запускаем, работает!

