Code Monkey home page Code Monkey logo

pages.jl's Introduction

Pages.jl

Travis Appveyor

This is a package designed to help get started with web APIs and some basic interaction between Julia and a browser.

Installation

To get the latest tagged version, try:

pkg> add Pages

However, this package is still in early development and is likely to change often. To get the latest, try:

pkg> add Pages#master

Introduction

To get started, try the following:

julia> using Pages

julia> @async Pages.start();
Listening on 0.0.0.0:8000...

This starts a server that is listening at http://localhost:8000 and exposes the Endpoint type with a few methods.

To create an Endpoint, try:

julia> Endpoint("/hello") do request::HTTP.Request
          "Hello world"
       end

This creates a web page at http://localhost:8000/hello that says Hello world.

One nice thing about using Pages is that we can create pages whenever and wherever we want in our Julia code even while the server is running.

Examples

There are a few examples included. The fastest way to see the examples is to run:

julia> Pages.examples(launch=true);

This will start a server and launch a browser open to a page with links to some simple examples. If you prefer not to open a browser to the page from the command line, you can instead run

julia> Pages.examples();

and then navigate to http://localhost:8000/examples.

Current examples include:

  • Requests - Send GET and POST requests from the browser to Julia and print the contents to the REPL.
  • Blank - You can use this for experimemntation, e.g. use Pages.add_library to insert your favorite JavaScript library.
  • Random Ping - For this example, click the "Blank" link and run
julia> Pages.Examples.randomping.start()

This puts you into an infinite loop inserting text to the webpage.

To stop the example, run

julia> Pages.Examples.randomping.stop()

Documentation

This package is sorely lacking documentation, but some of the additional features were recently explained on Discourse:

Acknowledgements

This package benefitted greatly from studying and working with Blink.jl. A lot of the functionality is shared with Blink although Pages does not require Electron and should work with any modern browser.

pages.jl's People

Contributors

ericforgy avatar gitter-badger avatar staticfloat avatar tkelman avatar tlienart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pages.jl's Issues

UndefVarError: `closewrite` not defined

I installed Pages#main (with HTTP v1.10.1) in a clean (activate --temp) environment. The basic example in README.md gives an error:

julia> ┌ Error: error handling request
│   exception =
│    UndefVarError: `closewrite` not defined
│    Stacktrace:
│     [1] (::HTTP.Servers.var"#13#14"{Pages.var"#12#15", HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}, HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})()
│       @ HTTP.Servers ~/.julia/packages/HTTP/IAI92/src/Servers.jl:371
└ @ HTTP.Servers ~/.julia/packages/HTTP/IAI92/src/Servers.jl:373

Also

@async Pages.start();

does not return anything (like Listening on 0.0.0.0:8000...).
Any suggestions?

Add an example for using websockets

I would like to stream data from Julia to Vega-Lite to create updating plots. Could you add a MWE (an echo server for example) for using websockets? Here is what I'm trying to achieve, but with the echo server being replaced with a Julia server. I can probably figure out how to convert the example to use the messaging protocol of Pages.jl, but I do not know how to set the websocket connection up.

how to handle routing without specifying every file?

Sorry if this is a dumb question but I have not been able to get files to the client unless they are specified as per the following:

Endpoint("/test.js") do request::Request readstring(joinpath(dirname(@__FILE__),"test.js")) end

What I would like to do is specify the directory and have all of its files available as the client may request them. Is there something I've overlooked because I can't seem to get that working.

Websocket help

More an issue with my understanding, rather than the codebase. Trying to get a message from a julia function call that was started by a Pages Post back to the originating browser (prior to the calculation returning the body in a http response, as a form of progress bar):

I've now got the blank.html example working (in chrome, the socket didn't work in firefox 61.0.1, but that might be just me). And can see the connection in Pages.connections. I guess if I could get the POST triggered by my javascript to inform the server which client to respond to, I could use Pages.message in julia, but I'm not sure this is the best way, and I can't see a way to access the uid in javascript which I could then append to the POST.

Many thanks for any advice - Gavin

A crash from latest master branch

after update to latest master branch, a crash occurs.

julia> using Pages
WARNING: Error requiring DataFrames from PlotlyJS:
LoadError: UndefVarError: df not defined
Stacktrace:
 [1] include_from_node1(::String) at ./loading.jl:576
 [2] include(::String) at ./sysimg.jl:14
 [3] err(::PlotlyJS.##264#271, ::Module, ::String) at /usr/lib/julia0.6.2/packages/v0.6/Requires/src/require.jl:42
 [4] withpath(::PlotlyJS.##263#270, ::String) at /usr/lib/julia0.6.2/packages/v0.6/Requires/src/require.jl:32
 [5] (::PlotlyJS.##262#269)() at /usr/lib/julia0.6.2/packages/v0.6/Requires/src/require.jl:53
 [6] _collect(::Array{Function,1}, ::Base.Generator{Array{Function,1},Requires.##3#4}, ::Base.EltypeUnknown, ::Base.HasShape) at ./array.jl:488
 [7] loadmod(::Symbol) at /usr/lib/julia0.6.2/packages/v0.6/Requires/src/require.jl:20
 [8] require(::Symbol) at ./loading.jl:408
 [9] include_from_node1(::String) at ./loading.jl:576
 [10] eval(::Module, ::Any) at ./boot.jl:235
 [11] _require(::Symbol) at ./loading.jl:490
 [12] require(::Symbol) at ./loading.jl:405
 [13] eval(::Module, ::Any) at ./boot.jl:235
 [14] eval_user_input(::Any, ::Base.REPL.REPLBackend) at ./REPL.jl:66
 [15] macro expansion at ./REPL.jl:97 [inlined]
 [16] (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:73
while loading /usr/lib/julia0.6.2/packages/v0.6/PlotlyJS/src/dataframes_api.jl, in expression starting on line 522

by the last sentence, it's strongly PlotlyJS's problem.
please check out if this problem occurs only on my side.

Is the latest version of this being pulled with: Pkg.add("Pages") ?

Hello, great work on this project. It seems to be just what I need and I hope that I can eventually help supplement this project. Unfortunately, I had to be a bit determined at hacking away at this to get it working as indicated per the readme and eventually came to the realization that what you have here on github is much more complete than what I got on either of my computers (work and home) using Pkg.add("Pages") Is this due to some error on my part or what is going on here?

For some context, I am using julia v0.6.0 on Ubuntu. I was comparing the code on github and realized that the line numbers did not line up with the same code on my computer. I ended up cut-pasting the code and then re-running things after saving and everything works as expected.

Clean interruption

Pages.examples()
# click blank
Pages.randomping()

works fine, however if I interrupt it in the REPL using CTRL+C it throws the error and then it seems the server is not closed gracefully (?).

I think this can be solved by using

try while true
            sleep(1)
            e = Element(string(count),innerHTML = "Ping $(count): $(round(time()-t0,digits=2)) seconds")
            e.style["color"] = rand(["red","green","blue"])
            rand() < .5 && Pages.appendChild(e)
            count += 1
            tstart = time()
    end
catch err
    if isa(err, InterruptException)
        # close server gracefully
    else
        throw(err)
    end
end

The "close server gracefully" part I'm not sure. Maybe one way is to let Pages.start take a socket and then close that, something like

ipaddr = ip"127.0.0.1"
port = 8000
inetaddr = Sockets.InetAddr(ipaddr, port)
server = Sockets.listen(inetaddr)

Then in start have something like

HTTP.listen(ip"0.0.0.0", p, readtimeout=0, server=server) do http
# ...

and finally in the caught interruption above

# on interrupt
close(server)

?

HandlerFunction not defined

HTTP.register!(router[],method,route,HTTP.HandlerFunction(handler))

This is probably a failure in my setup, but I'm failing to get Pages.start() to work (in julia 1.0.3) when I'm bundling it up in a fresh container.

using Pages;
Pages.start();

gives UndefVarError: HandlerFunction not defined

relevant lines of pkg status are
[cd3eb016] + HTTP v0.8.0
[7c165e09] + Pages v0.2.2

Any help gratefully received - many thanks.

Support routing variables and query parameters

I can't find a way to route the call properly when query parameters are provided in the URL e.g. http://localhost:8888/hello?id=1. I expect an id parameter should be created in the Request object. Instead, the endpoint for hello isn't even called and a 404 error is returned. It appears that the whole string (hello?id=1) becomes the endpoint.

Second, it's common for REST API's to pass arguments as in the path. For example, the route may be specified as http://localhost:8888/hello/<city> and the client calls it as http://localhost:8888/hello/losangeles. In that case, a city parameter should be created and accessible to the method.

See Flask examples (http://flask.pocoo.org/docs/0.12/quickstart/#routing)

how to get "post" method data in endpoint?

hello, EricForgy!
I'm testing Pages to replace from python-flask.
In flask, I can recieve requested data both GET and POST.

I wrote code like below,
`using Pages, JSON

Pages.Endpoint("/") do request::Request
json_out = Dict()
#param = Pages.query_params(Pages.URI(request.resources))
#=if request.method == "GET"
pass
elseif request.method == "POST"
pass
end=#
#println(fieldnames(request))
println(request.method)
println(request.resource)
println(request.headers)
println(request.data)
println(request.uri)

json_out["a"] = 1

println(string(json_out))

return JSON.json(json_out)

end

Pages.Endpoint("/shutdown") do request::Request
json_out = Dict()

try
    exit()
    json_out["result"] = "success"
catch error
    json_out["result"] = string(error)
end

return JSON.json(json_out)

end

Pages.start(9000)`

I run very successful, but cannot recieve post datas.

when i post to "/" with python,
requests.post("http://localhost:9000", data = json.dumps({"dump": "a"}))

server prints,
POST
/
Dict{AbstractString,AbstractString}(Pair{AbstractString,AbstractString}("Connection", "keep-alive"),Pair{AbstractString,AbstractString}("http_major", "1"),Pair{AbstractString,AbstractString}("Content-Length", "13"),Pair{AbstractString,AbstractString}("Host", "localhost:9000"),Pair{AbstractString,AbstractString}("Accept", "/"),Pair{AbstractString,AbstractString}("http_minor", "1"),Pair{AbstractString,AbstractString}("Keep-Alive", "1"),Pair{AbstractString,AbstractString}("User-Agent", "python-requests/2.18.4"),Pair{AbstractString,AbstractString}("Accept-Encoding", "gzip, deflate"))
UInt8[0x7b, 0x22, 0x64, 0x75, 0x6d, 0x70, 0x22, 0x3a, 0x20, 0x22, 0x61, 0x22, 0x7d]
:/

so there is no data I posted, json.dumps({"dump": "a"})

is there any way to do this?

A small correction

This:
Endpoint("/hello") do request::Request
should be:
Endpoint("/hello") do request::HTTP.Request

At least for me it was needed.

And what I get with Pages.pages is really something else than what is shown in the doc.

Jussi Salmela

Error when hitting "back"

┌ Error: (ErrorException("Unexpected end of input\nLine: 0\nAround: ......\n           ^\n"), Base.StackTraces.StackFrame[error(::String) at error.jl:33, _error(::String, ::MemoryParserState) at Parser.jl:142, byteat at Parser.jl:51 [inlined], parse_value(::ParserContext{Dict{String,Any},Int64}, ::MemoryParserState) at Parser.jl:162, #parse#1(::Type, ::Type{Int64}, ::Function, ::String) at Parser.jl:414, parse at Parser.jl:412 [inlined], (::##13#16)(::WebSocket{Transaction{TCPSocket}}) at server.jl:27, #upgrade#8(::Bool, ::Function, ::##13#16, ::Stream{Request,Transaction{TCPSocket}}) at WebSockets.jl:144, upgrade at WebSockets.jl:127 [inlined], #12 at server.jl:24 [inlined], handle_stream(::##12#15, ::Stream{Request,Transaction{TCPSocket}}) at Servers.jl:484, (::##55#56{Bool,##12#15,Transaction{TCPSocket},Stream{Request,Transaction{TCPSocket}}})() at task.jl:259])
└ @ HTTP.Servers C:\Users\Eric\.julia\packages\HTTP\YjRCz\src\Servers.jl:464

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.