@@ -4,29 +4,17 @@ weight = 6
4template = "doc.html"
4template = "doc.html"
9−- [Introduction](#introduction)
10−- [Authenticating](#authenticating)
11−- [Using the Channel System](#using-the-channel-system)
13−- [Direct HTTP Handling With Gall Agents](#direct-http-handling-with-gall-agents)
14−- [Generators](#generators)
15−- [Managing CORS Origins](#managing-cors-origins)
19This documents contains practical examples of the various ways of interacting with Eyre.
7This documents contains practical examples of the various ways of interacting with Eyre.
21−General documentation of the `task`s and methods described here are available in the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document and the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document.
9+General documentation of the `task`s and methods described here are available in the [External API Reference](/docs/arvo/eyre/external-api-ref) document and the [Internal API Reference](/docs/arvo/eyre/tasks) document.
23−# Authenticating
11+## Authenticating
25−In most cases we must obtain a valid session cookie by [authenticating](@/docs/arvo/eyre/external-api-ref.md#authentication) with our web login code (which can be obtained by running `+code` in the dojo) before we can use Eyre's interfaces (such as the channel system or scry interface).
13+In most cases we must obtain a valid session cookie by [authenticating](/docs/arvo/eyre/external-api-ref#authentication) with our web login code (which can be obtained by running `+code` in the dojo) before we can use Eyre's interfaces (such as the channel system or scry interface).
27Here we'll try authenticating with the default fakezod code.
15Here we'll try authenticating with the default fakezod code.
29−Using `curl` in the unix terminal, we'll make an HTTP POST request with `"password=<code>"` in the body:
17+Using `curl` in the unix terminal, we'll make an HTTP POST request with `"password=CODE"` in the body:
32curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"
20curl -i localhost:8080/~/login -X POST -d "password=lidlut-tabwed-pillex-ridrup"
@@ -44,9 +32,9 @@ set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=6048
45The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
33The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
47−# Using The Channel System
35+## Using The Channel System
49−Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](@/docs/arvo/eyre/external-api-ref.md#channels) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document for relevant details.
37+Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](/docs/arvo/eyre/external-api-ref#channels) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
51First, we must obtain a session cookie by [authenticating](#authenticating). You will be copying the entry of the `set-cookie` field into the `--cookie` field in subsequent commands.
39First, we must obtain a session cookie by [authenticating](#authenticating). You will be copying the entry of the `set-cookie` field into the `--cookie` field in subsequent commands.
@@ -54,7 +42,7 @@ Now that we have our cookie, we can try poking an app & simultaneously opening a
55We'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.
43We'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.
57−The data will be a JSON array containing a [poke](@/docs/arvo/eyre/external-api-ref.md#poke) `action`:
45+The data will be a JSON array containing a [poke](/docs/arvo/eyre/external-api-ref#poke) `action`:
60curl --header "Content-Type: application/json" \
48curl --header "Content-Type: application/json" \
@@ -76,7 +64,7 @@ Now we can connect to the `mychannel` channel we opened. We do this with an HTTP
76curl -i --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" http://localhost:8080/~/channel/my-channel
64curl -i --cookie "urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm" http://localhost:8080/~/channel/my-channel
79−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](@/docs/arvo/eyre/external-api-ref.md#poke-ack) `response` for our original poke:
67+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](/docs/arvo/eyre/external-api-ref#poke-ack) `response` for our original poke:
82HTTP/1.1 200 ok
70HTTP/1.1 200 ok
@@ -97,7 +85,7 @@ Normally this event stream would be handled by an EventSource object or similar
98Leaving 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.
86Leaving 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.
100−We'll do this in the same way as the initial poke, except this time it will be a [subscribe](@/docs/arvo/eyre/external-api-ref.md#subscribe) `action`:
88+We'll do this in the same way as the initial poke, except this time it will be a [subscribe](/docs/arvo/eyre/external-api-ref#subscribe) `action`:
103curl --header "Content-Type: application/json" \
91curl --header "Content-Type: application/json" \
@@ -109,21 +97,21 @@ curl --header "Content-Type: application/json" \
110Notice 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.
98Notice 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.
112−Back in the event stream, we'll see a positive watch ack as a [subscribe](@/docs/arvo/eyre/external-api-ref.md#watch-ack) `response`, meaning the subscription has been successful:
100+Back in the event stream, we'll see a positive watch ack as a [subscribe](/docs/arvo/eyre/external-api-ref#watch-ack) `response`, meaning the subscription has been successful:
116data: {"ok":"ok","id":2,"response":"subscribe"}
104data: {"ok":"ok","id":2,"response":"subscribe"}
119−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](@/docs/arvo/eyre/external-api-ref.md#diff) `response`:
107+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](/docs/arvo/eyre/external-api-ref#diff) `response`:
123data: {"json":{"graph-update":{"add-graph":{"graph":{},"resource":{"name":"test-1183","ship":"zod"},"mark":"graph-validator-chat","overwrite":false}}},"id":2,"response":"diff"}
111data: {"json":{"graph-update":{"add-graph":{"graph":{},"resource":{"name":"test-1183","ship":"zod"},"mark":"graph-validator-chat","overwrite":false}}},"id":2,"response":"diff"}
126−All events we receive must be `ack`ed so Eyre knows we've successfully received them. To do this we'll send an [ack](@/docs/arvo/eyre/external-api-ref.md#ack) `action` which specifies the `event-id` of the event in question - `2` in this case:
114+All events we receive must be `ack`ed so Eyre knows we've successfully received them. To do this we'll send an [ack](/docs/arvo/eyre/external-api-ref#ack) `action` which specifies the `event-id` of the event in question - `2` in this case:
129curl --header "Content-Type: application/json" \
117curl --header "Content-Type: application/json" \
@@ -135,7 +123,7 @@ curl --header "Content-Type: application/json" \
136This 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 `ack`ed.
124This 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 `ack`ed.
138−When we're finished, we can unsubscribe from `graph-store` `/update`. We do this by sending Eyre a [unsubscribe](@/docs/arvo/eyre/external-api-ref.md#unsubscribe) `action`, and specify the request ID of the original `subscribe` `action` in the `subscription` field - `2` in our case:
126+When we're finished, we can unsubscribe from `graph-store` `/update`. We do this by sending Eyre a [unsubscribe](/docs/arvo/eyre/external-api-ref#unsubscribe) `action`, and specify the request ID of the original `subscribe` `action` in the `subscription` field - `2` in our case:
141curl --header "Content-Type: application/json" \
129curl --header "Content-Type: application/json" \
@@ -147,7 +135,7 @@ curl --header "Content-Type: application/json" \
148Unlike `poke` and `subscribe` actions, Eyre doesn't acknowledge `unsubscribe`s, but we'll now have stopped receiving updates from `graph-store`.
136Unlike `poke` and `subscribe` actions, Eyre doesn't acknowledge `unsubscribe`s, but we'll now have stopped receiving updates from `graph-store`.
150−Finally, let's close the channel itself. We can do this simply by sending Eyre a [delete](@/docs/arvo/eyre/external-api-ref.md#delete-channel) `action`:
138+Finally, let's close the channel itself. We can do this simply by sending Eyre a [delete](/docs/arvo/eyre/external-api-ref#delete-channel) `action`:
153curl --header "Content-Type: application/json" \
141curl --header "Content-Type: application/json" \
@@ -159,9 +147,9 @@ curl --header "Content-Type: application/json" \
160With our channel deleted, we can now close the connection on the client side.
148With our channel deleted, we can now close the connection on the client side.
162−# Scrying
150+## Scrying
164−Here we'll look at performing scries through Eyre. You can refer to the [Scry](@/docs/arvo/eyre/external-api-ref.md#scry) section of the [External API Reference](@/docs/arvo/eyre/external-api-ref.md) document for relevant details.
152+Here we'll look at performing scries through Eyre. You can refer to the [Scry](/docs/arvo/eyre/external-api-ref#scry) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
166First we must obtain a session cookie by [authenticating](#authenticating).
154First we must obtain a session cookie by [authenticating](#authenticating).
@@ -213,13 +201,13 @@ content-type: text/html
213<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>
201<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>
216−# Direct HTTP Handling With Gall Agents
204+## Direct HTTP Handling With Gall Agents
218In many cases you'll just want to interact with Gall agents through the JSON API of the channel system, but it's also possible to bypass all that and just deal with HTTP requests directly. Here we'll take a look at how that practically works.
206In many cases you'll just want to interact with Gall agents through the JSON API of the channel system, but it's also possible to bypass all that and just deal with HTTP requests directly. Here we'll take a look at how that practically works.
220−You can refer to the [%connect](@/docs/arvo/eyre/tasks.md#connect) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document for relevant details.
208+You can refer to the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
222−Here's a Gall agent that demonstrates this method. It binds the URL path `/foo`, serves `<h1>Hello, World!</h1>` for GET requests and a `405` error for all others. It also prints debug information to the terminal as various things happen.
210+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.
224Note 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.
212Note 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.
@@ -336,7 +324,7 @@ activated app home/eyre-agent
336[unlinked from [p=~zod q=%eyre-agent]]
324[unlinked from [p=~zod q=%eyre-agent]]
339−Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](@/docs/arvo/eyre/tasks.md#connect) `task` to Eyre when poked with `%bind`:
327+Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](/docs/arvo/eyre/tasks#connect) `task` to Eyre when poked with `%bind`:
@@ -436,11 +424,11 @@ Eyre subscribed to /http-response/~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929.
437This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
425This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
439−# Generators
427+## Generators
441Here 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.
429Here 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.
443−You can refer to the [%serve](@/docs/arvo/eyre/tasks.md#serve) section of the [Internal API Reference](@/docs/arvo/eyre/tasks.md) document for relevant details.
431+You can refer to the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
445Here'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 %home`.
433Here'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 %home`.
@@ -475,7 +463,7 @@ The sample of the second nested gate must be:
475[authenticated=? =request:http]
463[authenticated=? =request:http]
478−The return type of the generator must be [simple-payload:http](@/docs/arvo/eyre/data-types.md#simple-payload-http). If you look at our example generator you'll see it meets these requirements.
466+The return type of the generator must be [$simple-payload:http](/docs/arvo/eyre/data-types#simple-payloadhttp). If you look at our example generator you'll see it meets these requirements.
480Because generators return the entire HTTP message as a single `simple-payload`, Eyre can calculate the `content-length` itself and automatically add the header.
468Because generators return the entire HTTP message as a single `simple-payload`, Eyre can calculate the `content-length` itself and automatically add the header.
@@ -485,7 +473,7 @@ In order to make our generator available, we must bind it to a URL path. To do t
485[%serve =binding =generator]
473[%serve =binding =generator]
488−The [binding](@/docs/arvo/eyre/data-types.md#binding) specifies the site and URL path, and the [generator](@/docs/arvo/eyre/data-types.md#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.
476+The [$binding](/docs/arvo/eyre/data-types#binding) specifies the site and URL path, and the [$generator](/docs/arvo/eyre/data-types#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.
490Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
478Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
@@ -516,9 +504,9 @@ Content-Length: 41
516blah blah blah
504blah blah blah
519−# Managing CORS Origins
507+## Managing CORS Origins
521−Here we'll look at approving and rejecting a CORS origin by passing Clay a [%approve-origin](@/docs/arvo/eyre/tasks.md#approve-origin) `task` and [%reject-origin](@/docs/arvo/eyre/tasks.md#reject-origin) `task` respectively.
509+Here we'll look at approving and rejecting a CORS origin by passing Clay a [%approve-origin](/docs/arvo/eyre/tasks#approve-origin) `task` and [%reject-origin](/docs/arvo/eyre/tasks#reject-origin) `task` respectively.
523In 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.
511In 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.
@@ -528,7 +516,7 @@ First, using `|pass` in the dojo, let's approve the origin `http://foo.example`
528|pass [%e [%approve-origin 'http://foo.example']]
516|pass [%e [%approve-origin 'http://foo.example']]
531−Now if we scry for the [approved](@/docs/arvo/eyre/scry.md#cors-approved) CORS `set`:
519+Now if we scry for the [approved](/docs/arvo/eyre/scry#cors-approved) CORS `set`:
534> .^(approved=(set @t) %ex /=//=/cors/approved)
522> .^(approved=(set @t) %ex /=//=/cors/approved)
@@ -566,7 +554,7 @@ Now we'll try rejecting an `origin`. Back in the dojo, let's `|pass` Eyre a `%re
566|pass [%e [%reject-origin 'http://bar.example']]
554|pass [%e [%reject-origin 'http://bar.example']]
569−If we scry for the [rejected](@/docs/arvo/eyre/scry.md#cors-rejected) CORS `set`:
557+If we scry for the [rejected](/docs/arvo/eyre/scry#cors-rejected) CORS `set`:
572> .^(rejected=(set @t) %ex /=//=/cors/rejected)
560> .^(rejected=(set @t) %ex /=//=/cors/rejected)
@@ -615,7 +603,7 @@ Connection: close
615Server: urbit/vere-1.5
603Server: urbit/vere-1.5
618−Now if we scry for the [requests](@/docs/arvo/eyre/scry.md#cors-requests) CORS `set`:
606+Now if we scry for the [requests](/docs/arvo/eyre/scry#cors-requests) CORS `set`:
621> .^(requests=(set @t) %ex /=//=/cors/requests)
609> .^(requests=(set @t) %ex /=//=/cors/requests)