Skip to content

Commit 5456b58

Browse files
authored
Merge pull request #67 from JuliaWeb/depwarn
Updates for Julia 0.7, and moving to HTTP.jl
2 parents 8d51830 + 9c204b4 commit 5456b58

19 files changed

+307
-256
lines changed

README.md

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,3 @@ function auth_preproc(req::Request, res::Response)
7979
end
8080
run_http(apiclnt, 8888, auth_preproc)
8181
````
82-
83-
84-
## JuliaBox Deployment
85-
86-
Deploying on JuliaBox takes care of most of the boilerplate code. To expose a simple fibonacci generator on JuliaBox, paste the following
87-
code as the API command:
88-
````
89-
fib(n::AbstractString) = fib(parse(Int, n));
90-
fib(n::Int) = (n < 2) ? n : (fib(n-1) + fib(n-2));
91-
process([(fib, false)]);
92-
````
93-
94-
Notice that we need to specify a lot less detail on JuliaBox. JuliaBox connects the API servers to a queue, instead of the server having to listen
95-
for requests. The obvious packages are aleady imported.
96-
97-
The JuliaBox API command must however be concisely expressed within 512 bytes without new lines. To run larger applications, simply package up the
98-
code as a Julia package and install the package as part of the command. For an example, see the [Juliaset API package](https://github.com/tanmaykm/Juliaset.jl).
99-
100-
Note: A [JuliaBox](https://github.com/JuliaCloud/JuliaBox) deployment may or may not have this enabled, depending on how it has been configured.

REQUIRE

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ julia 0.6
22
ZMQ 0.3.3
33
JSON
44
Logging 0.3.1
5-
HttpCommon
6-
HttpServer 0.0.12
7-
Compat 0.17.0
5+
Compat 0.70.0
6+
HTTP 0.6.12

examples/filedownload/srvr.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using JuliaWebAPI
22
using Compat
3+
using Compat.Base64
34
using Logging
45
using GZip
56

@@ -8,7 +9,7 @@ const FILE_DOWNLOAD_HDR = Dict{String,String}("Content-Type" => "application/oct
89

910
function filebytes(filename)
1011
open(filename, "r") do fp
11-
buff = Array(UInt8, filesize(filename))
12+
buff = Array{UInt8}(filesize(filename))
1213
return read!(fp, buff)
1314
end
1415
end
@@ -52,7 +53,7 @@ function listfiles()
5253
println(iob, "<li><a href=\"/servefile/$fname\">$fname</a> | <a href=\"/servefile/$fname?zipped=true\">zipped</a></li>")
5354
end
5455
println(iob, "</ul></body></html>")
55-
takebuf_string(iob)
56+
String(take!(iob))
5657
end
5758

5859
function savefile(; upfile=nothing, filename=nothing)
@@ -75,4 +76,4 @@ const REGISTERED_APIS = [
7576
(savefile, false),
7677
]
7778

78-
process(REGISTERED_APIS, "tcp://127.0.0.1:9999"; bind=true, log_level=INFO)
79+
process(JuliaWebAPI.create_responder(REGISTERED_APIS, "tcp://127.0.0.1:9999", true, ""))

src/APIInvoker.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
APIInvoker holds the transport and format used for a remote api call.
33
"""
4-
immutable APIInvoker{T<:AbstractTransport,F<:AbstractMsgFormat}
4+
struct APIInvoker{T<:AbstractTransport,F<:AbstractMsgFormat}
55
transport::T
66
format::F
77
end
@@ -18,7 +18,7 @@ APIInvoker(ip::IPv4, port::Int, ctx::Context=Context()) = APIInvoker(ZMQTranspor
1818
Calls a remote api `cmd` with `args...` and `data...`.
1919
The response is formatted as specified by the formatter specified in `conn`.
2020
"""
21-
function apicall{T<:AbstractTransport,F<:AbstractMsgFormat}(conn::APIInvoker{T,F}, cmd, args...; data...)
21+
function apicall(conn::APIInvoker{T,F}, cmd, args...; data...) where {T<:AbstractTransport, F<:AbstractMsgFormat}
2222
req = wireformat(conn.format, String(cmd), args...; data...)
2323
resp = sendrecv(conn.transport, req)
2424
juliaformat(conn.format, resp)

src/APIResponder.jl

Lines changed: 52 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
@compat abstract type AbstractAPIResponder end
1+
abstract type AbstractAPIResponder end
22

3-
immutable APISpec
3+
struct APISpec
44
fn::Function
55
resp_json::Bool
66
resp_headers::Dict{String,String}
@@ -11,15 +11,15 @@ const EndPts = Dict{String,APISpec}
1111
"""
1212
APIResponder holds the transport and format used for data exchange and the endpoint specifications.
1313
"""
14-
immutable APIResponder{T<:AbstractTransport,F<:AbstractMsgFormat}
14+
struct APIResponder{T<:AbstractTransport,F<:AbstractMsgFormat}
1515
transport::T
1616
format::F
17-
id::Union{Void,String} # optional responder id to be sent back
17+
id::Union{Nothing,String} # optional responder id to be sent back
1818
open::Bool #whether the responder will process all functions, or only registered ones
1919
endpoints::EndPts
2020
end
2121

22-
APIResponder{T<:AbstractTransport,F<:AbstractMsgFormat}(transport::T, format::F, id::Union{Void,String}=nothing, open::Bool=false) = APIResponder(transport, format, id, open, EndPts())
22+
APIResponder(transport::T, format::F, id::Union{Nothing,String}=nothing, open::Bool=false) where {T<:AbstractTransport,F<:AbstractMsgFormat} = APIResponder(transport, format, id, open, EndPts())
2323

2424
"""
2525
APIResponder holds the transport and format used for data exchange and the endpoint specifications.
@@ -31,7 +31,7 @@ APIResponder(ip::IPv4, port::Int, ctx::Context=Context()) = APIResponder("tcp://
3131

3232
function Base.show(io::IO, x::APIResponder)
3333
println(io, "JuliaWebAPI.APIResponder with endpoints:")
34-
Base.show_comma_array(STDOUT, keys(x.endpoints), "","")
34+
Base.show_comma_array(io, keys(x.endpoints), "","")
3535
end
3636

3737
function default_endpoint(f::Function)
@@ -50,7 +50,11 @@ TODO: validate method belongs to module?
5050
function register(conn::APIResponder, f::Function;
5151
resp_json::Bool=false,
5252
resp_headers::Dict=Dict{String,String}(), endpt=default_endpoint(f))
53-
Logging.debug("registering endpoint [$endpt]")
53+
@static if isdefined(Base, Symbol("@debug"))
54+
@debug("registering", endpt)
55+
else
56+
Logging.debug("registering endpoint [$endpt]")
57+
end
5458
conn.endpoints[endpt] = APISpec(f, resp_json, resp_headers)
5559
return conn # make fluent api possible
5660
end
@@ -61,17 +65,18 @@ function respond(conn::APIResponder, code::Int, headers::Dict, resp)
6165
sendresp(conn.transport, resp)
6266
end
6367

64-
respond(conn::APIResponder, api::Nullable{APISpec}, status::Symbol, resp=nothing) =
68+
respond(conn::APIResponder, api::Union{Nothing,APISpec}, status::Symbol, resp=nothing) =
6569
respond(conn, ERR_CODES[status][1], get_hdrs(api), get_resp(api, status, resp))
6670

67-
get_hdrs(api::Nullable{APISpec}) = !isnull(api) ? get(api).resp_headers : Dict{String,String}()
71+
get_hdrs(api::Nothing) = Dict{String,String}()
72+
get_hdrs(api::APISpec) = api.resp_headers
6873

69-
function get_resp(api::Nullable{APISpec}, status::Symbol, resp=nothing)
74+
function get_resp(api::Union{Nothing,APISpec}, status::Symbol, resp=nothing)
7075
st = ERR_CODES[status]
7176
stcode = st[2]
72-
stresp = ((stcode != 0) && (resp === nothing)) ? "$(st[3]) : $(st[2])" : resp
77+
stresp = ((stcode != 0) && (resp === nothing)) ? string(st[3], " : ", st[2]) : resp
7378

74-
if !isnull(api) && get(api).resp_json
79+
if (api !== nothing) && api.resp_json
7580
return Dict{String, Any}("code"=>stcode, "data"=>stresp)
7681
else
7782
return stresp
@@ -95,10 +100,10 @@ function call_api(api::APISpec, conn::APIResponder, args, data::Dict{Symbol,Any}
95100
narrow_args!(args)
96101
end
97102
result = dynamic_invoke(conn, api.fn, args...; data...)
98-
respond(conn, Nullable(api), :success, result)
103+
respond(conn, api, :success, result)
99104
catch ex
100105
logerr("api_exception: ", ex)
101-
respond(conn, Nullable(api), :api_exception, string(ex))
106+
respond(conn, api, :api_exception, string(ex))
102107
end
103108
end
104109

@@ -130,30 +135,46 @@ end
130135
"""start processing as a server"""
131136
function process(conn::APIResponder; async::Bool=false)
132137
if async
133-
Logging.debug("processing async...")
138+
@static if isdefined(Base, Symbol("@debug"))
139+
@debug("processing async...")
140+
else
141+
Logging.debug("processing async...")
142+
end
134143
@async process(conn)
135144
else
136-
Logging.debug("processing...")
145+
@static if isdefined(Base, Symbol("@debug"))
146+
@debug("processing...")
147+
else
148+
Logging.debug("processing...")
149+
end
137150
while true
138151
msg = juliaformat(conn.format, recvreq(conn.transport))
139152

140153
command = cmd(conn.format, msg)
141-
Logging.info("received request: ", command)
154+
@static if isdefined(Base, Symbol("@info"))
155+
@info("received", command)
156+
else
157+
Logging.info("received request: ", command)
158+
end
142159

143160
if startswith(command, ':') # is a control command
144161
ctrlcmd = Symbol(command[2:end])
145162
if ctrlcmd === :terminate
146-
respond(conn, Nullable{APISpec}(), :terminate, "")
163+
respond(conn, nothing, :terminate, "")
147164
break
148165
else
149-
err("invalid control command ", command)
166+
@static if isdefined(Base, Symbol("@error"))
167+
@error("invalid control command ", command)
168+
else
169+
err("invalid control command ", command)
170+
end
150171
continue
151172
end
152173
end
153174

154175
if !haskey(conn.endpoints, command)
155176
if !conn.open || !isdefined(Main, Symbol(command))
156-
respond(conn, Nullable{APISpec}(), :invalid_api)
177+
respond(conn, nothing, :invalid_api)
157178
continue
158179
else
159180
_add_spec(getfield(Main, Symbol(command)), conn)
@@ -164,35 +185,19 @@ function process(conn::APIResponder; async::Bool=false)
164185
call_api(conn.endpoints[command], conn, args(conn.format, msg), data(conn.format, msg))
165186
catch ex
166187
logerr("exception ", ex)
167-
respond(conn, Nullable(conn.endpoints[command]), :invalid_data)
188+
respond(conn, conn.endpoints[command], :invalid_data)
168189
end
169190
end
170191
close(conn.transport)
171-
Logging.info("stopped processing.")
192+
@static if isdefined(Base, Symbol("@info"))
193+
@info("stopped processing.")
194+
else
195+
Logging.info("stopped processing.")
196+
end
172197
end
173198
conn
174199
end
175200

176-
function setup_logging(;log_level=INFO, nid::String=get(ENV,"JBAPI_CID",""))
177-
api_name = get(ENV,"JBAPI_NAME", "noname")
178-
logfile = "apisrvr_$(api_name)_$(nid).log"
179-
Logging.configure(level=log_level, filename=logfile)
180-
end
181-
182-
function process_async(apispecs::Array, addr::String=get(ENV,"JBAPI_QUEUE",""); log_level=INFO, bind::Bool=false, nid::String=get(ENV,"JBAPI_CID",""), open::Bool=false)
183-
Base.depwarn("processs_async is deprecated, use process(conn::APIResponder; async::Bool=true) instead", :process)
184-
process(apispecs, addr; log_level=log_level, bind=bind, nid=nid, open=open, async=true)
185-
end
186-
187-
function process(apispecs::Array, addr::String=get(ENV,"JBAPI_QUEUE",""); log_level=Logging.LogLevel(get(ENV, "JBAPI_LOGLEVEL", "INFO")),
188-
bind::Bool=false, nid::String=get(ENV,"JBAPI_CID",""), open::Bool=false, async::Bool=false)
189-
Base.depwarn("processs(apispecs::Array,...) is deprecated, use process(conn::APIResponder; async::Bool=false) instead", :process)
190-
setup_logging(;log_level=log_level)
191-
Logging.debug("queue is at $addr")
192-
api = create_responder(apispecs, addr, bind, nid, open)
193-
process(api; async=async)
194-
end
195-
196201
_add_spec(fn::Function, api::APIResponder) = register(api, fn, resp_json=false, resp_headers=Dict{String,String}())
197202

198203
function _add_spec(spec::Tuple, api::APIResponder)
@@ -211,26 +216,13 @@ function create_responder(apispecs::Array, addr, bind, nid, open=false)
211216
api
212217
end
213218

214-
function process()
215-
Base.depwarn("process() is deprecated, use process(conn::APIResponder; async::Bool=false) instead", :process)
216-
log_level = Logging.LogLevel(get(ENV, "JBAPI_LOGLEVEL", "INFO"))
217-
setup_logging(;log_level=log_level)
218-
219-
Logging.info("Reading api server configuration from environment...")
220-
Logging.info("JBAPI_NAME=" * get(ENV,"JBAPI_NAME",""))
221-
Logging.info("JBAPI_QUEUE=" * get(ENV,"JBAPI_QUEUE",""))
222-
Logging.info("JBAPI_CMD=" * get(ENV,"JBAPI_CMD",""))
223-
Logging.info("JBAPI_CID=" * get(ENV,"JBAPI_CID",""))
224-
Logging.info("JBAPI_LOGLEVEL=" * get(ENV,"JBAPI_LOGLEVEL","") * " as " * string(log_level))
225-
226-
cmd = get(ENV,"JBAPI_CMD","")
227-
eval(parse(cmd))
228-
nothing
229-
end
230-
231219
function logerr(msg, ex)
232220
iob = IOBuffer()
233221
write(iob, msg)
234222
showerror(iob, ex)
235-
err(String(take!(iob)))
223+
@static if isdefined(Base, Symbol("@error"))
224+
@error(String(take!(iob)))
225+
else
226+
err(String(take!(iob)))
227+
end
236228
end

src/JuliaWebAPI.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ module JuliaWebAPI
55
using ZMQ
66
using JSON
77
using Logging
8-
using HttpCommon
9-
using HttpServer
8+
using HTTP
109
using Compat
10+
using Compat.Base64
11+
using Compat.Sockets
12+
using Compat.Serialization
1113

1214
import Base: close
1315

0 commit comments

Comments
 (0)