-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Use HTTP.jl * Support SSLContext * Get tests to pass * Fix chat example * examples/server.jl is working. * Restrict tests to Julia v0.6 (v0.5 no longer supported). * Almost done. Last test is nearly passing...
- Loading branch information
Showing
16 changed files
with
598 additions
and
551 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ os: | |
- linux | ||
- osx | ||
julia: | ||
- 0.5 | ||
- 0.6 | ||
sudo: false | ||
notifications: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
info("Loading HTTP methods...") | ||
|
||
function open(f::Function, url; binary=false, verbose=false, kw...) | ||
|
||
key = base64encode(rand(UInt8, 16)) | ||
|
||
headers = [ | ||
"Upgrade" => "websocket", | ||
"Connection" => "Upgrade", | ||
"Sec-WebSocket-Key" => key, | ||
"Sec-WebSocket-Version" => "13" | ||
] | ||
|
||
HTTP.open("GET", url, headers; | ||
reuse_limit=0, verbose=verbose ? 2 : 0, kw...) do http | ||
|
||
HTTP.startread(http) | ||
|
||
status = http.message.status | ||
if status != 101 | ||
return | ||
end | ||
|
||
check_upgrade(http) | ||
|
||
if HTTP.header(http, "Sec-WebSocket-Accept") != generate_websocket_key(key) | ||
throw(WebSocketError(0, "Invalid Sec-WebSocket-Accept\n" * | ||
"$(http.message)")) | ||
end | ||
|
||
io = HTTP.ConnectionPool.getrawstream(http) | ||
f(WebSocket(io,false)) | ||
end | ||
end | ||
|
||
function upgrade(f::Function, http::HTTP.Stream; binary=false) | ||
|
||
check_upgrade(http) | ||
if !HTTP.hasheader(http, "Sec-WebSocket-Version", "13") | ||
throw(WebSocketError(0, "Expected \"Sec-WebSocket-Version: 13\"!\n$(http.message)")) | ||
end | ||
|
||
HTTP.setstatus(http, 101) | ||
HTTP.setheader(http, "Upgrade" => "websocket") | ||
HTTP.setheader(http, "Connection" => "Upgrade") | ||
key = HTTP.header(http, "Sec-WebSocket-Key") | ||
HTTP.setheader(http, "Sec-WebSocket-Accept" => generate_websocket_key(key)) | ||
|
||
HTTP.startwrite(http) | ||
|
||
io = HTTP.ConnectionPool.getrawstream(http) | ||
f(WebSocket(io, true)) | ||
end | ||
|
||
function check_upgrade(http) | ||
if !HTTP.hasheader(http, "Upgrade", "websocket") | ||
throw(WebSocketError(0, "Expected \"Upgrade: websocket\"!\n$(http.message)")) | ||
end | ||
|
||
if !HTTP.hasheader(http, "Connection", "upgrade") | ||
throw(WebSocketError(0, "Expected \"Connection: upgrade\"!\n$(http.message)")) | ||
end | ||
end | ||
|
||
function is_upgrade(r::HTTP.Message) | ||
(r isa HTTP.Request && r.method == "GET" || r.status == 101) && | ||
HTTP.hasheader(r, "Connection", "upgrade") && | ||
HTTP.hasheader(r, "Upgrade", "websocket") | ||
end | ||
|
||
# function listen(f::Function, host::String="localhost", port::UInt16=UInt16(8081); binary=false, verbose=false) | ||
# HTTP.listen(host, port; verbose=verbose) do http | ||
# upgrade(f, http; binary=binary) | ||
# end | ||
# end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
info("Loading HttpServer methods...") | ||
|
||
export WebSocketHandler | ||
|
||
|
||
""" | ||
Responds to a WebSocket handshake request. | ||
Checks for required headers and subprotocols; sends Response(400) if they're missing or bad. Otherwise, transforms client key into accept value, and sends Reponse(101). | ||
Function returns true for accepted handshakes. | ||
""" | ||
function websocket_handshake(request,client) | ||
if !haskey(request.headers, "Sec-WebSocket-Key") | ||
Base.write(client.sock, HttpServer.Response(400)) | ||
return false | ||
end | ||
if get(request.headers, "Sec-WebSocket-Version", "13") != "13" | ||
response = HttpServer.Response(400) | ||
response.headers["Sec-WebSocket-Version"] = "13" | ||
Base.write(client.sock, response) | ||
return false | ||
end | ||
|
||
key = request.headers["Sec-WebSocket-Key"] | ||
if length(base64decode(key)) != 16 # Key must be 16 bytes | ||
Base.write(client.sock, HttpServer.Response(400)) | ||
return false | ||
end | ||
resp_key = generate_websocket_key(key) | ||
|
||
response = HttpServer.Response(101) | ||
response.headers["Upgrade"] = "websocket" | ||
response.headers["Connection"] = "Upgrade" | ||
response.headers["Sec-WebSocket-Accept"] = resp_key | ||
|
||
if haskey(request.headers, "Sec-WebSocket-Protocol") | ||
if hasprotocol(request.headers["Sec-WebSocket-Protocol"]) | ||
response.headers["Sec-WebSocket-Protocol"] = request.headers["Sec-WebSocket-Protocol"] | ||
else | ||
Base.write(client.sock, HttpServer.Response(400)) | ||
return false | ||
end | ||
end | ||
|
||
Base.write(client.sock, response) | ||
return true | ||
end | ||
|
||
""" Implement the WebSocketInterface, for compatilibility with HttpServer.""" | ||
struct WebSocketHandler <: HttpServer.WebSocketInterface | ||
handle::Function | ||
end | ||
|
||
""" | ||
Performs handshake. If successfull, establishes WebSocket type and calls | ||
handler with the WebSocket and the original request. On exit from handler, closes websocket. No return value. | ||
""" | ||
function HttpServer.handle(handler::WebSocketHandler, req::HttpServer.Request, client::HttpServer.Client) | ||
websocket_handshake(req, client) || return | ||
sock = WebSocket(client.sock,true) | ||
handler.handle(req, sock) | ||
if isopen(sock) | ||
try | ||
close(sock) | ||
end | ||
end | ||
end | ||
|
||
function HttpServer.is_websocket_handshake(handler::WebSocketHandler, req::HttpServer.Request) | ||
is_get = req.method == "GET" | ||
# "upgrade" for Chrome and "keep-alive, upgrade" for Firefox. | ||
is_upgrade = contains(lowercase(get(req.headers, "Connection", "")),"upgrade") | ||
is_websockets = lowercase(get(req.headers, "Upgrade", "")) == "websocket" | ||
return is_get && is_upgrade && is_websockets | ||
end |
Oops, something went wrong.