Dear all,
I want to do a small server using Julia. This service implies to receive POST parameters and returns a file. Because I want to include it inside my package, I have chosen HTTP.jl (instead of Genie) to reduce the dependencies.
Using HTTP, after many errors, I could send the file. The problem is how to receive the POST parameters from a HTML form using a handle.
I have check the documentation but I have not found any clue. I have try the request.headers and request.body but without any success.
function handle(req::HTTP.Request)
# Get the POST parameters?
end
Any suggestion?
Thanks in advance.
Daniel
I can’t help you directly, since I’ve done something similar for images, but with Genie:
route("/getpic", method = POST) do
#read payload
raw = filespayload()
img = ImageMagick.readblob(raw["file_name"].data)
end
Genie.startup(port,ip,async = false)
Maybe if you look inside the Genie.filespayload()
function?
Hi Daniel,
I have studied the HTTP.jl
library extensively.
You would need to do:
HTTP.Handlers.serve(server_host, server_port) do request::HTTP.Request
request_payload=String(take!(IOBuffer(request.body))))
end
request_payload
is JSON string format
As side note I recently created a lighter Julia web library (only renders JSON API and HTTP Get) doing all this for you. Might want to check Dance.jl
Cheers
2 Likes
Did you see this example from the HTTP.jl
documentation where the payload is obtained using IOBuffer(HTTP.payload(req))
. This object can then be parsed with one of the julia json readers.
Thank you for all your suggestions!
Finally, I have done:
function handle(req::HTTP.Request)
data = String(req.body)
params = Dict(split.(split(data, "&"), Ref("=")))
# Process params
end
The String(req.body) is enough when your form is simple (in my case all where input, select, and textarea), if there is a file the option suggested by @yoh-meyers is the best one. That sentence concatenate the values as: "data = “penalty_options=0.25&penalty_boolean=0&text=…”
So, the next line divide the different form values using the & and the = symbol, and create a Dictionary with the parameters. (if there is a conflictive symbol as ‘&’ or ‘=’ as the values of the variables, they are encoded).
@uwechsler thank you, but the payload function did not work for me.
Thanks again all for your ideas!
1 Like
To answer myself, I have develop a (not so) simple function to read parameters. It is not working with files, but it is working with “application/x-www-form-urlencoded” and “multipart/form-data” content-types:
function get_params(req::HTTP.Request)
data = String(req.body)
params = Dict{String,String}()
headers = filter(x->x[1] == "Content-Type", req.headers)
# Check there is content-type
if (isempty(headers))
content_type = ""
else
content_type = only(headers)[2]
end
if (content_type == "application/x-www-form-urlencoded")
pairs = split.(split(data, "&"), Ref("="))
params = Dict(name => HTTP.URIs.unescapeuri(value) for (name, value) in pairs)
elseif (startswith(content_type, "multipart/form-data"))
body = IOBuffer(data)
# First line is the stopping line
stopping_line = replace(readline(body), "-" => "")
while(!eof(body))
line = readline(body)
text_head = r"Content-Disposition: form-data; name=\"(.*)\""
m = match(text_head, line)
if !isnothing(m)
name = m.captures[1]
_ = readline(body)
line = readline(body)
value = ""
if (!occursin(stopping_line, line))
value = "$(line)"
end
while (!eof(body) && !occursin(stopping_line, line))
line = readline(body)
if (!occursin(stopping_line, line))
value *= "\n$(line)"
end
end
params[name] = value
end
end
end
return params
end
I have put the code if it could help anyone.
1 Like