Skip to content

Commit

Permalink
Merge branch 'main' into floitsch/add_content_size
Browse files Browse the repository at this point in the history
  • Loading branch information
floitsch committed Jul 28, 2023
2 parents bc17398 + 1e9de1e commit b387459
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 26 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Setup constants
shell: bash
Expand Down Expand Up @@ -70,7 +70,7 @@ jobs:
docker run -d -p 8765:80 kennethreitz/httpbin
docker ps
- uses: suisei-cn/actions-download-file@v1
- uses: suisei-cn/actions-download-file@v1.4.0
name: Download Toit
with:
url: ${{ env.TOIT_URL }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Publish
uses: toitlang/pkg-publish@v1.0.2
uses: toitlang/pkg-publish@v1.3.0
18 changes: 10 additions & 8 deletions src/client.toit
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ class Client:
--uri/string
--headers/Headers?=null:
parsed := parse_ uri --web_socket=false
ensure_connection_ parsed
request := connection_.new_request method parsed.path headers
request := null
try_to_reuse_ parsed: | connection |
request = connection.new_request method parsed.path headers
return request

/**
Expand All @@ -177,8 +178,9 @@ class Client:
--headers/Headers?=null
--use_tls/bool?=null:
parsed := parse_ host port path use_tls --web_socket=false
ensure_connection_ parsed
request := connection_.new_request method parsed.path headers
request := null
try_to_reuse_ parsed: | connection |
request = connection.new_request method parsed.path headers
return request

/**
Expand All @@ -205,8 +207,9 @@ class Client:
--path=path
--parse_port_in_host=true
if not parsed.scheme.starts_with "http": throw "INVALID_SCHEME"
ensure_connection_ parsed
request := connection_.new_request method parsed.path headers
request := null
try_to_reuse_ parsed: | connection |
request = connection.new_request method parsed.path headers
return request

static starts_with_ignore_case_ str/string needle/string -> bool:
Expand Down Expand Up @@ -343,10 +346,9 @@ class Client:
headers = headers ? headers.copy : Headers
MAX_REDIRECTS.repeat:
nonce := WebSocket.add_client_upgrade_headers_ headers
headers.add "Host" parsed.host_with_port
response/Response? := null
try_to_reuse_ parsed: | connection |
request := connection.new_request GET parsed.path headers
request/RequestOutgoing := connection.new_request GET parsed.path headers
response = request.send
if follow_redirects and
(is_regular_redirect_ response.status_code
Expand Down
6 changes: 3 additions & 3 deletions src/connection.toit
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class Connection:
else:
// Return a writer that doesn't accept any data.
body_writer = ContentLengthWriter this writer_ 0
if not headers.matches "Connection" "upgrade":
if not headers.matches "Connection" "Upgrade":
headers.set "Content-Length" "0"

// Set this before doing blocking operations on the socket, so that we
Expand Down Expand Up @@ -331,8 +331,8 @@ A $tcp.Socket doesn't support ungetting data that was already read for it, so we
*/
class DetachedSocket_ implements tcp.Socket:
socket_/tcp.Socket
buffered_/ByteArray? := null
constructor .socket_ buffered_:
buffered_/ByteArray? := ?
constructor .socket_ .buffered_:

local_address -> net.SocketAddress:
return socket_.local_address
Expand Down
21 changes: 11 additions & 10 deletions src/web_socket.toit
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,10 @@ class WebSocket:
// The WebSocket nonce is not very important and does not need to be
// cryptographically random.
nonce := base64.encode (ByteArray 16: random 0x100)
headers.add "Connection" "upgrade"
headers.add "Upgrade" "websocket"
headers.add "Sec-WebSocket-Key" nonce
headers.add "Sec-WebSocket-Version" "13"
headers.add "Connection" "Upgrade"
return nonce

static check_client_upgrade_response_ response/Response nonce/string -> none:
Expand Down Expand Up @@ -278,14 +278,15 @@ class WebSocket:
version_header := request.headers.single "Sec-WebSocket-Version"
nonce := request.headers.single "Sec-WebSocket-Key"
message := null
if nonce == null: message = "No nonce"
else if nonce.size != 24: message = "Bad nonce size"
else if connection_header != "upgrade": message = "No Connection: upgrade"
else if upgrade_header != "websocket": message = "No Upgrade: websocket"
else if version_header != "13": message = "Unrecognized Websocket version"
if nonce == null: message = "No nonce"
else if nonce.size != 24: message = "Bad nonce size"
else if not connection_header or not upgrade_header: message = "No upgrade headers"
else if (Headers.ascii_normalize_ connection_header) != "Upgrade": message = "No Connection: Upgrade"
else if (Headers.ascii_normalize_ upgrade_header) != "Websocket": message = "No Upgrade: websocket"
else if version_header != "13": message = "Unrecognized Websocket version"
else:
response_writer.headers.add "Sec-WebSocket-Accept" (response_ nonce)
response_writer.headers.add "Connection" "upgrade"
response_writer.headers.add "Connection" "Upgrade"
response_writer.headers.add "Upgrade" "websocket"
return nonce
response_writer.write_headers STATUS_BAD_REQUEST --message=message
Expand Down Expand Up @@ -425,11 +426,11 @@ class WebSocketReader implements reader.Reader:
class FragmentReader_:
owner_ /WebSocket
control_bits_ /int
size_ /int ::= ?
size_ /int
received_ := 0
masking_bytes /ByteArray? := null
masking_bytes /ByteArray?

constructor .owner_ .size_ .control_bits_ --masking_bytes/ByteArray?=null:
constructor .owner_ .size_ .control_bits_ --.masking_bytes/ByteArray?=null:

is_continuation -> bool: return control_bits_ & 0x0f == OPCODE_CONTINUATION_
is_text -> bool: return control_bits_ & 0x0f == OPCODE_TEXT_
Expand Down
22 changes: 22 additions & 0 deletions tests/google_404_test.toit
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (C) 2023 Toitware ApS.
// Use of this source code is governed by a Zero-Clause BSD license that can
// be found in the tests/TESTS_LICENSE file.
import certificate_roots show *
import expect show *
import http
import net

HOST ::= "google.com"
PATH ::= "/nogood"
CODE ::= 404

main:
network := net.open
client := http.Client.tls network

client.root_certificates_.add GTS_ROOT_R1

response := client.get --host=HOST --path=PATH

expect_equals CODE response.status_code
3 changes: 1 addition & 2 deletions tests/google_test.toit
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ main:
security_store := http.SecurityStoreInMemory
client := http.Client.tls network
--security_store=security_store
--root_certificates=[certificate_roots.GLOBALSIGN_ROOT_CA,
certificate_roots.GTS_ROOT_R1]
--root_certificates=[certificate_roots.GTS_ROOT_R1]
response := client.get "script.google.com" "/"
while data := response.body.read:
response = client.get "www.google.com" "/"
Expand Down
28 changes: 28 additions & 0 deletions tests/websocket_client_test.toit
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2023 Toitware ApS.
// Use of this source code is governed by a Zero-Clause BSD license that can
// be found in the tests/TESTS_LICENSE file.
import certificate_roots
import expect show *
import http
import net

URI ::= "wss://echo.websocket.events/"
// This header is required by the WebSocket endpoint.
ORIGIN ::= { "Origin": "http://echo.websocket.events" }
MSG1 ::= "Hello, from Toit!"
MSG2 ::= #[0xff, 0x00, 103]

main:
network := net.open
client := http.Client network --root_certificates=[certificate_roots.ISRG_ROOT_X1]
web_socket := client.web_socket --uri=URI --headers=(http.Headers.from_map ORIGIN)
greeting := web_socket.receive
expect_equals "echo.websocket.events sponsored by Lob.com" greeting
print greeting
web_socket.send MSG1
echo := web_socket.receive
expect_equals MSG1 echo
web_socket.send MSG2
echo_bytes := web_socket.receive
expect_equals MSG2 echo_bytes

0 comments on commit b387459

Please sign in to comment.