Urbit Developers
  • Hoon

    • Overview
    • Cheat Sheet
    • Irregular forms
    • Hoon Errors
    • Hoon Style Guide
    • Basic Types
    • Advanced Types
    • Auras
    • Arvo
    • Standard Library

      • 1a: Basic Arithmetic
      • 1b: Tree Addressing
      • 1c: Molds and Mold-Builders
      • 2a: Unit Logic
      • 2b: List Logic
      • 2c: Bit Arithmetic
      • 2d: Bit Logic
      • 2e: Insecure Hashing
      • 2f: Noun Ordering
      • 2g: Unsigned Powers
      • 2h: Set Logic
      • 2i: Map Logic
      • 2j: Jar and Jug Logic
      • 2k: Queue Logic
      • 2l: Container from Container
      • 2m: Container from Noun
      • 2n: Functional Hacks
      • 2o: Normalizing Containers
      • 2p: Serialization
      • 2q: Molds and Mold-Builders
      • 3a: Modular and Signed Ints
      • 3b: Floating Point
      • 3c: Urbit Time
      • 3d: SHA Hash Family
      • 3e: AES encryption (Removed)
      • 3f: Scrambling
      • 3g: Molds and Mold-Builders
      • 4a: Exotic Bases
      • 4b: Text Processing
      • 4c: Tank Printer
      • 4d: Parsing (Tracing)
      • 4e: Parsing (Combinators)
      • 4f: Parsing (Rule-Builders)
      • 4g: Parsing (Outside Caller)
      • 4h: Parsing (ASCII Glyphs)
      • 4i: Parsing (Useful Idioms)
      • 4j: Parsing (Bases and Base Digits)
      • 4k: Atom Printing
      • 4l: Atom Parsing
      • 4m: Formatting Functions
      • 4n: Virtualization
      • 4o: Molds
      • 5a: Compiler Utilities
      • 5b: Macro Expansion
      • 5c: Compiler Backend & Prettyprinter
      • 5d: Parser
      • 5e: Molds and mold builders
      • 5f: Profiling support
      • Runes

        • Constants (Atoms and Strings)
        • + lus · Arms
        • | bar · Cores
        • $ buc · Structures
        • % cen · Calls
        • : col · Cells
        • . dot · Nock
        • / fas · Imports
        • ^ ket · Casts
        • ; mic · Make
        • ~ sig · Hints
        • = tis · Subject
        • ? wut · Conditionals
        • ! zap · Wild
        • --, == Terminators
        • Limbs and wings

          • Limbs
          • Wings
          • Zuse

            • 2d(1-5): To JSON, Wains
            • 2d(6): From JSON
            • 2d(7): From JSON (unit)
            • 2e(2-3): Print & Parse JSON
            • 2m: Ordered Maps
          • Arvo

            • Overview
            • Ames

              • Overview
              • Cryptography
              • API Reference
              • Scry Reference
              • Data Types
              • Behn

                • Overview
                • API Reference
                • Scry Reference
                • Examples
                • Clay

                  • Overview
                  • Architecture
                  • Using Clay
                  • Data Types
                  • Scry Reference
                  • API Reference
                  • Examples
                  • Marks

                    • Overview
                    • Writing Marks
                    • Using Marks
                    • Examples
                  • Dill

                    • Overview
                    • API Reference
                    • Scry Reference
                    • Data Types
                    • Eyre

                      • Overview
                      • External API Reference
                      • Internal API Reference
                      • Scry Reference
                      • Data Types
                      • Guide
                      • Gall

                        • Overview
                        • API Reference
                        • Data Types
                        • Threads Reference
                        • Iris

                          • Overview
                          • API Reference
                          • Data Types
                          • Example
                          • Jael

                            • Overview
                            • API Reference
                            • Scry Reference
                            • Data Types
                            • Examples
                            • Khan

                              • Overview
                              • API Reference
                              • Data Types
                              • Example
                              • Threads

                                • Overview
                                • HTTP API
                                • Reference
                                • Gall

                                  • Start Thread
                                  • Take Result
                                  • Take Facts
                                  • Stop Thread
                                  • Poke Thread
                                  • Examples

                                    • Fetch JSON
                                    • Child Thread
                                    • Main-loop
                                    • Poke Agent
                                    • Scry
                                    • Take Fact
                                  • Concepts

                                    • Scries
                                    • Subscriptions
                                    • Tutorials

                                      • Move Trace
                                      • Reference

                                        • Cryptography
                                        • Filesystem Hierarchy
                                      • Nock

                                        • Nock Definition
                                        • Explanation
                                        • Example
                                        • Implementations
                                        • Vere

                                          • C Runtime System
                                          • Land of Nouns
                                          • API overview by prefix
                                          • C in Urbit
                                          • Writing Jets
                                          • Cryptography
                                          • Azimuth

                                            • Overview
                                            • Urbit HD Wallet
                                            • Azimuth Data Flow
                                            • Azimuth.eth
                                            • Ecliptic.eth
                                            • Advanced Azimuth Tools
                                            • Life and Rift
                                            • Layer 2

                                              • Layer 2 Overview
                                              • Layer 2 Actions
                                              • Transaction Format
                                              • Rollers
                                              • Roller HTTP RPC-API
                                              • Custom Roller Tutorial
                                            • Glossary

                                              • Agent
                                              • Ames
                                              • API
                                              • Aqua
                                              • Arm
                                              • Arvo
                                              • Atom
                                              • Aura
                                              • Aural ASCII
                                              • Azimuth
                                              • Battery
                                              • Behn
                                              • Bowl
                                              • Bridge
                                              • Bunt
                                              • Card
                                              • Case
                                              • Cask
                                              • Cell
                                              • Censures
                                              • Claims
                                              • Clay
                                              • Cold atom
                                              • Comet
                                              • Commit
                                              • Cons
                                              • Context
                                              • Cord
                                              • Core
                                              • Delegated Sending
                                              • Desk
                                              • Dill
                                              • Document Proposal
                                              • Dojo
                                              • Door
                                              • Double-boot
                                              • Dry Gate
                                              • Duct
                                              • Ecliptic
                                              • Entropy
                                              • Event Log
                                              • Eyre
                                              • Face
                                              • Fact
                                              • Foo Bar Baz
                                              • Galaxy
                                              • Gall
                                              • Garden
                                              • Gate
                                              • Generator
                                              • Gift
                                              • Glob
                                              • HD Wallet
                                              • Helm
                                              • Hood
                                              • Hoon
                                              • Invite Tree
                                              • Iris
                                              • Jael
                                              • Jet
                                              • Kelvin versioning
                                              • Kelvin versioning
                                              • Keyfile
                                              • Keywords
                                              • Khan
                                              • Kiln
                                              • Landscape
                                              • Leg
                                              • List
                                              • Loobean
                                              • Lull
                                              • Mark
                                              • Metals
                                              • Mold
                                              • Monad
                                              • Moon
                                              • Move
                                              • Nock
                                              • Noun
                                              • ~
                                              • OTA Updates
                                              • Path Prefix
                                              • Path
                                              • @p
                                              • Payload
                                              • Peek
                                              • pH
                                              • Pier
                                              • Pill
                                              • Planet
                                              • Poke
                                              • Proxies
                                              • Replay
                                              • Factory Reset
                                              • Roller
                                              • Naive rollups
                                              • Rune
                                              • Runtime
                                              • Sail
                                              • Sample
                                              • Scry
                                              • Senate
                                              • Ship
                                              • Slam
                                              • Spider
                                              • Sponsor
                                              • Star
                                              • String
                                              • Subject Oriented Programming
                                              • Subject
                                              • Subscription
                                              • Tape
                                              • Thread
                                              • Trap
                                              • Udon
                                              • Upgrade Proposal
                                              • Userspace
                                              • Vane
                                              • Vase
                                              • Vere
                                              • Voting
                                              • Warm atom
                                              • Wet Gate
                                              • Wing
                                              • Wire
                                              • Wrapper
                                              • ~zod
                                              • Zuse
                                              • Additional

                                                • Cryptography
                                                • Mips (Maps of Maps)
                                                • Software Distribution

                                                  • Overview
                                                  • Docket File
                                                  • Glob
                                                Urbit Developers
                                                • Hoon

                                                  • Overview
                                                  • Cheat Sheet
                                                  • Irregular forms
                                                  • Hoon Errors
                                                  • Hoon Style Guide
                                                  • Basic Types
                                                  • Advanced Types
                                                  • Auras
                                                  • Arvo
                                                  • Standard Library

                                                    • 1a: Basic Arithmetic
                                                    • 1b: Tree Addressing
                                                    • 1c: Molds and Mold-Builders
                                                    • 2a: Unit Logic
                                                    • 2b: List Logic
                                                    • 2c: Bit Arithmetic
                                                    • 2d: Bit Logic
                                                    • 2e: Insecure Hashing
                                                    • 2f: Noun Ordering
                                                    • 2g: Unsigned Powers
                                                    • 2h: Set Logic
                                                    • 2i: Map Logic
                                                    • 2j: Jar and Jug Logic
                                                    • 2k: Queue Logic
                                                    • 2l: Container from Container
                                                    • 2m: Container from Noun
                                                    • 2n: Functional Hacks
                                                    • 2o: Normalizing Containers
                                                    • 2p: Serialization
                                                    • 2q: Molds and Mold-Builders
                                                    • 3a: Modular and Signed Ints
                                                    • 3b: Floating Point
                                                    • 3c: Urbit Time
                                                    • 3d: SHA Hash Family
                                                    • 3e: AES encryption (Removed)
                                                    • 3f: Scrambling
                                                    • 3g: Molds and Mold-Builders
                                                    • 4a: Exotic Bases
                                                    • 4b: Text Processing
                                                    • 4c: Tank Printer
                                                    • 4d: Parsing (Tracing)
                                                    • 4e: Parsing (Combinators)
                                                    • 4f: Parsing (Rule-Builders)
                                                    • 4g: Parsing (Outside Caller)
                                                    • 4h: Parsing (ASCII Glyphs)
                                                    • 4i: Parsing (Useful Idioms)
                                                    • 4j: Parsing (Bases and Base Digits)
                                                    • 4k: Atom Printing
                                                    • 4l: Atom Parsing
                                                    • 4m: Formatting Functions
                                                    • 4n: Virtualization
                                                    • 4o: Molds
                                                    • 5a: Compiler Utilities
                                                    • 5b: Macro Expansion
                                                    • 5c: Compiler Backend & Prettyprinter
                                                    • 5d: Parser
                                                    • 5e: Molds and mold builders
                                                    • 5f: Profiling support
                                                    • Runes

                                                      • Constants (Atoms and Strings)
                                                      • + lus · Arms
                                                      • | bar · Cores
                                                      • $ buc · Structures
                                                      • % cen · Calls
                                                      • : col · Cells
                                                      • . dot · Nock
                                                      • / fas · Imports
                                                      • ^ ket · Casts
                                                      • ; mic · Make
                                                      • ~ sig · Hints
                                                      • = tis · Subject
                                                      • ? wut · Conditionals
                                                      • ! zap · Wild
                                                      • --, == Terminators
                                                      • Limbs and wings

                                                        • Limbs
                                                        • Wings
                                                        • Zuse

                                                          • 2d(1-5): To JSON, Wains
                                                          • 2d(6): From JSON
                                                          • 2d(7): From JSON (unit)
                                                          • 2e(2-3): Print & Parse JSON
                                                          • 2m: Ordered Maps
                                                        • Arvo

                                                          • Overview
                                                          • Ames

                                                            • Overview
                                                            • Cryptography
                                                            • API Reference
                                                            • Scry Reference
                                                            • Data Types
                                                            • Behn

                                                              • Overview
                                                              • API Reference
                                                              • Scry Reference
                                                              • Examples
                                                              • Clay

                                                                • Overview
                                                                • Architecture
                                                                • Using Clay
                                                                • Data Types
                                                                • Scry Reference
                                                                • API Reference
                                                                • Examples
                                                                • Marks

                                                                  • Overview
                                                                  • Writing Marks
                                                                  • Using Marks
                                                                  • Examples
                                                                • Dill

                                                                  • Overview
                                                                  • API Reference
                                                                  • Scry Reference
                                                                  • Data Types
                                                                  • Eyre

                                                                    • Overview
                                                                    • External API Reference
                                                                    • Internal API Reference
                                                                    • Scry Reference
                                                                    • Data Types
                                                                    • Guide
                                                                    • Gall

                                                                      • Overview
                                                                      • API Reference
                                                                      • Data Types
                                                                      • Threads Reference
                                                                      • Iris

                                                                        • Overview
                                                                        • API Reference
                                                                        • Data Types
                                                                        • Example
                                                                        • Jael

                                                                          • Overview
                                                                          • API Reference
                                                                          • Scry Reference
                                                                          • Data Types
                                                                          • Examples
                                                                          • Khan

                                                                            • Overview
                                                                            • API Reference
                                                                            • Data Types
                                                                            • Example
                                                                            • Threads

                                                                              • Overview
                                                                              • HTTP API
                                                                              • Reference
                                                                              • Gall

                                                                                • Start Thread
                                                                                • Take Result
                                                                                • Take Facts
                                                                                • Stop Thread
                                                                                • Poke Thread
                                                                                • Examples

                                                                                  • Fetch JSON
                                                                                  • Child Thread
                                                                                  • Main-loop
                                                                                  • Poke Agent
                                                                                  • Scry
                                                                                  • Take Fact
                                                                                • Concepts

                                                                                  • Scries
                                                                                  • Subscriptions
                                                                                  • Tutorials

                                                                                    • Move Trace
                                                                                    • Reference

                                                                                      • Cryptography
                                                                                      • Filesystem Hierarchy
                                                                                    • Nock

                                                                                      • Nock Definition
                                                                                      • Explanation
                                                                                      • Example
                                                                                      • Implementations
                                                                                      • Vere

                                                                                        • C Runtime System
                                                                                        • Land of Nouns
                                                                                        • API overview by prefix
                                                                                        • C in Urbit
                                                                                        • Writing Jets
                                                                                        • Cryptography
                                                                                        • Azimuth

                                                                                          • Overview
                                                                                          • Urbit HD Wallet
                                                                                          • Azimuth Data Flow
                                                                                          • Azimuth.eth
                                                                                          • Ecliptic.eth
                                                                                          • Advanced Azimuth Tools
                                                                                          • Life and Rift
                                                                                          • Layer 2

                                                                                            • Layer 2 Overview
                                                                                            • Layer 2 Actions
                                                                                            • Transaction Format
                                                                                            • Rollers
                                                                                            • Roller HTTP RPC-API
                                                                                            • Custom Roller Tutorial
                                                                                          • Glossary

                                                                                            • Agent
                                                                                            • Ames
                                                                                            • API
                                                                                            • Aqua
                                                                                            • Arm
                                                                                            • Arvo
                                                                                            • Atom
                                                                                            • Aura
                                                                                            • Aural ASCII
                                                                                            • Azimuth
                                                                                            • Battery
                                                                                            • Behn
                                                                                            • Bowl
                                                                                            • Bridge
                                                                                            • Bunt
                                                                                            • Card
                                                                                            • Case
                                                                                            • Cask
                                                                                            • Cell
                                                                                            • Censures
                                                                                            • Claims
                                                                                            • Clay
                                                                                            • Cold atom
                                                                                            • Comet
                                                                                            • Commit
                                                                                            • Cons
                                                                                            • Context
                                                                                            • Cord
                                                                                            • Core
                                                                                            • Delegated Sending
                                                                                            • Desk
                                                                                            • Dill
                                                                                            • Document Proposal
                                                                                            • Dojo
                                                                                            • Door
                                                                                            • Double-boot
                                                                                            • Dry Gate
                                                                                            • Duct
                                                                                            • Ecliptic
                                                                                            • Entropy
                                                                                            • Event Log
                                                                                            • Eyre
                                                                                            • Face
                                                                                            • Fact
                                                                                            • Foo Bar Baz
                                                                                            • Galaxy
                                                                                            • Gall
                                                                                            • Garden
                                                                                            • Gate
                                                                                            • Generator
                                                                                            • Gift
                                                                                            • Glob
                                                                                            • HD Wallet
                                                                                            • Helm
                                                                                            • Hood
                                                                                            • Hoon
                                                                                            • Invite Tree
                                                                                            • Iris
                                                                                            • Jael
                                                                                            • Jet
                                                                                            • Kelvin versioning
                                                                                            • Kelvin versioning
                                                                                            • Keyfile
                                                                                            • Keywords
                                                                                            • Khan
                                                                                            • Kiln
                                                                                            • Landscape
                                                                                            • Leg
                                                                                            • List
                                                                                            • Loobean
                                                                                            • Lull
                                                                                            • Mark
                                                                                            • Metals
                                                                                            • Mold
                                                                                            • Monad
                                                                                            • Moon
                                                                                            • Move
                                                                                            • Nock
                                                                                            • Noun
                                                                                            • ~
                                                                                            • OTA Updates
                                                                                            • Path Prefix
                                                                                            • Path
                                                                                            • @p
                                                                                            • Payload
                                                                                            • Peek
                                                                                            • pH
                                                                                            • Pier
                                                                                            • Pill
                                                                                            • Planet
                                                                                            • Poke
                                                                                            • Proxies
                                                                                            • Replay
                                                                                            • Factory Reset
                                                                                            • Roller
                                                                                            • Naive rollups
                                                                                            • Rune
                                                                                            • Runtime
                                                                                            • Sail
                                                                                            • Sample
                                                                                            • Scry
                                                                                            • Senate
                                                                                            • Ship
                                                                                            • Slam
                                                                                            • Spider
                                                                                            • Sponsor
                                                                                            • Star
                                                                                            • String
                                                                                            • Subject Oriented Programming
                                                                                            • Subject
                                                                                            • Subscription
                                                                                            • Tape
                                                                                            • Thread
                                                                                            • Trap
                                                                                            • Udon
                                                                                            • Upgrade Proposal
                                                                                            • Userspace
                                                                                            • Vane
                                                                                            • Vase
                                                                                            • Vere
                                                                                            • Voting
                                                                                            • Warm atom
                                                                                            • Wet Gate
                                                                                            • Wing
                                                                                            • Wire
                                                                                            • Wrapper
                                                                                            • ~zod
                                                                                            • Zuse
                                                                                            • Additional

                                                                                              • Cryptography
                                                                                              • Mips (Maps of Maps)
                                                                                              • Software Distribution

                                                                                                • Overview
                                                                                                • Docket File
                                                                                                • Glob
                                                                                              Reference/Arvo/Eyre

                                                                                              Guide

                                                                                              This document walks through practical examples of the various ways of interacting with Eyre. The Basic sections goes over the common methods of interacting through Eyre from an HTTP client, and the Advanced section explains how to handle HTTP directly with generators and Gall agents.

                                                                                              General documentation of the tasks and methods described here are available in the External API Reference document and the Internal API Reference document.

                                                                                              Basic

                                                                                              Eyre's channel system is the typical way of interacting with Gall agents from an HTTP client. It provides a simple JSON API for actions like pokes, watches, etc, and an SSE event stream for subscription updates. Additionally, Eyre has a scry interface so you can retrieve data in a more ad-hoc manner. These examples use curl to be more language agnostic and to show the nitty-gritty details. In practice you'd probably use an "airlock" library (like http-api for Javascript) which abstracts things like ack'ing events, incrementing event IDs, manually composing the JSON for actions, etc.

                                                                                              It's advisable to have a read through the External API Reference before going through these examples.

                                                                                              Authenticating

                                                                                              You must have a valid session cookie in order to use Eyre's interfaces (such as the channel system or scry interface). If your HTTP client is served from your ship, your browser will automatically add the session cookie it obtained upon login, so there's no need to worry about authentication in practice. If your client does not run in the browser or is not served by your ship, authenticating with your web login code (which can be obtained by running +code in the dojo) is necessary.

                                                                                              Here we'll try authenticating with the default fakezod code.

                                                                                              Using curl in the unix terminal, we'll make an HTTP POST request with "password=CODE" in the body:

                                                                                              curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"

                                                                                              Eyre will respond with HTTP status 204, and a set-cookie header containing the session cookie.

                                                                                              HTTP/1.1 204 ok
                                                                                              Date: Tue, 18 May 2021 01:38:48 GMT
                                                                                              Connection: keep-alive
                                                                                              Server: urbit/vere-1.5
                                                                                              set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=604800

                                                                                              The urbauth-.... cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.

                                                                                              Using Channels

                                                                                              Here we'll look at a practical example of Eyre's channel system. You can refer to the Channels section of the External API Reference document for relevant details.

                                                                                              First, we must obtain a session cookie by authenticating. You will be copying the entry of the set-cookie field into the --cookie field in subsequent commands.

                                                                                              Now that we have our cookie, we can try poking an app & simultaneously opening a new channel. In this case, we'll poke the hood app with a mark of helm-hi to print "Opening airlock" in the dojo.

                                                                                              We'll do this with an HTTP PUT request, and we'll include the cookie we obtained when we authenticated in the Cookie header. The URL path we'll make the request to will be http://localhost:8080/~/channel/mychannel. The last part of the path is the channel UID - the name for our new channel. Normally you'd use the current unix time plus a hash to ensure uniqueness, but in this case we'll just use mychannel for simplicity.

                                                                                              The data will be a JSON array containing a poke action:

                                                                                              curl --header "Content-Type: application/json" \
                                                                                              --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
                                                                                              --request PUT \
                                                                                              --data '[{"id":1,"action":"poke","ship":"zod","app":"hood","mark":"helm-hi","json":"Opening airlock"}]' \
                                                                                              http://localhost:8080/~/channel/my-channel

                                                                                              If we now have a look in the dojo we'll see it's printed our message, so the poke was successful:

                                                                                              < ~zod: Opening airlock

                                                                                              Now we can connect to the mychannel channel we opened. We do this with an HTTP GET request with our session cookie and the same path as the last request:

                                                                                              curl -i --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" http://localhost:8080/~/channel/my-channel

                                                                                              Eyre will respond with an HTTP status code of 200 and a content-type of text/event-stream, indicating an SSE (Server Sent Event) stream. It will also send us any pending events on the channel - in this case the poke ack as a poke response for our original poke:

                                                                                              HTTP/1.1 200 ok
                                                                                              Date: Tue, 18 May 2021 01:40:47 GMT
                                                                                              Connection: keep-alive
                                                                                              Server: urbit/vere-1.5
                                                                                              set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=604800
                                                                                              connection: keep-alive
                                                                                              cache-control: no-cache
                                                                                              content-type: text/event-stream
                                                                                              transfer-encoding: chunked
                                                                                              id: 0
                                                                                              data: {"ok":"ok","id":1,"response":"poke"}

                                                                                              Normally this event stream would be handled by an EventSource object or similar in Javascript or the equivalent in whatever other language you're using. Here, though, we'll continue using curl for simplicity.

                                                                                              Leaving the event stream connection open, in another shell session on unix we'll try subscribing to the watch path of a Gall agent - the /updates watch path of graph-store in this case.

                                                                                              We'll do this in the same way as the initial poke, except this time it will be a subscribe action:

                                                                                              curl --header "Content-Type: application/json" \
                                                                                              --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
                                                                                              --request PUT \
                                                                                              --data '[{"id":2,"action":"subscribe","ship":"zod","app":"graph-store","path":"/updates"}]' \
                                                                                              http://localhost:8080/~/channel/my-channel

                                                                                              Notice we've incremented the id to 2. Eyre doesn't require IDs to be sequential, merely numerical and unique, but sequential IDs are typically the most practical.

                                                                                              Back in the event stream, we'll see a positive watch ack as a subscribe response, meaning the subscription has been successful:

                                                                                              id: 1
                                                                                              data: {"ok":"ok","id":2,"response":"subscribe"}

                                                                                              Now we'll try trigger an event on our event stream. In fakezod's Landscape, create a new chat channel named "test". You should see the add-graph graph-update come through on our channel in a diff response:

                                                                                              id: 2
                                                                                              data: {"json":{"graph-update":{"add-graph":{"graph":{},"resource":{"name":"test-1183","ship":"zod"},"mark":"graph-validator-chat","overwrite":false}}},"id":2,"response":"diff"}

                                                                                              All events we receive must be acked so Eyre knows we've successfully received them. To do this we'll send an ack action which specifies the event-id of the event in question - 2 in this case:

                                                                                              curl --header "Content-Type: application/json" \
                                                                                              --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
                                                                                              --request PUT \
                                                                                              --data '[{"id":3,"action":"ack","event-id":2}]' \
                                                                                              http://localhost:8080/~/channel/my-channel

                                                                                              This same pattern would be repeated for all subsequent events. Note that when you ack one event, you also implicitly ack all previous events, so in this case event 1 will also be acked.

                                                                                              When we're finished, we can unsubscribe from graph-store /update. We do this by sending Eyre a unsubscribe action, and specify the request ID of the original subscribe action in the subscription field - 2 in our case:

                                                                                              curl --header "Content-Type: application/json" \
                                                                                              --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
                                                                                              --request PUT \
                                                                                              --data '[{"id":4,"action":"unsubscribe","subscription":2}]' \
                                                                                              http://localhost:8080/~/channel/my-channel

                                                                                              Unlike poke and subscribe actions, Eyre doesn't acknowledge unsubscribes, but we'll now have stopped receiving updates from graph-store.

                                                                                              Finally, let's close the channel itself. We can do this simply by sending Eyre a delete action:

                                                                                              curl --header "Content-Type: application/json" \
                                                                                              --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" \
                                                                                              --request PUT \
                                                                                              --data '[{"id":5,"action":"delete"}]' \
                                                                                              http://localhost:8080/~/channel/my-channel

                                                                                              With our channel deleted, we can now close the connection on the client side.

                                                                                              Scrying

                                                                                              Here we'll look at performing scries through Eyre. You can refer to the Scry section of the External API Reference document for relevant details.

                                                                                              First we must obtain a session cookie by authenticating.

                                                                                              Having obtained a cookie, we can now try a scry. We'll scry the graph-store Gall agent on the /x/keys scry path, which will return the list of channels it has. If you don't already have any chat channels on your fakezod, go ahead and create one via landscape so it'll have something to return.

                                                                                              The url path will be /~/scry/graph-store/keys.json. The /~/scry part specifies a scry, the /graph-store part is the Gall agent, the /keys is the scry path without the care, and the .json file extension specifies the return mark.

                                                                                              The request will be an HTTP GET request:

                                                                                              curl -i --cookie "urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm" \
                                                                                              --request GET \
                                                                                              http://localhost:8080/~/scry/graph-store/keys.json

                                                                                              Eyre will respond with HTTP status 200 if it's successful and the body of the response will contain the data we requested:

                                                                                              HTTP/1.1 200 ok
                                                                                              Date: Fri, 04 Jun 2021 10:16:32 GMT
                                                                                              Connection: keep-alive
                                                                                              Content-Length: 61
                                                                                              Server: urbit/vere-1.5
                                                                                              set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
                                                                                              content-type: application/json
                                                                                              {"graph-update":{"keys":[{"name":"test-1183","ship":"zod"}]}}

                                                                                              Now let's make a request to a non-existent scry endpoint:

                                                                                              curl -i --cookie "urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm" \
                                                                                              --request GET \
                                                                                              http://localhost:8080/~/scry/foo/bar/baz.json

                                                                                              Eyre will respond with a 404 Missing status and an error message:

                                                                                              HTTP/1.1 404 missing
                                                                                              Date: Fri, 04 Jun 2021 10:22:51 GMT
                                                                                              Connection: keep-alive
                                                                                              Content-Length: 187
                                                                                              Server: urbit/vere-1.5
                                                                                              set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
                                                                                              content-type: text/html
                                                                                              <html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>There was an error while handling the request for /foo/bar/baz.json.</p><code>no scry result</code></body></html>

                                                                                              Advanced

                                                                                              Rather than using things like Eyre's channel system described in the Basic section, it's possible to handle HTTP requests directly in Gall agents or generators. This is useful if you want to implement a custom API or work with sail to dynamically compose HTML inside an agent.

                                                                                              Agents: Direct HTTP

                                                                                              Here we'll look at handling HTTP requests directly in Gall agents rather than using Eyre's channel system.

                                                                                              You can refer to the %connect section of the Internal API Reference document for relevant details.

                                                                                              Here's a Gall agent that demonstrates this method. It binds the URL path /foo, serves Hello, World! for GET requests and a 405 error for all others. It also prints debug information to the terminal as various things happen.

                                                                                              Note that this example does a lot of things manually for demonstrative purposes. In practice you'd likely want to use a library like /lib/server.hoon to cut down on boilerplate code.

                                                                                              eyre-agent.hoon

                                                                                              /+ default-agent, dbug
                                                                                              =* card card:agent:gall
                                                                                              %- agent:dbug
                                                                                              ^- agent:gall
                                                                                              |_ =bowl:gall
                                                                                              +* this .
                                                                                              def ~(. (default-agent this %|) bowl)
                                                                                              ::
                                                                                              ++ on-init on-init:def
                                                                                              ++ on-save on-save:def
                                                                                              ++ on-load on-load:def
                                                                                              ++ on-poke
                                                                                              |= [=mark =vase]
                                                                                              ^- (quip card _this)
                                                                                              ?+ mark
                                                                                              (on-poke:def [mark vase])
                                                                                              ::
                                                                                              %noun
                                                                                              ?. =(q.vase %bind)
                                                                                              %- (slog leaf+"Bad argument." ~)
                                                                                              `this
                                                                                              %- (slog leaf+"Attempting to bind /foo." ~)
                                                                                              :_ this
                                                                                              [%pass /bind-foo %arvo %e %connect `/'foo' %eyre-agent]~
                                                                                              ::
                                                                                              %handle-http-request
                                                                                              =/ req !< (pair @ta inbound-request:eyre) vase
                                                                                              ~& [mark req]
                                                                                              ?+ method.request.q.req
                                                                                              =/ data=octs
                                                                                              (as-octs:mimes:html '<h1>405 Method Not Allowed</h1>')
                                                                                              =/ content-length=@t
                                                                                              (crip ((d-co:co 1) p.data))
                                                                                              =/ =response-header:http
                                                                                              :- 405
                                                                                              :~ ['Content-Length' content-length]
                                                                                              ['Content-Type' 'text/html']
                                                                                              ['Allow' 'GET']
                                                                                              ==
                                                                                              :_ this
                                                                                              :~
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
                                                                                              [%give %kick [/http-response/[p.req]]~ ~]
                                                                                              ==
                                                                                              ::
                                                                                              %'GET'
                                                                                              =/ data=octs
                                                                                              (as-octs:mimes:html '<h1>Hello, World!</h1>')
                                                                                              =/ content-length=@t
                                                                                              (crip ((d-co:co 1) p.data))
                                                                                              =/ =response-header:http
                                                                                              :- 200
                                                                                              :~ ['Content-Length' content-length]
                                                                                              ['Content-Type' 'text/html']
                                                                                              ==
                                                                                              :_ this
                                                                                              :~
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
                                                                                              [%give %kick [/http-response/[p.req]]~ ~]
                                                                                              ==
                                                                                              ==
                                                                                              ==
                                                                                              ++ on-watch
                                                                                              |= =path
                                                                                              ^- (quip card _this)
                                                                                              ?+ path
                                                                                              (on-watch:def path)
                                                                                              ::
                                                                                              [%http-response *]
                                                                                              %- (slog leaf+"Eyre subscribed to {(spud path)}." ~)
                                                                                              `this
                                                                                              ==
                                                                                              ++ on-leave on-leave:def
                                                                                              ++ on-peek on-peek:def
                                                                                              ++ on-agent on-agent:def
                                                                                              ++ on-arvo
                                                                                              |= [=wire =sign-arvo]
                                                                                              ^- (quip card _this)
                                                                                              ?. ?=([%bind-foo ~] wire)
                                                                                              (on-arvo:def [wire sign-arvo])
                                                                                              ?> ?=([%eyre %bound *] sign-arvo)
                                                                                              ?: accepted.sign-arvo
                                                                                              %- (slog leaf+"/foo bound successfully!" ~)
                                                                                              `this
                                                                                              %- (slog leaf+"Binding /foo failed!" ~)
                                                                                              `this
                                                                                              ++ on-fail on-fail:def
                                                                                              --

                                                                                              Save the above to /app/eyre-agent.hoon. Commit it:

                                                                                              > |commit %base
                                                                                              >=
                                                                                              + /~zod/base/2/app/eyre-agent/hoon

                                                                                              ...and start it:

                                                                                              > |rein %base [& %eyre-agent]

                                                                                              Now, first we need to bind a URL to our app. In the ++ on-poke arm, our agent will send a %connect task to Eyre when poked with %bind:

                                                                                              %noun
                                                                                              ?. =(q.vase %bind)
                                                                                              %- (slog leaf+"Bad argument." ~)
                                                                                              `this
                                                                                              %- (slog leaf+"Attempting to bind /foo." ~)
                                                                                              :_ this
                                                                                              [%pass /eyre %arvo %e %connect `/'foo' %eyre-agent]~

                                                                                              ...and when %eyre responds with a %bound gift, the +on-agent arm will print whether the bind succeeded:

                                                                                              [%eyre %bound *]
                                                                                              ?: accepted.sign-arvo
                                                                                              %- (slog leaf+"/foo bound successfully!" ~)
                                                                                              `this
                                                                                              %- (slog leaf+"Binding /foo failed!" ~)
                                                                                              `this

                                                                                              ...so let's try:

                                                                                              > :eyre-agent %bind
                                                                                              >=
                                                                                              Attempting to bind /foo.
                                                                                              /foo bound successfully!

                                                                                              As you can see, we have successfully bound the /foo url path. Now we can try making an HTTP request. Over in the unix terminal, we can make a GET request using curl:

                                                                                              > curl -i localhost:8080/foo
                                                                                              HTTP/1.1 200 ok
                                                                                              Date: Mon, 17 May 2021 04:39:40 GMT
                                                                                              Connection: keep-alive
                                                                                              Server: urbit/vere-1.5
                                                                                              Content-Type: text/html
                                                                                              Content-Length: 22
                                                                                              transfer-encoding: chunked
                                                                                              <h1>Hello, World!</h1>%

                                                                                              ...which has succeed! This is because the +on-poke arm tests for http GET requests and responds with Hello, World! when it sees one:

                                                                                              %'GET'
                                                                                              =/ data=octs
                                                                                              (as-octs:mimes:html '<h1>Hello, World!</h1>')
                                                                                              =/ content-length=@t
                                                                                              (crip ((d-co:co 1) p.data))
                                                                                              =/ =response-header:http
                                                                                              :- 200
                                                                                              :~ ['Content-Length' content-length]
                                                                                              ['Content-Type' 'text/html']
                                                                                              ==
                                                                                              :_ this
                                                                                              :~
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-header !>(response-header)]
                                                                                              [%give %fact [/http-response/[p.req]]~ %http-response-data !>(`data)]
                                                                                              [%give %kick [/http-response/[p.req]]~ ~]
                                                                                              ==

                                                                                              Back in the dojo, our app's +on-watch arm has printed the path on which Eyre has subscribed for the response:

                                                                                              Eyre subscribed to /http-response/~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929.

                                                                                              ...and it's also printed the request so you can see how it looks when it comes in:

                                                                                              [ %handle-http-request
                                                                                              p=~.~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929
                                                                                              q
                                                                                              [ authenticated=%.n
                                                                                              secure=%.n
                                                                                              address=[%ipv4 .127.0.0.1]
                                                                                              request
                                                                                              [ method=%'GET'
                                                                                              url='/foo'
                                                                                              header-list
                                                                                              ~[
                                                                                              [key='host' value='localhost:8080']
                                                                                              [key='user-agent' value='curl/7.76.1']
                                                                                              [key='accept' value='*/*']
                                                                                              ]
                                                                                              body=~
                                                                                              ]
                                                                                              ]
                                                                                              ]

                                                                                              This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.

                                                                                              Generators

                                                                                              Here we'll look at running a generator via Eyre. Eyre doesn't have a mediated JSON API for generators, instead it just passes through the HTTP request and returns the HTTP response composed by the generator.

                                                                                              You can refer to the %serve section of the Internal API Reference document for relevant details.

                                                                                              Here's a very simple generator that will just echo back the body of the request (if available) along with the current datetime. You can save it in the /gen directory and |commit %base.

                                                                                              Note that this example does some things manually for demonstrative purposes. In practice you'd likely want to use a library like /lib/server.hoon to cut down on boilerplate code.

                                                                                              eyre-gen.hoon

                                                                                              |= [[now=@da eny=@uvJ bec=beak] ~ ~]
                                                                                              |= [authenticated=? =request:http]
                                                                                              ^- simple-payload:http
                                                                                              =/ msg=@t
                                                                                              ?~ body.request
                                                                                              (scot %da now)
                                                                                              (cat 3 (cat 3 (scot %da now) 10) q.u.body.request)
                                                                                              =/ data=octs
                                                                                              (as-octs:mimes:html msg)
                                                                                              =/ =response-header:http
                                                                                              [200 ['Content-Type' 'text/plain']~]
                                                                                              [response-header `data]

                                                                                              Eyre requires generators to be a gate within a gate. The sample of the first gate must be:

                                                                                              [[now=@da eny=@uvJ bec=beak] ~ ~]

                                                                                              The sample of the second nested gate must be:

                                                                                              [authenticated=? =request:http]

                                                                                              The return type of the generator must be $simple-payload:http. If you look at our example generator you'll see it meets these requirements.

                                                                                              Because generators return the entire HTTP message as a single simple-payload, Eyre can calculate the content-length itself and automatically add the header.

                                                                                              In order to make our generator available, we must bind it to a URL path. To do this, we send Eyre a %serve task, which looks like:

                                                                                              [%serve =binding =generator]

                                                                                              The $binding specifies the site and URL path, and the $generator specifies the desk, the path to the generator, and arguments. Note that the passing of arguments to the generator by Eyre is not currently implemented, so you can just leave that as ~ since it won't do anything.

                                                                                              Let's bind our generator to the /mygen URL path with the |pass command in the dojo:

                                                                                              |pass [%e [%serve `/mygen %base /gen/eyre-gen/hoon ~]]

                                                                                              Note that Eyre responds with a %bound gift to indicate whether the binding succeeded but |pass doesn't take such responses so it's not shown.

                                                                                              Now let's try making an HTTP request using curl in the unix terminal:

                                                                                              curl -i http://localhost:8080/mygen --data 'blah blah blah'

                                                                                              We can see that the request has succeeded and our generator has responded with the datetime and request body:

                                                                                              HTTP/1.1 200 ok
                                                                                              Date: Sat, 29 May 2021 09:19:45 GMT
                                                                                              Connection: keep-alive
                                                                                              Content-Length: 41
                                                                                              Server: urbit/vere-1.5
                                                                                              Content-Type: text/plain
                                                                                              Content-Length: 41
                                                                                              ~2021.5.29..09.19.45..e096
                                                                                              blah blah blah

                                                                                              Managing CORS Origins

                                                                                              Here we'll look at approving and rejecting a CORS origin by passing Clay a %approve-origin task and %reject-origin task respectively.

                                                                                              In this example we'll use more manual methods for demonstrative purposes but note there are also the |cors-approve and |cors-reject generators to approve/reject origins from the dojo, and the +cors-registry generator for viewing the CORS configuration.

                                                                                              First, using |pass in the dojo, let's approve the origin http://foo.example by sending Eyre a %approve-origin task:

                                                                                              |pass [%e [%approve-origin 'http://foo.example']]

                                                                                              Now if we scry for the approved CORS set:

                                                                                              > .^(approved=(set @t) %ex /=//=/cors/approved)
                                                                                              approved={'http://foo.example'}

                                                                                              ...we can see that http://foo.example has been added.

                                                                                              Next, let's test it by sending Eyre a CORS preflight request via curl in unix:

                                                                                              curl -i -X OPTIONS \
                                                                                              -H "Access-Control-Request-Method: POST" \
                                                                                              -H "Access-Control-Request-Headers: X-Requested-With" \
                                                                                              -H "Origin: http://foo.example" \
                                                                                              http://localhost:8080

                                                                                              We can see in the response that it has succeeded:

                                                                                              HTTP/1.1 204 ok
                                                                                              Date: Fri, 28 May 2021 12:37:12 GMT
                                                                                              Connection: keep-alive
                                                                                              Server: urbit/vere-1.5
                                                                                              Access-Control-Allow-Origin: http://foo.example
                                                                                              Access-Control-Allow-Credentials: true
                                                                                              Access-Control-Allow-Headers: X-Requested-With
                                                                                              Access-Control-Allow-Methods: POST

                                                                                              Now we'll try rejecting an origin. Back in the dojo, let's |pass Eyre a %reject-origin task for http://bar.example:

                                                                                              |pass [%e [%reject-origin 'http://bar.example']]

                                                                                              If we scry for the rejected CORS set:

                                                                                              > .^(rejected=(set @t) %ex /=//=/cors/rejected)
                                                                                              rejected={'http://bar.example'}

                                                                                              ...we can see that http://bar.example has been added.

                                                                                              If we again test it with curl in unix:

                                                                                              curl -i -X OPTIONS \
                                                                                              -H "Access-Control-Request-Method: POST" \
                                                                                              -H "Access-Control-Request-Headers: X-Requested-With" \
                                                                                              -H "Origin: http://bar.example" \
                                                                                              http://localhost:8080

                                                                                              ...we can see that, as expected, it has not returned the access control headers:

                                                                                              HTTP/1.1 404 missing
                                                                                              Date: Fri, 28 May 2021 12:38:47 GMT
                                                                                              Connection: close
                                                                                              Server: urbit/vere-1.5

                                                                                              Finally, let's look at CORS requests that are neither approved nor rejected.

                                                                                              If we make another request with curl on unix, this time for http://baz.example which we haven't added to a list:

                                                                                              curl -i -X OPTIONS \
                                                                                              -H "Access-Control-Request-Method: POST" \
                                                                                              -H "Access-Control-Request-Headers: X-Requested-With" \
                                                                                              -H "Origin: http://baz.example" \
                                                                                              http://localhost:8080

                                                                                              ...we can see it also correctly fails to return the access control headers:

                                                                                              HTTP/1.1 404 missing
                                                                                              Date: Fri, 28 May 2021 12:39:59 GMT
                                                                                              Connection: close
                                                                                              Server: urbit/vere-1.5

                                                                                              Now if we scry for the requests CORS set:

                                                                                              > .^(requests=(set @t) %ex /=//=/cors/requests)
                                                                                              requests={'http://baz.example' 'http://localhost:8080'}

                                                                                              ... we can see it has automatically been added by the mere fact of the request being made.

                                                                                              <-

                                                                                              Data Types

                                                                                              Edit this page on GitHub

                                                                                              Last modified March 17, 2023