@@ -22,6 +22,7 @@ import org.http4s.Response
22
22
import org .http4s .curl .internal .Utils
23
23
import org .http4s .curl .internal ._
24
24
import org .http4s .curl .unsafe .CurlExecutorScheduler
25
+ import org .http4s .curl .unsafe .CurlMultiSocket
25
26
26
27
private [curl] object CurlRequest {
27
28
private def setup (
@@ -78,6 +79,57 @@ private[curl] object CurlRequest {
78
79
)
79
80
)
80
81
82
+ private def setup (
83
+ handle : CurlEasy ,
84
+ send : RequestSend ,
85
+ recv : RequestRecv ,
86
+ req : Request [IO ],
87
+ ): Resource [IO , Unit ] =
88
+ Utils .newZone.flatMap(implicit zone =>
89
+ CurlSList ().evalMap(headers =>
90
+ IO {
91
+ // TODO add in options
92
+ // handle.setVerbose(true)
93
+
94
+ import org .http4s .curl .unsafe .libcurl_const
95
+ import scala .scalanative .unsafe ._
96
+ import org .http4s .Header
97
+ import org .http4s .HttpVersion
98
+ import org .typelevel .ci ._
99
+
100
+ handle.setCustomRequest(toCString(req.method.renderString))
101
+
102
+ handle.setUpload(true )
103
+
104
+ handle.setUrl(toCString(req.uri.renderString))
105
+
106
+ val httpVersion = req.httpVersion match {
107
+ case HttpVersion .`HTTP/1.0` => libcurl_const.CURL_HTTP_VERSION_1_0
108
+ case HttpVersion .`HTTP/1.1` => libcurl_const.CURL_HTTP_VERSION_1_1
109
+ case HttpVersion .`HTTP/2` => libcurl_const.CURL_HTTP_VERSION_2
110
+ case HttpVersion .`HTTP/3` => libcurl_const.CURL_HTTP_VERSION_3
111
+ case _ => libcurl_const.CURL_HTTP_VERSION_NONE
112
+ }
113
+ handle.setHttpVersion(httpVersion)
114
+
115
+ req.headers // curl adds these headers automatically, so we explicitly disable them
116
+ .transform(Header .Raw (ci " Expect " , " " ) :: Header .Raw (ci " Transfer-Encoding " , " " ) :: _)
117
+ .foreach(header => headers.append(header.toString))
118
+
119
+ handle.setHttpHeader(headers.toPtr)
120
+
121
+ handle.setReadData(Utils .toPtr(send))
122
+ handle.setReadFunction(RequestSend .readCallback(_, _, _, _))
123
+
124
+ handle.setHeaderData(Utils .toPtr(recv))
125
+ handle.setHeaderFunction(RequestRecv .headerCallback(_, _, _, _))
126
+
127
+ handle.setWriteData(Utils .toPtr(recv))
128
+ handle.setWriteFunction(RequestRecv .writeCallback(_, _, _, _))
129
+ }
130
+ )
131
+ )
132
+
81
133
def apply (ec : CurlExecutorScheduler , req : Request [IO ]): Resource [IO , Response [IO ]] = for {
82
134
gc <- GCRoot ()
83
135
handle <- CurlEasy ()
@@ -89,4 +141,17 @@ private[curl] object CurlRequest {
89
141
_ <- req.body.through(send.pipe).compile.drain.background
90
142
resp <- recv.response()
91
143
} yield resp
144
+
145
+ def applyMultiSocket (ms : CurlMultiSocket , req : Request [IO ]): Resource [IO , Response [IO ]] = for {
146
+ gc <- GCRoot ()
147
+ handle <- CurlEasy ()
148
+ flow <- FlowControl (handle)
149
+ send <- RequestSend (flow)
150
+ recv <- RequestRecv (flow)
151
+ _ <- gc.add(send, recv)
152
+ _ <- setup(handle, send, recv, req)
153
+ _ <- ms.addHandlerTerminating(handle, recv.onTerminated).toResource
154
+ _ <- req.body.through(send.pipe).compile.drain.background
155
+ resp <- recv.response()
156
+ } yield resp
92
157
}
0 commit comments