@@ -5,6 +5,17 @@ import com.facebook.react.bridge.Arguments
55import com.facebook.react.bridge.Promise
66import com.facebook.react.bridge.ReactApplicationContext
77import com.facebook.react.module.annotations.ReactModule
8+ import okhttp3.Call
9+ import okhttp3.Callback
10+ import okhttp3.MediaType
11+ import okhttp3.MediaType.Companion.toMediaTypeOrNull
12+ import okhttp3.OkHttpClient
13+ import okhttp3.Request
14+ import okhttp3.RequestBody
15+ import okhttp3.RequestBody.Companion.toRequestBody
16+ import okhttp3.Response
17+ import java.io.IOException
18+ import java.util.concurrent.TimeUnit
819
920/* *
1021 * React Native TurboModule for WebWorker support.
@@ -16,6 +27,8 @@ import com.facebook.react.module.annotations.ReactModule
1627class WebworkerModule (reactContext : ReactApplicationContext ) :
1728 NativeWebworkerSpec (reactContext), WebWorkerNative .WorkerCallback {
1829
30+ private val client = OkHttpClient ()
31+
1932 init {
2033 // Initialize the native core with this module as the callback receiver
2134 WebWorkerNative .initialize(this )
@@ -52,6 +65,91 @@ class WebworkerModule(reactContext: ReactApplicationContext) :
5265 })
5366 }
5467
68+ override fun onFetch (
69+ workerId : String ,
70+ requestId : String ,
71+ url : String ,
72+ method : String ,
73+ headerKeys : Array <String >,
74+ headerValues : Array <String >,
75+ body : ByteArray? ,
76+ timeout : Double ,
77+ redirect : String
78+ ) {
79+ val requestBuilder = Request .Builder ()
80+ .url(url)
81+
82+ // Headers
83+ var contentType: MediaType ? = null
84+ for (i in headerKeys.indices) {
85+ val key = headerKeys[i]
86+ val value = headerValues[i]
87+ requestBuilder.addHeader(key, value)
88+ if (key.equals(" Content-Type" , ignoreCase = true )) {
89+ contentType = value.toMediaTypeOrNull()
90+ }
91+ }
92+
93+ // Body
94+ val requestBody = if (body != null && body.isNotEmpty()) {
95+ body.toRequestBody(contentType)
96+ } else if (method.equals(" POST" , ignoreCase = true ) || method.equals(" PUT" , ignoreCase = true ) || method.equals(" PATCH" , ignoreCase = true )) {
97+ ByteArray (0 ).toRequestBody(null )
98+ } else {
99+ null
100+ }
101+
102+ requestBuilder.method(method, requestBody)
103+
104+ // Configure client based on options
105+ val requestClient = if (timeout > 0 || redirect != " follow" ) {
106+ val builder = client.newBuilder()
107+ if (timeout > 0 ) {
108+ val timeoutMs = timeout.toLong()
109+ builder.callTimeout(timeoutMs, TimeUnit .MILLISECONDS )
110+ builder.readTimeout(timeoutMs, TimeUnit .MILLISECONDS )
111+ builder.connectTimeout(timeoutMs, TimeUnit .MILLISECONDS )
112+ }
113+ if (redirect == " error" || redirect == " manual" ) {
114+ builder.followRedirects(false )
115+ builder.followSslRedirects(false )
116+ }
117+ builder.build()
118+ } else {
119+ client
120+ }
121+
122+ requestClient.newCall(requestBuilder.build()).enqueue(object : Callback {
123+ override fun onFailure (call : Call , e : IOException ) {
124+ WebWorkerNative .handleFetchResponse(
125+ workerId, requestId, 0 , emptyArray(), emptyArray(), null , e.message
126+ )
127+ }
128+
129+ override fun onResponse (call : Call , response : Response ) {
130+ val responseBody = response.body?.bytes()
131+ val headers = response.headers
132+ val keys = mutableListOf<String >()
133+ val values = mutableListOf<String >()
134+
135+ for (i in 0 until headers.size) {
136+ keys.add(headers.name(i))
137+ values.add(headers.value(i))
138+ }
139+
140+ WebWorkerNative .handleFetchResponse(
141+ workerId,
142+ requestId,
143+ response.code,
144+ keys.toTypedArray(),
145+ values.toTypedArray(),
146+ responseBody,
147+ null
148+ )
149+ }
150+ })
151+ }
152+
55153 // ============================================================================
56154 // TurboModule Methods - mirror iOS implementation
57155 // ============================================================================
0 commit comments