Blob


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