johnk
johnk

Reputation: 1102

How do I pass a URL a cookie using Rebol 3 and get the response cookies?

This stackoverflow question - How do I pass a URL a cookie using Rebol 3? - almost answers my question, but I am not sure how to capture the cookies from the response.

What I would like to do is call to a URL passing in cookies (and headers) and to be able to view the response and the cookies (and headers).

I think what I need to do is to open the port then I can query the response. Something like this:

site: open http://rebol.com
write site [ GET [ Cookie: {test=1}] ]
query site
close site

Is this the best approach?

Upvotes: 3

Views: 209

Answers (1)

Graham Chiu
Graham Chiu

Reputation: 4886

I do this using an http protocol that has been modified to

  1. use an optional headers word in the write dialect that returns the port object so you can inspect the body and header
  2. return an error object with the port object when an error eg. a manual redirect is required.

The file is available at:

https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3

>> do https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3
>> a: write http://stackoverflow.com [ headers "" ]
>> probe a/spec/debug/headers/set-cookie
[{__cfduid=d349046701c0e9fd9f8858fa4b406ff141438752651; expires=Thu, 04-Aug-16 0
5:30:51 GMT; path=/; domain=.stackoverflow.com; HttpOnly} {prov=f1a9c7a9-cd49-44
82-94e0-4594c7991c19; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:
00 GMT; path=/; HttpOnly}]

Here is a .patch file of what's different from the http.r that's currently used by Atronix and Ren/C:

diff --git a/src/mezz/prot-http.r b/src/mezz/prot-http.r
index 426f115..dfa344a 100644
--- a/src/mezz/prot-http.r
+++ b/src/mezz/prot-http.r
@@ -11,16 +11,27 @@ REBOL [
    }
    Name: 'http
    Type: 'module
-   Version: 0.1.4
-   File: %prot-http.r
+   Version: 0.1.45
+   File: %prot-http.r3
    Purpose: {
        This program defines the HTTP protocol scheme for REBOL 3.
    }
-   Author: ["Gabriele Santilli" "Richard Smolak"]
-   Date: 26-Nov-2012
+   Author: ["Gabriele Santilli" "Richard Smolak" "Graham Chiu"]
+   notes: {modified to return an error object with the info object when manual redirect required - Graham}
+   Date: 27-April-2014
 ]

-sync-op: func [port body /local state] [
+digit: charset [ #"0" - #"9" ]
+alpha: charset [ #"a" - #"z" #"A" - #"Z" ]
+idate-to-date: func [ date [string!] /local day month year time zone]
+[
+   either parse date [ 5 skip copy day 2 digit space copy month 3 alpha space copy year 4 digit space copy time to space space copy zone to end ][
+       if zone = "GMT" [ zone: copy "+0" ]
+       to date! ajoin [ day "-" month "-" year "/" time zone ]
+   ][ none ]
+]
+
+sync-op: func [port body /local state ] [
    unless port/state [open port port/state/close?: yes]
    state: port/state
    state/awake: :read-sync-awake
@@ -35,7 +46,11 @@ sync-op: func [port body /local state] [
    ]
    body: copy port
    if state/close? [close port]
-   body
+   either port/spec/debug [
+       state/connection/locals
+   ][
+       body
+   ]
 ]
 read-sync-awake: func [event [event!] /local error] [
    switch/default event/type [
@@ -111,12 +126,34 @@ http-awake: func [event /local port http-port state awake res] [
 make-http-error: func [
    "Make an error for the HTTP protocol"
    message [string! block!]
+   /inf obj
+   /otherhost new-url [url!]
 ] [
    if block? message [message: ajoin message]
-   make error! [
-       type: 'Access
-       id: 'Protocol
-       arg1: message
+   case [
+       inf [
+           make error! [
+               type: 'Access
+               id: 'Protocol
+               arg1: message
+               arg2: obj
+           ]
+       ]
+       otherhost [
+           make error! [
+               type: 'Access
+               id: 'Protocol
+               arg1: message
+               arg3: new-url
+           ]
+       ]
+       true [
+           make error! [
+               type: 'Access
+               id: 'Protocol
+               arg1: message
+           ]
+       ]
    ]
 ]
 http-error: func [
@@ -174,9 +211,11 @@ do-request: func [
    make-http-request spec/method to file! any [spec/path %/]
    spec/headers spec/content
 ]
-parse-write-dialect: func [port block /local spec] [
+parse-write-dialect: func [port block /local spec debug] [
    spec: port/spec
-   parse block [[set block word! (spec/method: block) | (spec/method: 'post)]
+   parse block [
+       opt [ 'headers ( spec/debug: true ) ] 
+       [set block word! (spec/method: block) | (spec/method: 'post)]
        opt [set block [file! | url!] (spec/path: block)] [set block block! (spec/headers: block) | (spec/headers: [])] [set block [any-string! | binary!] (spec/content: block) | (spec/content: none)]
    ]
 ]
@@ -197,7 +236,7 @@ check-response: func [port /local conn res headers d1 d2 line info state awake s
        info/headers: headers: construct/with d1 http-response-headers
        info/name: to file! any [spec/path %/]
        if headers/content-length [info/size: headers/content-length: to integer! headers/content-length]
-       if headers/last-modified [info/date: attempt [to date! headers/last-modified]]
+       if headers/last-modified [info/date: attempt [idate-to-date headers/last-modified]]
        remove/part conn/data d2
        state/state: 'reading-data
    ]
@@ -237,6 +276,9 @@ check-response: func [port /local conn res headers d1 d2 line info state awake s
            | (info/response-parsed: 'version-not-supported)
        ]
    ]
+   if all [logic? spec/debug true? spec/debug]  [
+       spec/debug: info
+   ]
    switch/all info/response-parsed [
        ok [
            either spec/method = 'head [
@@ -276,7 +318,7 @@ check-response: func [port /local conn res headers d1 d2 line info state awake s
                ] [
                    res: do-redirect port headers/location
                ] [
-                   state/error: make-http-error "Redirect requires manual intervention"
+                   state/error: make-http-error/inf "Redirect requires manual intervention" info
                    res: awake make event! [type: 'error port: port]
                ]
            ]
@@ -364,7 +406,7 @@ do-redirect: func [port [port!] new-uri [url! string! file!] /local spec state]
        do-request port
        false
    ] [
-       state/error: make-http-error "Redirect to other host - requires custom handling"
+       state/error: make-http-error/otherhost "Redirect to other host - requires custom handling" to-url rejoin [new-uri/scheme "://" new-uri/host new-uri/path]
        state/awake make event! [type: 'error port: port]
    ]
 ]
@@ -449,6 +491,7 @@ sys/make-scheme [
        headers: []
        content: none
        timeout: 15
+       debug: none
    ]
    info: make system/standard/file-info [
        response-line:

Upvotes: 2

Related Questions