Как перезагрузить код при работающем HTTP-сервере?

При запуске http-сервера с использованием HTTP.serve, по-видимому, нет возможности перезагрузить код, который фактически обрабатывает HTTP-запрос. В приведенном ниже примере я хотел бы, чтобы изменения в my_httphandler учитывались без перезапуска сервера. На данный момент мне нужно остановить сервер из REPL, дважды нажав CTRL+C, а затем снова запустить скрипт.

Есть ли обходной путь?

module MyModule

using HTTP
using Mux
using JSON
using Sockets


function my_httphandler(req::HTTP.Request)    
    return HTTP.Response(200, "Hello world")
end

const MY_ROUTER = HTTP.Router()
HTTP.@register(MY_ROUTER, "GET", "/*", my_httphandler)


HTTP.serve(MY_ROUTER, Sockets.localhost, 8081)

end

person tencnivel    schedule 27.05.2019    source источник


Ответы (4)


Я не уверен, кэширует ли Mux обработчики. Пока это не так, это должно работать:

module MyModule

using HTTP
using Mux
using JSON
using Sockets

function my_httphandler(req::HTTP.Request)    
    return HTTP.Response(200, "Hello world")
end

const functionref = Any[my_httphandler]

const MY_ROUTER = HTTP.Router()
HTTP.@register(MY_ROUTER, "GET", "/*", functionref[1])


HTTP.serve(MY_ROUTER, Sockets.localhost, 8081)

end


function newhandler(req::HTTP.Request)    
    return HTTP.Response(200, "Hello world 2")
end

MyModule.functionref[1] = newhandler
person Bill    schedule 27.05.2019
comment
Но как определить этот новый обработчик после запуска http-сервера? Я предполагаю, что мой вопрос эквивалентен тому, как заставить Джулию учитывать изменения в коде без перезапуска сеанса и http-сервера?. Спасибо Билл! - person tencnivel; 28.05.2019
comment
Возможно, вам придется запустить сервер с @async до того, как HTTP.serve(...) запустит сервер, если проблема в том, что вы не получаете обратно командную строку. - person Bill; 28.05.2019
comment
Добавление @async до того, как HTTP.serve(...) вернет мне приглашение, затем я могу повторно запустить нужные строки кода, и изменения действительно будут учтены. Спасибо!! Одно замечание: Mux запускает http-сервер в фоновом режиме. - person tencnivel; 29.05.2019

Revise.jl позволяет автоматически обновлять код во время живого сеанса Julia. Вас могут особенно заинтересовать entr; подробности см. в документации Revise.

person tholy    schedule 28.05.2019

При использовании HTTP.jl: просто добавьте @async перед HTTP.serve

module MyModule

using HTTP
using Sockets


function my_httphandler(req::HTTP.Request)    
    return HTTP.Response(200, "Hello world")
end

const MY_ROUTER = HTTP.Router()
HTTP.@register(MY_ROUTER, "GET", "/*", my_httphandler)


@async HTTP.serve(MY_ROUTER, Sockets.localhost, 8081)

end # module

При использовании Mux.jl: ничего не делать, сервер запущен в фоновом режиме

using Mux

function sayhellotome(name)
  return("hello " * name * "!!!")
end

@app test = (
  Mux.defaults,

  route("/sayhello/:user", req -> begin
    sayhellotome(req[:params][:user])

  end),

  Mux.notfound())

Mux.serve(test, 8082)
person tencnivel    schedule 29.05.2019

Я добавил билет #587 в проект HTTP.jl для рабочего процесса разработчика. поддерживать. Я не уверен, что это ваш вариант использования или нет.

# hello.jl -- an example showing how Revise.jl works with HTTP.jl
# julia> using Revise; includet("hello.jl"); serve();

using HTTP
using Sockets

homepage(req::HTTP.Request) =
    HTTP.Response(200, "<html><body>Hello World!</body></html>")

const ROUTER = HTTP.Router()
HTTP.@register(ROUTER, "GET", "/", homepage)

serve() = HTTP.listen(request -> begin
                 Revise.revise()
                 Base.invokelatest(HTTP.handle, ROUTER, request)
          end, Sockets.localhost, 8080, verbose=true)

В качестве альтернативы у вас может быть файл test/serve.jl, в котором предполагается, что MyModule с маршрутизатором HTTP.jl верхнего уровня называется ROUTER. Вам нужно будет удалить вызов serve в вашем основном модуле.

#!/usr/bin/env julia
using HTTP
using Sockets
using Revise

using MyModule: ROUTER

HTTP.listen(request -> begin
       Revise.revise()
       Base.invokelatest(HTTP.handle, ROUTER, request)
end, Sockets.localhost, 8080, verbose=true)

Более надежное решение будет обнаруживать ошибки; однако у меня возникли проблемы с тем, чтобы заставить это работать, и я сообщил о своем опыте по адресу #541. в Revise.jl.

person clarkevans    schedule 24.09.2020