Blame


1 83c817b4 2021-10-13 op # gemini.core
2 1d126b15 2021-10-13 op
3 2957b0a4 2021-10-13 op [![Clojars Project](https://img.shields.io/clojars/v/com.omarpolo/gemini.svg)](https://clojars.org/com.omarpolo/gemini)
4 2957b0a4 2021-10-13 op
5 a7994c56 2021-10-13 op A Clojure library to make Gemini requests that exposes some low-level
6 a7994c56 2021-10-13 op API to handle network requests.
7 1d126b15 2021-10-13 op
8 1d126b15 2021-10-13 op
9 1d126b15 2021-10-13 op ## Usage
10 1d126b15 2021-10-13 op
11 83c817b4 2021-10-13 op Import the library for e.g. with:
12 83c817b4 2021-10-13 op
13 1d126b15 2021-10-13 op ```clojure
14 1d126b15 2021-10-13 op user=> (require '[gemini.core :as gemini])
15 1d126b15 2021-10-13 op ```
16 1d126b15 2021-10-13 op
17 83c817b4 2021-10-13 op ### Documentation
18 1d126b15 2021-10-13 op
19 2c7df1b2 2021-10-15 op `fetch` makes a Gemini request. The request needs to be closed
20 2c7df1b2 2021-10-15 op afterwards using `close`.
21 1d126b15 2021-10-13 op
22 2c7df1b2 2021-10-15 op Takes a map with the following keys (only `:request` is mandatory):
23 1d126b15 2021-10-13 op
24 2c7df1b2 2021-10-15 op - `:proxy`: a map of `:host` and `:port`, identifies the server to
25 2c7df1b2 2021-10-15 op send the requests to. This allows to use a gemini server as a
26 2c7df1b2 2021-10-15 op proxy, it doesn't do any other kind of proxying (e.g. SOCK5.)
27 2c7df1b2 2021-10-15 op - `:request` the URI (as string) to require.
28 2c7df1b2 2021-10-15 op - `:follow-redirects?` if `false` or `nil` don't follow redirects, if
29 2c7df1b2 2021-10-15 op `true` follow up to 5 redirects, or the number of redirects to
30 2c7df1b2 2021-10-15 op follow.
31 2c7df1b2 2021-10-15 op
32 2c7df1b2 2021-10-15 op Returns a map with `:error` key if an error occur or with the
33 2c7df1b2 2021-10-15 op following fields if it succeeds:
34 2c7df1b2 2021-10-15 op
35 2c7df1b2 2021-10-15 op - `:uri`: the URI of the request. May be different from the
36 2c7df1b2 2021-10-15 op requested one if `:follow-redirects?` was specified.
37 2c7df1b2 2021-10-15 op - `:request`: the object backing the request.
38 2c7df1b2 2021-10-15 op - `:code` and `:meta` are the parsed header response.
39 2c7df1b2 2021-10-15 op - `:body` an instance of a `BufferedReader`. Note: closing the body
40 c558001b 2022-03-14 op is not enough, always call `close` on the returned map.
41 2c7df1b2 2021-10-15 op - `:redirected?` true if a redirect was followed.
42 2c7df1b2 2021-10-15 op
43 1d126b15 2021-10-13 op ```clojure
44 2c7df1b2 2021-10-15 op user=> (gemini/fetch {:request "gemini://gemini.circumlunar.space"
45 2c7df1b2 2021-10-15 op :follow-redirects? true})
46 2c7df1b2 2021-10-15 op {:uri "gemini://gemini.circumlunar.space/",
47 2c7df1b2 2021-10-15 op :request
48 2c7df1b2 2021-10-15 op #object[com.omarpolo.gemini.Request 0x6fa9ec6f "com.omarpolo.gemini.Request@6fa9ec6f"],
49 2c7df1b2 2021-10-15 op :code 20,
50 2c7df1b2 2021-10-15 op :meta "text/gemini",
51 1d126b15 2021-10-13 op :body
52 2c7df1b2 2021-10-15 op #object[java.io.BufferedReader 0x18a8d9e0 "java.io.BufferedReader@18a8d9e0"],
53 2c7df1b2 2021-10-15 op :redirected? true}
54 1d126b15 2021-10-13 op ```
55 1d126b15 2021-10-13 op
56 83c817b4 2021-10-13 op `body-as-string!` reads all the response into a string and returns it.
57 83c817b4 2021-10-13 op It also closes the request automatically.
58 1d126b15 2021-10-13 op
59 1d126b15 2021-10-13 op ```clojure
60 e655d71e 2021-10-15 op user=> (-> {:request "gemini://gemini.circumlunar.space/"}
61 2c7df1b2 2021-10-15 op gemini/fetch
62 1d126b15 2021-10-13 op gemini/body-as-string!)
63 1d126b15 2021-10-13 op "# Project Gemini\n\n## Overview\n\nGemini is a new internet protocol which..."
64 1d126b15 2021-10-13 op ```
65 1d126b15 2021-10-13 op
66 2c7df1b2 2021-10-15 op `close` closes a request. It needs to be called after every request.
67 1d126b15 2021-10-13 op
68 83c817b4 2021-10-13 op ```clojure
69 9e7f2805 2021-10-15 op user=> (let [req (gemini/fetch {,,,})]
70 83c817b4 2021-10-13 op (when-not (:error req)
71 e4f66724 2021-10-13 op ;; do something with req
72 e4f66724 2021-10-13 op ,,,
73 e4f66724 2021-10-13 op (gemini/close req)))
74 83c817b4 2021-10-13 op ```
75 1d126b15 2021-10-13 op
76 83c817b4 2021-10-13 op `with-request` is a macro like `with-open` to making connection
77 83c817b4 2021-10-13 op easily. It automatically closes the request and evaluates the body
78 83c817b4 2021-10-13 op only when the request is successful, otherwise throws an exception.
79 1d126b15 2021-10-13 op
80 1d126b15 2021-10-13 op ```clojure
81 2c7df1b2 2021-10-15 op user=> (gemini/with-request [req {:request "gemini://gemini.circumlunar.space/"}]
82 1d126b15 2021-10-13 op ,,,)
83 1d126b15 2021-10-13 op ```
84 83c817b4 2021-10-13 op
85 83c817b4 2021-10-13 op
86 83c817b4 2021-10-13 op ## Streaming content
87 83c817b4 2021-10-13 op
88 83c817b4 2021-10-13 op The `:body` keyword in the returned map is an instance of a Java
89 83c817b4 2021-10-13 op BufferedReader, so streaming content is easy.
90 83c817b4 2021-10-13 op
91 83c817b4 2021-10-13 op However, `body-as-string!` needs to materialise the full reply, so in
92 83c817b4 2021-10-13 op case of a streaming request it will never return!
93 83c817b4 2021-10-13 op
94 83c817b4 2021-10-13 op
95 83c817b4 2021-10-13 op ## text/gemini
96 83c817b4 2021-10-13 op
97 83c817b4 2021-10-13 op This library only implements the network part of Gemini, it doesn't
98 83c817b4 2021-10-13 op try to handle any kind of content. To handle text/gemini you can use
99 83c817b4 2021-10-13 op e.g. the [gemtext][gemtext] library:
100 83c817b4 2021-10-13 op
101 83c817b4 2021-10-13 op ```clojure
102 83c817b4 2021-10-13 op user=> (require '[gemtext.core :as gemtext])
103 83c817b4 2021-10-13 op nil
104 a8e8ae45 2021-10-15 op user=> (gemini/with-request [req {:request "gemini://gemini.circumlunar.space/"}]
105 83c817b4 2021-10-13 op (gemtext/parse (:body req)))
106 83c817b4 2021-10-13 op [[:header-1 "Project Gemini"]
107 83c817b4 2021-10-13 op [:text ""]
108 83c817b4 2021-10-13 op [:header-2 "Overview"]
109 83c817b4 2021-10-13 op [:text ""]
110 83c817b4 2021-10-13 op [:text "Gemini is a new internet protocol which:"]
111 83c817b4 2021-10-13 op ,,,]
112 83c817b4 2021-10-13 op ```
113 83c817b4 2021-10-13 op
114 0ccdb5e9 2021-10-13 op The [gemtext][gemtext] library supports streaming via the
115 0ccdb5e9 2021-10-13 op `gemtext.core/parse` transducer:
116 83c817b4 2021-10-13 op
117 0ccdb5e9 2021-10-13 op ```clojure
118 a8e8ae45 2021-10-15 op user=> (gemini/with-request [req {:request "gemini://gemini.circumlunar.space/"}]
119 0ccdb5e9 2021-10-13 op (transduce gemtext/parser conj [] (line-seq (:body req))))
120 0ccdb5e9 2021-10-13 op ,,,
121 0ccdb5e9 2021-10-13 op ```
122 0ccdb5e9 2021-10-13 op
123 0ccdb5e9 2021-10-13 op
124 83c817b4 2021-10-13 op [gemtext]: https://github.com/omar-polo/gemtext
125 c9321798 2021-10-15 op
126 c9321798 2021-10-15 op
127 c9321798 2021-10-15 op ## License
128 c9321798 2021-10-15 op
129 c9321798 2021-10-15 op Copyright © 2021 Omar Polo, all rights reserved.
130 c9321798 2021-10-15 op
131 c9321798 2021-10-15 op Distributed under the Eclipse Public License either version 1.0 or (at
132 c9321798 2021-10-15 op your option) any later version.