connections
A Connection is passed as a single positional argument to every Route. The Connection contains the output stream that content is to be written to, a Dict{Symbol, ServerExtension} of Server Extensions, which can be accessed by indexing the Connection with a Symbol, and a Dict{String, Function} of routes that the server references. A different type of Connection can also be provided to a ServerTemplate in order to extend capabilities, but the new AbstractConnection must follow the consistencies of that type.
Toolips.AbstractConnection — Typeabstract type AbstractConnection
Connections are passed through function routes and can have Servables written to it.
Consistencies
- routes::Dict - A {String, Function} dictionary that the server references to
direct incoming connections.
- http::Any - Usually an HTTP.Stream, however can be anything that is binded to
the Base.write method.
- extensions::Dict - A {Symbol, ServerExtension} dictionary that can be used to
access ServerExtensions.
Toolips.Connection — TypeConnection <: AbstractConnection
- routes::Dict
- http::HTTP.Stream
- extensions::Dict
The connection type is passed into route functions and pages as an argument. This is both for functions, as well as Servable.f() methods. This constructor should not be called directly. Instead, it is called by the server and passed through the function pipeline. Indexing a Connection will return the extension named with that symbol.
example
# v The Connection
home = route("/") do c::Connection
c[Logger].log(1, "We can index extensions by type or symbol")
c[:logger].log(1, "see?")
c.routes["/"] = c::Connection -> write!(c, "rerouting!")
httpstream = c.http
write!(c, "Hello world!")
myheading::Component = h("myheading", 1, text = "Whoa!")
write!(c, myheading)
endfield info
- routes::Dict - A dictionary of routes where the keys
are the routed URL and the values are the functions to those keys.
- http::HTTP.Stream - The stream for this current peer's connection.
- extensions::Dict - A dictionary of extensions to load with the
name to reference as keys and the extension as the pair.
constructors
- Connection(routes::Dict, http::HTTP.Stream, extensions::Dict)
routes
Connection constructors, aside from the SpoofConnection, which is meant to be used solely for development of extensions, should not be called directly. Instead, Connections should be passed as an argument into routes.
using Toolips
thisroute = route("/") do c::Connection
end
function thisroute(c::Connection)
endConnections also contain the routes that are provided to your ServerTemplate. We can obtain all routes by using the routes method.
Toolips.routes — MethodInterface
routes(c::Connection) -> ::Dict{String, Function}
Returns the server's routes.
example
route("/") do c::Connection
routes(c)
endThe routes can also be set, or retrieved using setindex! and getindex! with a String respectively.
using Toolips
function example(c::Connection)
write!(c, "hello world!")
end
myroute = route("/") do c::Connection
c["/helloworld"] = example
this_function = c["/"]
endBase.setindex! — MethodInterface
setindex!(c::AbstractConnection, f::Function, s::String) -> _
Sets the route path s to serve at the function f.
example
c["/"] = c -> write!(c, "hello")Base.getindex — MethodInterface
getindex(c::AbstractConnection, s::String) -> ::Function
Returns the function that corresponds to the route dir s.
example
c["/"]
homeAnother technique we could also use is the route! method.
using Toolips
function example(c::Connection)
write!(c, "hello world!")
end
myroute = route("/") do c::Connection
route!(c, "/helloworld") do c::Connection
write!(c, "hello world!")
end
endextensions
A Connection also carries some of the extensions loaded into a ServerTemplate. Note that this is not always the case, as some extensions are not loaded into the Connection to work. We can access the extensions with the extensions method.
using Toolips
myroute = route("/") do c::Connection
ourextensions = extensions(c)
endWe can also check for a Connection extension by using the has_extension method.
using Toolips
myroute = route("/") do c::Connection
if has_extension(c, Logger)
c[:Logger].log("Hello world!")
end
endExtensions can be accessed by indexing a Connection or WebServer with a Symbol. The ServerExtension's Symbol will be the type as a Symbol. We can also index with a Type directly.
Base.getindex — MethodInterface
getindex(c::AbstractConnection, s::Symbol) -> ::ServerExtension
Indexes the extensions in c.
example
route("/") do c::Connection
c[:Logger].log("hi")
endBase.getindex — MethodInterface
getindex(c::AbstractConnection, t::Type) -> ::ServerExtension
Indexes the extensions in c by type.
example
route("/") do c::Connection
c[Logger].log("hi")
endservables basics
Servables are types that can be written to a Connection. This is done via the Servable.f(::Connection) method, which essentially becomes a Route inside of a Type. The main type of Servable that comes with the toolips base is the Component. There are several methods that can be used to construct a Component, and a full list of the Components that come with toolips are available here. For the following example, I will be using the p and divider Components. These are both equivalent to writing their tags in HTML, <p> and <div>. All Components take an infinite number of key-word arguments, which are element properties in HTML.
myroute = route("/") do c::Connection
# name - vvvvv | vvvvvvvvvvvvvv - setting text
myp = p("myp", text = "Hello world!")
mydiv = divider("mydiv")
endwriting
All writing can be done via the write! method. We can write any type this way, as well as several different Vectors.
Toolips.write! — FunctionInterface
write!(c::AbstractConnection, s::Servable) -> _
Writes a Servable's return to a Connection's stream. This is usually used in a routing function or a route where ::Connection is provided as an argument.
example
serv = p("mycomp", text = "hello")
rt = route("/") do c::Connection
write!(c, serv)
endInterface
write!(c::AbstractConnection, s::Vector{Servable}) -> _
Writes all servables in s to c.
example
c = Component()
c2 = Component()
comps = components(c, c2)
Vector{Servable}(Component(), Component())
write!(c, comps)Interface
write!(c::AbstractConnection, s::Servable ...) -> _
Writes Servables as Vector{Servable}
example
write!(c, p("mycomp", text = "hello!"), p("othercomp", text = "hi!"))Interface
write!(c::AbstractConnection, s::Vector{Component}) -> _
A catch-all for when Vectors are accidentally stored as Vector{Any}.
example
write!(c, ["hello", p("mycomp", text = "hello!")])Interface
write!(c::AbstractConnection, s::Vector{Component}) -> _
A catch-all for when Vectors are accidentally stored as Vector{Component}.
example
write!(c, [p("mycomp", text = "bye")])Interface
write!(c::AbstractConnection, s::String) -> _
Writes the String into the Connection as HTML.
example
write!(c, "hello world!")Interface
write!(::AbstractConnection, ::Any) -> _
Attempts to write any type to the Connection's stream.
example
d = 50
write!(c, d)We will compose our Components from before using the push! method, and write them to our Connection using this method.
myroute = route("/") do c::Connection
# name - vvvvv | vvvvvvvvvvvvvv - setting text
myp = p("myp", text = "Hello world!")
mydiv = divider("mydiv")
push!(mydiv, myp)
write!(c, mydiv)
endWe can then load this into a ServerTemplate and use st.start() to reveal what has been created.
using Toolips
myroute = route("/") do c::Connection
myp = p("myp", text = "Hello world!")
mydiv = divider("mydiv")
push!(mydiv, myp)
write!(c, mydiv)
end
st = ServerTemplate()
st.add(myroute)
st.start()
[2022:07:02:17:46]: 🌷 toolips> Toolips Server starting on port 8000
[2022:07:02:17:46]: 🌷 toolips> Successfully started server on port 8000
[2022:07:02:17:46]: 🌷 toolips> You may visit it now at http://127.0.0.1:8000
arguments and posts
Connections also hold the arguments and post bodies for a given request. GET request arguments can be obtained via the getarg or getargs methods. getarg will index specifically for a particular Symbol, whereas getargs will return a Dict{Symbol, Any} with the values parsed as Any by ParseNotEval.
Toolips.getarg — FunctionInterface
getarg(c::AbstractConnection, s::Symbol) -> ::Any
Returns the requested argument from the target.
example
getarg(c, :x)
50Interface
getarg(c::AbstractConnection, s::Symbol, t::Type) -> ::Vector
This method is the same as getargs(::HTTP.Stream, ::Symbol), however types are parsed as type T(). Note that "Cannot convert..." errors are possible with this method.
example
getarg(c, :x, Int64)
50Toolips.getargs — FunctionInterface
getargs(c::AbstractConnection) -> ::Dict{Symbol, Any}
The getargs method returns arguments from the HTTP target (GET requests.) Returns a Dict with the argument keys as Symbols.
example
route("/") do c
args = getargs(c)
args[:message]
"welcome to toolips ! :)"
endWe can also get the POST body as a String by calling the getpost method.
Toolips.getpost — FunctionInterface
getpost(c::AbstractConnection) -> ::String
Returns the POST body of c.
example
getpost(c)
"hello, this is a post request"We can restart the reading of a POST by using the startread! method.
Toolips.startread! — MethodInterface
startread!(::AbstractConnection) -> _
Resets the seek on the Connection. This function is only meant to be used on post bodies.
example
post = getpost(c)
"hello"
post = getpost(c)
""
startread!(c)
post = getpost(c)
"hello"controlling connections
Controlling a Connection is relatively straightforward, we can navigate a Connection to a new URL using the navigate! method:
Toolips.navigate! — FunctionInterface
navigate!(::AbstractConnection, ::String) -> _
Routes a connected stream to a given URL.
example
navigate!(c, "https://github.com/ChifiSource/Toolips.jl")We can download files using the download! method.
Toolips.download! — FunctionInterface
download!(c::AbstractConnection, uri::String) -> _
Downloads a file to a given Connection's computer.
example
download!(c, "files/mytext.txt")Finally, we can get an incoming Connection's IP-Address using the getip function.
Toolips.getip — FunctionInterface
getip(c::AbstractConnection) -> ::String
Returns the IP that is connected via the connection c.
example
getip(c)
"127.0.0.2"