Skip to content

Commit ae93f76

Browse files
committed
ATRONIX: updated HTTP scheme to version 0.1.4 (Richard Smalak changes from Atronix fork)
1 parent b03dd68 commit ae93f76

File tree

1 file changed

+58
-15
lines changed

1 file changed

+58
-15
lines changed

src/mezz/prot-http.r

+58-15
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ REBOL [
1111
}
1212
Name: 'http
1313
Type: 'module
14-
Version: 0.1.0
14+
Version: 0.1.4
1515
File: %prot-http.r
1616
Purpose: {
1717
This program defines the HTTP protocol scheme for REBOL 3.
1818
}
19-
Author: "Gabriele Santilli"
20-
Date: 22-Jun-2007
19+
Author: ["Gabriele Santilli" "Richard Smolak"]
20+
Date: 26-Nov-2012
2121
]
2222

2323
sync-op: func [port body /local state] [
@@ -26,7 +26,13 @@ sync-op: func [port body /local state] [
2626
state/awake: :read-sync-awake
2727
do body
2828
if state/state = 'ready [do-request port]
29-
unless port? wait [state/connection port/spec/timeout] [http-error "Timeout"]
29+
;NOTE: We'll wait in a WHILE loop so the timeout cannot occur during 'reading-data state.
30+
;The timeout should be triggered only when the response from other side exceeds the timeout value.
31+
;--Richard
32+
while [not find [ready close] state/state][
33+
unless port? wait [state/connection port/spec/timeout] [http-error "Timeout"]
34+
if state/state = 'reading-data [read state/connection]
35+
]
3036
body: copy port
3137
if state/close? [close port]
3238
body
@@ -88,6 +94,8 @@ http-awake: func [event /local port http-port state awake res] [
8894
state/error: make-http-error "Server closed connection"
8995
awake make event! [type: 'error port: http-port]
9096
] [
97+
;set state to CLOSE so the WAIT loop in 'sync-op can be interrupted --Richard
98+
state/state: 'close
9199
any [
92100
awake make event! [type: 'done port: http-port]
93101
awake make event! [type: 'close port: http-port]
@@ -152,7 +160,7 @@ do-request: func [
152160
spec/headers: body-of make make object! [
153161
Accept: "*/*"
154162
Accept-Charset: "utf-8"
155-
Host: either spec/port-id <> 80 [
163+
Host: either not find [80 443] spec/port-id [
156164
rejoin [form spec/host #":" spec/port-id]
157165
] [
158166
form spec/host
@@ -249,6 +257,11 @@ check-response: func [port /local conn res headers d1 d2 line info state awake s
249257
res: awake make event! [type: 'custom port: port code: 0]
250258
] [
251259
res: check-data port
260+
unless open? port [
261+
;NOTE some servers(e.g. yahoo.com) don't supply content-data in the redirect header so the state/state can be left in 'reading-data after check-data call
262+
;I think it is better to check if port has been closed here and set the state so redirect sequence can happen. --Richard
263+
state/state: 'ready
264+
]
252265
]
253266
if all [not res state/state = 'ready] [
254267
either all [
@@ -328,16 +341,26 @@ do-redirect: func [port [port!] new-uri [url! string! file!] /local spec state]
328341
if #"/" = first new-uri [
329342
new-uri: to url! ajoin [spec/scheme "://" spec/host new-uri]
330343
]
331-
new-uri: construct/with decode-url new-uri port/scheme/spec
332-
if new-uri/scheme <> 'http [
333-
state/error: make-http-error {Redirect to a protocol different from HTTP not supported}
344+
new-uri: decode-url new-uri
345+
unless select new-uri 'port-id [
346+
switch new-uri/scheme [
347+
'https [append new-uri [port-id: 443]]
348+
'http [append new-uri [port-id: 80]]
349+
]
350+
]
351+
new-uri: construct/with new-uri port/scheme/spec
352+
unless find [http https] new-uri/scheme [
353+
state/error: make-http-error {Redirect to a protocol different from HTTP or HTTPS not supported}
334354
return state/awake make event! [type: 'error port: port]
335355
]
336356
either all [
337357
new-uri/host = spec/host
338358
new-uri/port-id = spec/port-id
339359
] [
340360
spec/path: new-uri/path
361+
;we need to reset tcp connection here before doing a redirect
362+
close port/state/connection
363+
open port/state/connection
341364
do-request port
342365
false
343366
] [
@@ -353,12 +376,14 @@ check-data: func [port /local headers res data out chunk-size mk1 mk2 trailer st
353376
case [
354377
headers/transfer-encoding = "chunked" [
355378
data: conn/data
356-
out: port/data: make binary! length? data
379+
;clear the port data only at the beginning of the request --Richard
380+
unless port/data [port/data: make binary! length? data]
381+
out: port/data
357382
until [
358383
either parse/all data [
359384
copy chunk-size some hex-digits thru crlfbin mk1: to end
360385
] [
361-
chunk-size: to integer! to issue! chunk-size
386+
chunk-size: to integer! to issue! to string! chunk-size
362387
either chunk-size = 0 [
363388
if parse/all mk1 [
364389
crlfbin (trailer: "") to end | copy trailer to crlf2bin to end
@@ -385,7 +410,10 @@ check-data: func [port /local headers res data out chunk-size mk1 mk2 trailer st
385410
true
386411
]
387412
]
388-
unless state/state = 'ready [read conn]
413+
unless state/state = 'ready [
414+
;Awake from the WAIT loop to prevent timeout when reading big data. --Richard
415+
res: true
416+
]
389417
]
390418
integer? headers/content-length [
391419
port/data: conn/data
@@ -394,12 +422,19 @@ check-data: func [port /local headers res data out chunk-size mk1 mk2 trailer st
394422
conn/data: make binary! 32000
395423
res: state/awake make event! [type: 'custom port: port code: 0]
396424
] [
397-
read conn
425+
;Awake from the WAIT loop to prevent timeout when reading big data. --Richard
426+
res: true
398427
]
399428
]
400429
true [
401430
port/data: conn/data
402-
read conn
431+
either state/info/response-parsed = 'ok [
432+
;Awake from the WAIT loop to prevent timeout when reading big data. --Richard
433+
res: true
434+
][
435+
;On other response than OK read all data asynchronously (assuming the data are small). --Richard
436+
read conn
437+
]
403438
]
404439
]
405440
res
@@ -465,8 +500,8 @@ sys/make-scheme [
465500
info: make port/scheme/info [type: 'file]
466501
awake: :port/awake
467502
]
468-
port/state/connection: conn: make port! [
469-
scheme: 'tcp
503+
port/state/connection: conn: make port! compose [
504+
scheme: (to lit-word! either port/spec/scheme = 'http ['tcp]['tls])
470505
host: port/spec/host
471506
port-id: port/spec/port-id
472507
ref: rejoin [tcp:// host ":" port-id]
@@ -520,3 +555,11 @@ sys/make-scheme [
520555
]
521556
]
522557
]
558+
559+
sys/make-scheme/with [
560+
name: 'https
561+
title: "Secure HyperText Transport Protocol v1.1"
562+
spec: make spec [
563+
port-id: 443
564+
]
565+
] 'http

0 commit comments

Comments
 (0)