Skip to content

Commit

Permalink
added Conn port, Logger.hide
Browse files Browse the repository at this point in the history
  • Loading branch information
wookay committed Oct 20, 2016
1 parent aef5d99 commit 87f82f2
Show file tree
Hide file tree
Showing 13 changed files with 68 additions and 46 deletions.
8 changes: 7 additions & 1 deletion examples/cafe.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Cafe

importall Bukdu
importall Bukdu.Octo
importall Tag
importall Bukdu.Tag

type CafeController <: ApplicationController
conn::Conn
Expand Down Expand Up @@ -108,7 +110,11 @@ end

Bukdu.start(8080)

Logger.hide(Plug.StaticController)

(Endpoint)("/")
Base.JLOptions().isinteractive==0 && wait()

# Bukdu.stop()

end # module Cafe
11 changes: 6 additions & 5 deletions src/controller/conn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ end
type Conn
## Request fields
host::String
port::Int
method::Symbol
path::String
req_headers::Assoc
Expand Down Expand Up @@ -61,11 +62,11 @@ type Conn

function Conn(code::Int, resp_headers::Dict{String,String}, resp_body::Any, params::Assoc, query_params::Assoc, private::Assoc, assigns::Assoc)
new(
"", :get, "", Assoc(), :http, # host, method, path, req_headers, scheme,
Vector{Cookie}(), query_params, params, # req_cookies, query_params, params,
"", 0, :get, "", Assoc(), :http, # host, port, method, path, req_headers, scheme,
Vector{Cookie}(), query_params, params, # req_cookies, query_params, params,
resp_body, "utf-8", Vector{Cookie}(), resp_headers, code, identity, # resp_body, resp_charset, resp_cookies, resp_headers, status, before_send,
assigns, false, :unset, # assigns, halted, state,
private # private
assigns, false, :unset, # assigns, halted, state,
private # private
)
end
end
Expand All @@ -76,7 +77,7 @@ immutable MissingConnError <: ApplicationError
end


## Request fields - host, method, path, req_headers, scheme
## Request fields - host, port, method, path, req_headers, scheme

function get_req_header(conn::Conn, key::String)
k = Symbol(key)
Expand Down
13 changes: 12 additions & 1 deletion src/logger.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ settings = Dict(
:have_datetime => false,
:info_prefix => "INFO",
:info_sub => "",
:path_padding => 39
:path_padding => 39,
:hide => []
)

fatal(block::Function) = settings[:level] >= level_fatal && fatal(block())
Expand All @@ -40,6 +41,12 @@ warn(block::Function) = settings[:level] >= level_warn && warn(block())
info(block::Function) = settings[:level] >= level_info && info(block())
debug(block::Function) = settings[:level] >= level_debug && debug(block())

fatal(block::Function, condition::Function) = settings[:level] >= level_fatal && condition() && fatal(block())
error(block::Function, condition::Function) = settings[:level] >= level_error && condition() && error(block())
warn(block::Function, condition::Function) = settings[:level] >= level_warn && condition() && warn(block())
info(block::Function, condition::Function) = settings[:level] >= level_info && condition() && info(block())
debug(block::Function, condition::Function) = settings[:level] >= level_debug && condition() && debug(block())

fatal(args...; kw...) = settings[:level] >= level_fatal && print_log(:magenta, "FATAL", "", args...; kw...)
error(args...; kw...) = settings[:level] >= level_error && print_log(:red, "ERROR", "", args...; kw...)
warn(args...; kw...) = settings[:level] >= level_warn && print_log(:gray, "WARN ", "", args...; kw...)
Expand Down Expand Up @@ -68,6 +75,10 @@ function set_level(lvl::Union{Symbol,Bool}) # throw ArgumentError
end
end

function hide(T::Type)
push!(settings[:hide], T)
end

function inner_stackframes(stackframes::Vector{StackFrame}, with_color::Function)
pat = r"(.* at )(?P<file>.*.jl):(?P<lineno>\d*)"
string('\n', join(map(stackframes) do frame
Expand Down
1 change: 1 addition & 0 deletions src/plug.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ end
module Plug

import ..plug
import ..Logger

include("plug/static.jl")
include("plug/upload.jl")
Expand Down
20 changes: 10 additions & 10 deletions src/plug/csrf_protection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ end

const unprotected_methods = [:head, :get, :options]

function cookie_key(conn::Conn)::String
string(bukdu_cookie_key, '_', conn.port)
end

function check_csrf_token(conn::Conn)::Bool # throw InvalidCSRFTokenError
conn.method in unprotected_methods && return false
if haskey(conn.query_params, :_csrf_token)
token = conn.query_params[:_csrf_token]
cookie = get_req_cookie(conn, bukdu_cookie_key)
cookie = get_req_cookie(conn, cookie_key(conn))
if isa(cookie, Cookie)
cipher_text = hex2bytes(cookie.value)
try
plain = String(decrypt(CIPHER_AES, bukdu_secret_key, cipher_text))
if token == plain
return true
end
token == plain && return true
catch ex
if !isa(ex, MbedException)
throw(ex)
end
!isa(ex, MbedException) && throw(ex)
end
end
end
Expand All @@ -55,13 +55,13 @@ function generate_token()::Tuple{String,String}
(token, cipher_text)
end

function get_csrf_token(conn::Conn)::Tuple{String,String}
function get_csrf_token()::Tuple{String,String}
(token, cipher_text) = generate_token()
end

function csrf_token(conn::Conn)
(token, cipher_text) = get_csrf_token(conn)
cookie = Cookie(bukdu_cookie_key, cipher_text, Dict{String,String}(
(token, cipher_text) = get_csrf_token()
cookie = Cookie(cookie_key(conn), cipher_text, Dict{String,String}(
"expires" => Dates.format(Dates.now() + Dates.Hour(1), Dates.RFC1123Format)
))
put_resp_cookie(conn, cookie)
Expand Down
9 changes: 2 additions & 7 deletions src/plug/logger.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# module Bukdu.Plug

import ..Bukdu

immutable Logger
end

"""
plug `Plug.Logger` to write the event logs.
Expand All @@ -14,9 +9,9 @@ Endpoint() do
end
```
"""
function plug(::Type{Plug.Logger}; kw...)
function plug(::Type{Val{:Logger}}; kw...)
# level::Union{Symbol,Bool}
opts = Dict(kw)
level = haskey(opts, :level) ? opts[:level] : :debug
Bukdu.Logger.set_level(level)
Logger.set_level(level)
end
2 changes: 1 addition & 1 deletion src/router.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function (::Type{AR}){AR<:ApplicationRouter}(verb::Function, path::String, heade
conn = Conn()
routes = haskey(Routing.router_routes, AR) ? Routing.router_routes[AR] : Vector{Route}()
param_data = Assoc([(k, escape(v)) for (k,v) in kw])
Routing.request(conn, Nullable{Type{Endpoint}}(), routes, Base.function_name(verb), path, headers, cookies, param_data) do route
Routing.route_request(conn, Nullable{Type{Endpoint}}(), routes, Base.function_name(verb), path, headers, cookies, param_data) do route
Base.function_name(route.verb) == Base.function_name(verb)
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/router/endpoint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function (::Type{AE}){AE<:ApplicationEndpoint}(path::String, headers=Assoc(), co
conn = Conn()
routes = haskey(Routing.endpoint_routes, AE) ? Routing.endpoint_routes[AE] : Vector{Route}()
param_data = Assoc([(k, escape(v)) for (k,v) in kw])
Routing.request(conn, Nullable{Type{AE}}(AE), routes, :get, path, headers, cookies, param_data) do route
Routing.route_request(conn, Nullable{Type{AE}}(AE), routes, :get, path, headers, cookies, param_data) do route
true
end
end
6 changes: 3 additions & 3 deletions src/router/routing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function error_route(verb::Symbol, path::String, ex, callstack)
callstack)
end

function request{AE<:ApplicationEndpoint}(compare::Function, conn::Conn, endpoint::Nullable{Type{AE}}, routes::Vector{Route}, verb::Symbol, path::String, headers::Assoc, cookies::Vector{Cookie}, param_data::Assoc)::Conn # throw NoRouteError
function route_request{AE<:ApplicationEndpoint}(compare::Function, conn::Conn, endpoint::Nullable{Type{AE}}, routes::Vector{Route}, verb::Symbol, path::String, headers::Assoc, cookies::Vector{Cookie}, param_data::Assoc)::Conn # throw NoRouteError
uri = URI(path)
reqsegs = split(uri.path, SLASH)
length_reqsegs = length(reqsegs)
Expand Down Expand Up @@ -140,7 +140,7 @@ function request{AE<:ApplicationEndpoint}(compare::Function, conn::Conn, endpoin
if !isempty(param_data)
merge!(query_params, param_data)
end
## Request fields - host, method, path, req_headers, scheme
## Request fields - host, port, method, path, req_headers, scheme
conn.host = uri.host
conn.method = verb
conn.path = path
Expand Down Expand Up @@ -172,7 +172,7 @@ function request{AE<:ApplicationEndpoint}(compare::Function, conn::Conn, endpoin
applicable(before, controller) && before(controller)
result = nothing
try
Logger.debug() do
Logger.debug(() -> !in(C, Logger.settings[:hide])) do
debug_route(route, verb, path, C)
end
result = route.action(controller)
Expand Down
25 changes: 16 additions & 9 deletions src/server.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ include("server/handler.jl")
module Farm

import HttpServer
servers = Dict{Type,Vector{Tuple{HttpServer.Server,Task}}}()
servers = Dict{Type,Vector{HttpServer.Server}}()

end # module Bukdu.Farm

Expand Down Expand Up @@ -79,13 +79,17 @@ else
end

function start_server{AE<:ApplicationEndpoint}(::Type{AE}, port::Int, host=getaddrinfo("localhost"); any_port=false, kw...)::Int
handler = (req::Request, res::Response) -> Server.handler(AE, req, res)
server = HttpServer.Server(handler)
function listening(addr)
addr_port = Logger.with_color(:bold, addr)
Logger.info("Listening on $addr_port..."; LF=!isdefined(:Juno))
end
server.http.events["listen"] = listening
function http_server(port::Int)::HttpServer.Server
handler = (req::Request, res::Response) -> Server.handler(AE, port, req, res)
server = HttpServer.Server(handler)
server.http.events["listen"] = listening
server
end
local server = nothing
tc = Condition()
task = @async begin
if any_port
Expand All @@ -95,6 +99,7 @@ function start_server{AE<:ApplicationEndpoint}(::Type{AE}, port::Int, host=getad
if bind(sock, addr) && trylisten(sock) == 0
close(sock)
port = Int(addr.port)
server = http_server(port)
notify(tc)
HttpServer.run(server, host=host, port=port; kw...)
break
Expand All @@ -104,15 +109,17 @@ function start_server{AE<:ApplicationEndpoint}(::Type{AE}, port::Int, host=getad
end
end
else
server = http_server(port)
notify(tc)
HttpServer.run(server, host=host, port=port; kw...)
end
end
any_port && wait(tc)
wait(tc)
if task.state in [:queued, :runnable]
if !haskey(Farm.servers, AE)
Farm.servers[AE] = Vector{Tuple{HttpServer.Server,Task}}()
Farm.servers[AE] = Vector{HttpServer.Server}()
end
push!(Farm.servers[AE], (server, task))
push!(Farm.servers[AE], server)
end
port
end
Expand All @@ -130,13 +137,13 @@ end
function stop{AE<:ApplicationEndpoint}(::Type{AE})::Void
if haskey(Farm.servers, AE)
stopped = 0
for (server, task) in Farm.servers[AE]
for server in Farm.servers[AE]
try
if Base.StatusActive == server.http.sock.status
stopped += 1
close(server)
end
catch e
catch ex
end
end
if stopped >= 1
Expand Down
5 changes: 3 additions & 2 deletions src/server/handler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ include("form_data.jl")
const commit_short = string(LibGit2.revparseid(LibGit2.GitRepo(Pkg.dir("Bukdu")), "HEAD"))[1:7]
const info = "Bukdu (commit $commit_short) with Julia $VERSION"

function handler{AE<:ApplicationEndpoint}(::Type{AE}, req::Request, res::Response)::Response
function handler{AE<:ApplicationEndpoint}(::Type{AE}, port::Int, req::Request, res::Response)::Response
if AE==Endpoint && !haskey(Routing.endpoint_routes, AE)
Endpoint() do
plug(Router)
end
end
local conn = Conn()
conn.port = port
routes = Routing.endpoint_routes[AE]
applicable(before, req, res) && before(req, res)
method = Symbol(lowercase(req.method))
Expand All @@ -50,7 +51,7 @@ function handler{AE<:ApplicationEndpoint}(::Type{AE}, req::Request, res::Respons
end
req_data = req_data_by_content_encoding(req)::Vector{UInt8}
param_data = :post==method ? form_data_for_post(req.headers, req_data) : Assoc()
conn = Routing.request(compare, conn, Nullable{Type{AE}}(AE), routes, method, path, headers, cookies, param_data)
conn = Routing.route_request(compare, conn, Nullable{Type{AE}}(AE), routes, method, path, headers, cookies, param_data)
catch ex
stackframes = stacktrace(catch_backtrace())
conn = conn_error(method, req.resource, ex, stackframes)
Expand Down
4 changes: 2 additions & 2 deletions test/renderers/json.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ conn = (Router)(get, "/api/users")
req = Request()
req.method = "GET"
req.resource = "/api/users"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 200 == res.status
@test "application/json" == res.headers["Content-Type"]
@test """\"hello\"""" == String(res.data)
Expand Down Expand Up @@ -55,7 +55,7 @@ end
empty!(logs)
req.method = "GET"
req.resource = "/api/users/1"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 200 == res.status
@test "application/json" == res.headers["Content-Type"]
@test "[\"hello\"]" == String(res.data)
Expand Down
8 changes: 4 additions & 4 deletions test/server.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@ req = Request()

req.method = "GET"
req.resource = "/"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 200 == res.status
@test "hello world" == String(res.data)

req.method = "GET"
req.resource = "/pi"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 200 == res.status
@test "π = 3.1415926535897..." == String(res.data)

req.method = "POST"
req.resource = "/"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 404 == res.status

req.method = "GET"
req.resource = "/test"
res = Bukdu.Server.handler(Endpoint, req, Response())
res = Bukdu.Server.handler(Endpoint, 0, req, Response())
@test 404 == res.status


Expand Down

0 comments on commit 87f82f2

Please sign in to comment.