@@ -22,11 +22,18 @@ def show(p: Protocol): String = p match {
22
22
case HTTP() => "http"
23
23
case HTTPS() => "https"
24
24
}
25
+ def defaultPort(p: Protocol): Int = p match {
26
+ case HTTP() => 80
27
+ case HTTPS() => 443
28
+ }
25
29
type Method { GET(); POST() }
26
30
def show(m: Method): String = m match {
27
31
case GET() => "GET"
28
32
case POST() => "POST"
29
33
}
34
+ /// Interface to build HTTP requests.
35
+ ///
36
+ /// Each of method, hostname, path, port, and protocol must be called at least once!
30
37
interface RequestBuilder {
31
38
def method(method: Method): Unit
32
39
def hostname(host: String): Unit
@@ -36,19 +43,28 @@ interface RequestBuilder {
36
43
def header(key: String, value: String): Unit
37
44
def body{ writer: => Unit / emit[Byte] }: Unit
38
45
}
46
+ /// Interface returned by HTTP requests.
39
47
interface ResponseReader {
48
+ /// Gets the response HTTP status code
40
49
def status(): Int
50
+
51
+ /// Returns the body of the response by emitting Bytes
52
+ /// May be called at most once.
41
53
def body(): Unit / emit[Byte]
54
+
55
+ /// Get the specified HTTP header, key should be lower-case
42
56
def getHeader(key: String): Option[String]
57
+
43
58
//def headers(): Unit / emit[(String, String)]
44
59
}
45
60
46
61
record RequestError()
47
-
48
62
// Backend-specific implementations
49
63
// --------------------------------
50
64
51
65
namespace js {
66
+ // Async iterators in JS
67
+ // ---------------------
52
68
extern type AsyncIterator[T]
53
69
extern type IterableResult[T]
54
70
extern io def nextPromise[T](it: AsyncIterator[T]): Promise[IterableResult[T]] =
@@ -70,13 +86,14 @@ namespace js {
70
86
do emit(r.unsafeValue())
71
87
}
72
88
}
73
- // broken if we resolve a promise inside
89
+ // broken if we resolve a promise inside, see issue #1016
74
90
// extern def makeAsyncIterator[T](next: => Promise[IterableResult[T]] at {io, async, global}): AsyncIterator[T] =
75
91
// js """{ next: () => $effekt.runToplevel((ks,k) => ${next}(ks, k)) }"""
76
92
77
93
// Native Byte Buffers
78
94
// -------------------
79
95
extern type NativeBytes
96
+ // jsNode "Buffer"
80
97
extern pure def length(n: NativeBytes): Int =
81
98
js "${n}.length"
82
99
extern pure def get(n: NativeBytes, x: Int): Byte =
@@ -116,6 +133,8 @@ namespace js {
116
133
js "${obj}[${key}] = ${value};"
117
134
extern io def set(obj: JsObj, key1: String, key2: String, value: Any): Unit =
118
135
js "${obj}[${key1}][${key2}] = ${value};"
136
+ extern io def isSet(obj: JsObj, key: String): Bool =
137
+ js "${obj}[${key}] !== undefined"
119
138
}
120
139
121
140
namespace jsNode {
@@ -182,6 +201,7 @@ namespace jsNode {
182
201
def protocol(p) = resume(protocol = p)
183
202
def body() = resume{ {wr} => reqBody = collectBytes{ wr } }
184
203
}
204
+ if(not(options.js::isSet("port"))) { options.js::set("port", protocol.defaultPort()) }
185
205
val res = protocol match {
186
206
case HTTP() => runHTTP(options, reqBody)
187
207
case HTTPS() => runHTTPS(options, reqBody)
@@ -230,17 +250,17 @@ namespace jsWeb {
230
250
var protocol = HTTPS()
231
251
var hostname = ""
232
252
var path = "/"
233
- var port = 443
253
+ var port = None()
234
254
try body() with RequestBuilder {
235
255
def method(m) = resume(options.js::set("method", m.show))
236
256
def hostname(n) = resume(hostname = n)
237
257
def path(p) = resume(path = p)
238
- def port(p) = resume(port = p )
258
+ def port(p) = resume(port = Some(p) )
239
259
def header(k, v) = resume(options.js::set("headers", k, v))
240
260
def protocol(p) = resume(protocol = p)
241
261
def body() = resume{ {wr} => options.js::set("body", collectBytes{wr}) }
242
262
}
243
- val url = s"${protocol.show}://${hostname}:${port.show}${path}"
263
+ val url = s"${protocol.show}://${hostname}:${port.getOrElse{ protocol.defaultPort }. show}${path}"
244
264
val res = run(url, options)
245
265
if(res.isError) { println(res.genericShow); do raise(RequestError(), "Request failed") }
246
266
@@ -273,7 +293,7 @@ namespace example {
273
293
do hostname("effekt-lang.org")
274
294
//do header("user-agent", "Effekt/script") // dont use this on js-web
275
295
do path("/")
276
- do port(443)
296
+ // do port(443) // optional
277
297
}
278
298
if(res.status() == 200){
279
299
println("OK")
0 commit comments