Skip to content

Commit

Permalink
Merge branch 'master' into bonito-connection
Browse files Browse the repository at this point in the history
  • Loading branch information
frankier committed Sep 5, 2024
2 parents 518476f + 925bdc6 commit d752683
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "Oxygen"
uuid = "df9a0d86-3283-4920-82dc-4555fc0d1d8b"
authors = ["Nathan Ortega <[email protected]>"]
repo = "https://github.com/OxygenFramework/Oxygen.jl.git"
version = "1.5.12"
version = "1.5.13"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand Down
19 changes: 15 additions & 4 deletions src/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ using Dates
using Reexport
using RelocatableFolders
using DataStructures: CircularDeque
import Base.Threads: lock
import Base.Threads: lock, nthreads

include("errors.jl"); @reexport using .Errors
include("util.jl"); @reexport using .Util
include("types.jl"); @reexport using .Types
include("constants.jl"); @reexport using .Constants
Expand Down Expand Up @@ -41,16 +42,26 @@ oxygen_title = raw"""

function serverwelcome(external_url::String, docs::Bool, metrics::Bool, parallel::Bool, docspath::String)
printstyled(oxygen_title, color=:blue, bold=true)
@info "📦 Version 1.5.12 (2024-06-18)"
@info "📦 Version 1.5.13 (2024-09-02)"
@info "✅ Started server: $external_url"
if docs
@info "📖 Documentation: $external_url$docspath"
@info "📖 Documentation: $external_url" * docspath
end
if docs && metrics
@info "📊 Metrics: $external_url$docspath/metrics"
@info "📊 Metrics: $external_url" * "$docspath/metrics"
end
if parallel
@info "🚀 Running in parallel mode with $(Threads.nthreads()) threads"
# Check if the current julia version supports interactive threadpools
if hasmethod(getfield(Threads, Symbol("@spawn")), Tuple{LineNumberNode, Module, Symbol, Expr})
# Add a warnign if the interactive threadpool is empty when running in parallel mode
if nthreads(:interactive) == 0
@warn """
🚨 Interactive threadpool is empty. This can hurt performance when running in parallel mode.
Try launching julia like \"julia --threads 3,1\" to add 1 thread to the interactive threadpool.
"""
end
end
end
end

Expand Down
15 changes: 15 additions & 0 deletions src/errors.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Errors
## In this module, we export commonly used exceptions across the package

export ValidationError

# This is used by the Extractors.jl module to signal that a validation error has occurred
struct ValidationError <: Exception
msg::String
end

function Base.showerror(io::IO, e::ValidationError)
print(io, "Validation Error: $(e.msg)")
end

end
5 changes: 3 additions & 2 deletions src/extractors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using StructTypes

using ..Util: text, json, formdata, parseparam
using ..Reflection: struct_builder, extract_struct_info
using ..Errors: ValidationError
using ..Types

export Extractor, extract, validate, extracttype, isextractor, isreqparam, isbodyparam,
Expand Down Expand Up @@ -85,14 +86,14 @@ function try_validate(param::Param{U}, instance::T) :: T where {T, U <: Extracto
# Case 1: Use global validate function - returns true if one isn't defined for this type
if !validate(instance)
impl = Base.which(validate, (T,))
throw(ArgumentError("Validation failed for $(param.name): $T \n|> $instance \n|> $impl"))
throw(ValidationError("Validation failed for $(param.name): $T \n|> $instance \n|> $impl"))
end

# Case 2: Use custom validate function from an Extractor (if defined)
if param.hasdefault && param.default isa U && !isnothing(param.default.validate)
if !param.default.validate(instance)
impl = Base.which(param.default.validate, (T,))
throw(ArgumentError("Validation failed for $(param.name): $T \n|> $instance \n|> $impl"))
throw(ValidationError("Validation failed for $(param.name): $T \n|> $instance \n|> $impl"))
end
end

Expand Down
16 changes: 12 additions & 4 deletions src/utilities/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ using HTTP
using JSON3
using Dates

using ..Errors: ValidationError

export countargs, recursive_merge, parseparam,
queryparams, redirect, handlerequest,
format_response!, set_content_size!, format_sse_message


### Request helper functions ###

"""
Expand All @@ -19,7 +20,6 @@ function queryparams(req::HTTP.Request) :: Dict
return HTTP.queryparams(uri.query)
end


"""
redirect(path::String; code = 308)
Expand All @@ -29,6 +29,14 @@ function redirect(path::String; code = 307) :: HTTP.Response
return HTTP.Response(code, ["Location" => path])
end

function handle_error(::ValidationError)
return json(("message" => "400: Bad Request"), status = 400)
end

function handle_error(::Any)
return json(("message" => "500: Internal Server Error"), status = 500)
end

function handlerequest(getresponse::Function, catch_errors::Bool; show_errors::Bool = true)
if !catch_errors
return getresponse()
Expand All @@ -37,9 +45,9 @@ function handlerequest(getresponse::Function, catch_errors::Bool; show_errors::B
return getresponse()
catch error
if show_errors && !isa(error, InterruptException)
@error "ERROR: " exception=(error, catch_backtrace())
@error "ERROR: " exception=(error, catch_backtrace())
end
return json(("message" => "The Server encountered a problem"), status = 500)
return handle_error(error)
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions test/extractortests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ end
# Test that negative age trips the global validator
req = HTTP.Request("GET", "/", [], """name=joe&age=-4""")
param = Param(:form, Form{Person}, missing, false)
@test_throws ArgumentError extract(param, LazyRequest(request=req))
@test_throws Oxygen.Core.Errors.ValidationError extract(param, LazyRequest(request=req))


# Test that age < 25 trips the local validator
req = HTTP.Request("GET", "/", [], """name=joe&age=10""")
default_value = Form{Person}(x -> x.age > 25)
param = Param(:form, Form{Person}, default_value, true)
@test_throws ArgumentError extract(param, LazyRequest(request=req))
@test_throws Oxygen.Core.Errors.ValidationError extract(param, LazyRequest(request=req))
end


Expand Down Expand Up @@ -253,7 +253,7 @@ end
@suppress_err begin
# should fail since we are missing query params
r = internalrequest(HTTP.Request("GET", "/headers", ["limit" => "3"], ""))
@test r.status == 500
@test r.status == 400
end

@suppress_err begin
Expand All @@ -265,7 +265,7 @@ end
"value": 12.0
}
"""))
@test r.status == 500
@test r.status == 400
end

r = internalrequest(HTTP.Request("POST", "/json", [], """
Expand Down

0 comments on commit d752683

Please sign in to comment.