SimonDanisch / Bonito.jl

Serving JS to the browser
MIT License
204 stars 29 forks source link

accessing query variables in Request #219

Closed bjarthur closed 4 months ago

bjarthur commented 4 months ago

when i serve a website with Bonito, i'd like the user to be able to configure the generated HTML by appending "?var=val" to the end of the URL. programmatically something like this would be convenient:

app = App() do session::Session
    query = session...   # var=val stored as a Dict or similar somewhere in the session Struct
    return DOM.div(query["var"])
end

currently i think this is not possible.

digging into the code, the query is stored in request here and subsequently further down the call stack in context here, but then is never stored. i think the definition of Session would need a new field to store this information.

does that make sense? if so, i'm happy to work on a PR with some guidance.

SimonDanisch commented 4 months ago

There is:

app = App() do session::Session, request::HTTP.Request
    requested_path= request.path # There should be some query parsing tools somewhere in in URIs or HTTP.jl
    ...
end
SimonDanisch commented 4 months ago

I'm surprised that App isn't documented at all, I fuzzily remember writing docstrings for it^^ Maybe you could add a PR for that?

bjarthur commented 4 months ago

oh! my bad. App is documented, in two places, and i did read the docs when first learning Bonito, but then forgot:

julia> using Bonito

help?> App
search: App append! applicable isapprox swapproperty! apropos hasproperty replaceproperty!

  App(callback_or_dom; title="Bonito App")
  App((session, request) -> DOM.div(...))
  App((session::Session) -> DOM.div(...))
  App((request::HTTP.Request) -> DOM.div(...))
  App(() -> DOM.div(...))
  App(DOM.div(...))

  Usage:

  using Bonito
  app = App() do
      return DOM.div(DOM.h1("hello world"), js"""console.log('hello world')""")
  end

  If you depend on global observable, make sure to bind it to the session. This is pretty
  important, since every time you display the app, listeners will get registered to it, that
  will just continue staying there until your Julia process gets closed. bind_global prevents
  that by binding the observable to the life cycle of the session and cleaning up the state
  after the app isn't displayed anymore. If you serve the App via a Server, be aware, that
  those globals will be shared with everyone visiting the page, so possibly by many users
  concurrently.

  global some_observable = Observable("global hello world")
  App() do session::Session
      bound_global = bind_global(session, some_observable)
      return DOM.div(bound_global)
  end

perhaps it would be worthwhile adding an example which explicitly used Request.