Skip to content

Commit 74f3df0

Browse files
committed
FEAT: implemented read/seek on url!
1 parent 1171af8 commit 74f3df0

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/mezz/prot-http.reb

+30-9
Original file line numberDiff line numberDiff line change
@@ -733,15 +733,28 @@ sys/make-scheme [
733733
actor: [
734734
read: func [
735735
port [port!]
736-
/binary
737-
/part length [number!]
738-
/lines
736+
/part {Partial read a given number of units (source relative)}
737+
length [integer!]
738+
/seek {Read from a specific position (source relative)}
739+
index [integer!] "zero-based!"
740+
/string {Convert UTF and line terminators to standard text string}
741+
/binary {Preserves contents exactly}
742+
/lines {Convert to block of strings (implies /string)}
739743
/local result
740744
][
741745
sys/log/debug 'HTTP "READ"
746+
if lines [
747+
if binary [cause-error 'Script 'bad-refine /binary ]
748+
seek: part: none
749+
]
750+
if all [string binary] [cause-error 'Script 'bad-refines none]
751+
742752
unless port/state [open port port/state/close?: yes]
743-
if all [part binary length > 0] [
744-
append port/spec/headers compose [Range: (join "bytes=0-" (to integer! length) - 1)]
753+
754+
if all [any [part seek] not string] [
755+
either seek [ binary: true assert [index >= 0]][ index: 0 ]
756+
length: either part [ assert [length > 0] length + index][ none ]
757+
put port/spec/headers quote Range: ajoin ["bytes=" index #"-" any [all [length length - 1] ""]]
745758
]
746759
either any-function? :port/awake [
747760
unless open? port [cause-error 'Access 'not-open port/spec/ref]
@@ -750,11 +763,19 @@ sys/make-scheme [
750763
do-request port
751764
][
752765
result: sync-op port []
753-
unless binary [decode-result result]
754-
if result/2 [
766+
either binary [
767+
unless find result/1 'Accept-Ranges [
768+
case/all [
769+
seek [ result/2: at result/2 index if part [length: length - index]]
770+
part [ clear skip result/2 length]
771+
]
772+
]
773+
][
774+
decode-result result
755775
case/all [
756-
lines [ result/2: split-lines result/2 ]
757-
part [ clear skip result/2 length ]
776+
lines [ result/2: split-lines result/2 ]
777+
index [ result/2: skip result/2 index ]
778+
length [ clear skip result/2 length]
758779
]
759780
]
760781
result/2

src/tests/units/port-test.r3

+24
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,30 @@ if system/platform = 'Windows [
554554
--assert error? try [query https://www]
555555
--assert object? query https://www.google.com
556556

557+
--test-- "read/seek/part"
558+
; first results without read/part
559+
--assert "<!doctype html>" = copy/part str: read/string http://example.com 15
560+
--assert "<!doctype html>" = copy/part skip str 0 15
561+
--assert "doctype html>" = copy/part skip str 2 13
562+
; using read/part
563+
--assert "<!doctype html>" = read/part http://example.com 15
564+
--assert "<!doctype html>" = read/seek/part/string http://example.com 0 15
565+
--assert "doctype html>" = read/seek/part/string http://example.com 2 13
566+
; when used /seek without /string, than result is always binary!
567+
--assert #{3C21646F63747970652068746D6C3E} = read/seek/part http://example.com 0 15
568+
--assert #{646F63747970652068746D6C3E} = read/seek/part http://example.com 2 13
569+
570+
--test-- "read/lines/seek/part"
571+
--assert ["<!doctype html>" "<html>" "<head>"] = read/lines/part http://example.com 3
572+
--assert ["<!doctype html>" "<html>" "<head>"] = read/lines/seek/part http://example.com 0 3
573+
--assert ["<html>" "<head>"] = read/lines/seek/part http://example.com 1 2
574+
; using /lines with /binary is not allowed
575+
--assert all [error? e: try [read/lines/binary http://example.com] e/id = 'bad-refine]
576+
--assert all [block? b: try [read/lines/seek http://example.com 2] b/1 = "<head>"]
577+
578+
--test-- "read/string/binary"
579+
--assert all [error? e: try [read/string/binary http://example.com] e/id = 'bad-refines]
580+
557581
===end-group===
558582

559583

0 commit comments

Comments
 (0)