Skip to content

Commit

Permalink
Prepare for 0.7 (#47)
Browse files Browse the repository at this point in the history
* mod:   .travis.yml                 Drop 0.5
mod:   README.md                   Comment, issue #43 URI field
mod:   REQUIRE                     Drop 0.5
mod:   src/HttpCommon.jl           AbstractString -> String. Constructors accepting AbstractString.

* modified:   .travis.yml     Separate depwarns from URIParser <- Compat

* modified:   test/runtests.jl      Added tests for constructing requests with Dict{AbstractString, AbstractString}
                                  Added two-step test for isa(HttpCommon.header(), Header)

* modified:   src/HttpCommon.jl     Added using Base.Dates (the 0.6 way)

* 	modified:   .travis.yml         Drop the two-step compilation again.
	modified:   REQUIRE             No way around including Compat for covering 0.6 and 0.7.
	modified:   src/HttpCommon.jl   using Compat.Dates
  • Loading branch information
hustf authored and ararslan committed Jan 20, 2018
1 parent e546dc2 commit 51c55f1
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 24 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ os:
- linux
- osx
julia:
- 0.5
- 0.6
- nightly
notifications:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ It has five fields:
* `resource`: the resource requested (e.g. "/hello/world")
* `headers`: see `Headers` above
* `data`: the data in the request as a vector of bytes
* `uri`: additional details, normally not used


#### `Cookie`
Expand Down
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
julia 0.5
julia 0.6
URIParser
Compat 0.37.0
46 changes: 26 additions & 20 deletions src/HttpCommon.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__precompile__()

module HttpCommon

using Compat.Dates
using URIParser: URI, unescape

export Headers, Request, Cookie, Response, escapeHTML, parsequerystring
Expand All @@ -15,14 +15,13 @@ include("status.jl")
"""
`Headers` represents the header fields for an HTTP request.
"""
const Headers = Dict{AbstractString, AbstractString}
const Headers = Dict{String, String}
headers() = Headers(
"Server" => "Julia/$VERSION",
"Content-Type" => "text/html; charset=utf-8",
"Content-Language" => "en",
"Date" => Dates.format(now(Dates.UTC), Dates.RFC1123Format) )


"""
A `Request` represents an HTTP request sent by a client to a server.
It has five fields:
Expand All @@ -31,16 +30,18 @@ It has five fields:
* `resource`: the resource requested (e.g. "/hello/world")
* `headers`: see `Headers` above
* `data`: the request data as a vector of bytes
* `uri`: additional details, normally not used
"""
type Request
mutable struct Request
method::String # HTTP method string (e.g. "GET")
resource::String # Resource requested (e.g. "/hello/world")
headers::Headers
data::Vector{UInt8}
uri::URI
end
Request() = Request("", "", Headers(), UInt8[], URI(""))
Request(method, resource, headers, data) = Request(method, resource, headers, data, URI(""))
Request(method, resource, headers, data) =
Request(String(method), String(resource), Headers(headers), Vector{UInt8}(data), URI(""))

Base.show(io::IO, r::Request) = print(io, "Request(", r.uri, ", ",
length(r.headers), " headers, ",
Expand All @@ -52,12 +53,12 @@ A `Cookie` represents an HTTP cookie. It has three fields:
`name` and `value` are strings, and `attrs` is dictionary
of pairs of strings.
"""
type Cookie
mutable struct Cookie
name::String
value::String
attrs::Dict{String, String}
end
Cookie(name, value) = Cookie(name, value, Dict{String, String}())
Cookie(name, value) = Cookie(String(name), String(value), Dict{String, String}())
Base.show(io::IO, c::Cookie) = print(io, "Cookie(", c.name, ", ", c.value,
", ", length(c.attrs), " attributes)")

Expand All @@ -77,7 +78,7 @@ It has six fields:
Response has many constructors - use `methods(Response)` for full list.
"""
type Response
mutable struct Response
status::Int
headers::Headers
cookies::Dict{String, Cookie}
Expand All @@ -91,16 +92,21 @@ type Response
end
# If a Response is instantiated with all of fields except for `finished`,
# `finished` will default to `false`.
const HttpData = Union{Vector{UInt8}, AbstractString}
const HttpData = Union{Vector{UInt8}, String}
Response(s::Int, h::Headers, d::HttpData) =
Response(s, h, Dict{String, Cookie}(), d, Nullable(), Response[], false, Request[])
Response(s, h, Dict{String, Cookie}(), Vector{UInt8}(d), Nullable(), Response[], false, Request[])
Response(s::Int, h::Dict{AbstractString,AbstractString}, d::HttpData) =
Response(s, Headers(h), Dict{String, Cookie}(), Vector{UInt8}(d), Nullable(), Response[], false, Request[])
Response(s::Int, h::Headers) = Response(s, h, UInt8[])
Response(s::Int, d::HttpData) = Response(s, headers(), d)
Response(d::HttpData, h::Headers) = Response(200, h, d)
Response(d::HttpData) = Response(d, headers())
Response(s::Int, h::Dict{AbstractString,AbstractString}) = Response(s, Headers(h), UInt8[])
Response(s::Int, d::HttpData) = Response(s, headers(), Vector{UInt8}(d))
Response(d::HttpData, h::Headers) = Response(200, h, Vector{UInt8}(d))
Response(d::HttpData, h::Dict{AbstractString,AbstractString}) = Response(200, Headers(h), Vector{UInt8}(d))
Response(d::HttpData) = Response(Vector{UInt8}(d), headers())
Response(s::Int) = Response(s, headers(), UInt8[])
Response() = Response(200)


function Base.show(io::IO, r::Response)
print(io, "Response(", r.status, " ", get(STATUS_CODES, r.status, "Unknown Code"), ", ",
length(r.headers)," headers, ",
Expand All @@ -109,23 +115,23 @@ end


"""
escapeHTML(i::AbstractString)
escapeHTML(i::String)
Returns a string with special HTML characters escaped: &, <, >, ", '
"""
function escapeHTML(i::AbstractString)
function escapeHTML(i::String)
# Refer to http://stackoverflow.com/a/7382028/3822752 for spec. links
o = replace(i, "&", "&amp;")
o = replace(o, "\"", "&quot;")
o = replace(o, "'", "&#39;")
o = replace(o, "<", "&lt;")
o = replace(o, ">", "&gt;")
return o
return o
end


"""
parsequerystring(query::AbstractString)
parsequerystring(query::String)
Convert a valid querystring to a Dict:
Expand All @@ -135,8 +141,8 @@ Convert a valid querystring to a Dict:
# "baz" => "<a href='http://www.hackershool.com'>hello world!</a>"
# "foo" => "bar"
"""
function parsequerystring{T<:AbstractString}(query::T)
q = Dict{AbstractString,AbstractString}()
function parsequerystring(query::T) where T<:AbstractString
q = Dict{String,String}()
length(query) == 0 && return q
for field in split(query, "&")
keyval = split(field, "=")
Expand Down
15 changes: 13 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ using HttpCommon
using Base.Test

# headers
h = HttpCommon.headers()
@test isa(h, Headers)
@test isa(HttpCommon.headers(), Headers)

# Request
@test sprint(show, Request()) == "Request(:/, 0 headers, 0 bytes in body)"
@test sprint(show, Request("GET", "/get", HttpCommon.headers(), "")) ==
Expand All @@ -14,21 +15,31 @@ using Base.Test
"Cookie(test, it, 0 attributes)"

# Response
h = HttpCommon.headers()
h_abstract = Dict{AbstractString, AbstractString}(h)
@test sprint(show, Response(200, h, "HttpCommon")) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response(200, h_abstract, "HttpCommon")) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response(200, h, UInt8[1,2,3])) ==
"Response(200 OK, 4 headers, 3 bytes in body)"
@test sprint(show, Response(200, h_abstract, UInt8[1,2,3])) ==
"Response(200 OK, 4 headers, 3 bytes in body)"
@test sprint(show, Response(200, h)) ==
"Response(200 OK, 4 headers, 0 bytes in body)"
@test sprint(show, Response(200, h_abstract)) ==
"Response(200 OK, 4 headers, 0 bytes in body)"
@test sprint(show, Response(200, "HttpCommon")) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response(200, UInt8[1,2,3])) ==
"Response(200 OK, 4 headers, 3 bytes in body)"
@test sprint(show, Response("HttpCommon", h)) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response("HttpCommon", h_abstract)) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response(UInt8[1,2,3], h)) ==
"Response(200 OK, 4 headers, 3 bytes in body)"
@test sprint(show, Response(UInt8[1,2,3], h_abstract)) ==
"Response(200 OK, 4 headers, 3 bytes in body)"
@test sprint(show, Response("HttpCommon")) ==
"Response(200 OK, 4 headers, 10 bytes in body)"
@test sprint(show, Response(UInt8[1,2,3])) ==
Expand Down

0 comments on commit 51c55f1

Please sign in to comment.