Julia build and parse URL query strings

Julia
escape_uri(s) = replace(string(s), r"[^A-Za-z0-9_.~-]" => m -> join(["%" * uppercase(string(b, base=16, pad=2)) for b in codeunits(m)]))
unescape_uri(s) = replace(replace(string(s), '+' => ' '), r"%([0-9A-Fa-f]{2})" => m -> string(Char(parse(UInt8, m[2:3]; base=16))))
build_query(d) = join(["$(escape_uri(k))=$(escape_uri(v))" for (k, v) in d], "&")

function parse_query(q)
    out = Dict{String,Vector{String}}()
    for pair in split(lstrip(q, '?'), '&')
        isempty(pair) && continue
        parts = split(pair, '='; limit=2)
        push!(get!(out, unescape_uri(parts[1]), String[]), length(parts) == 2 ? unescape_uri(parts[2]) : "")
    end
    return out
end

q = build_query(Dict("q" => "julia lang", "page" => 2))
println(q, " -> ", parse_query(q))