Skip to content

Commit a4c1309

Browse files
authored
feat: fetch android with streams (#49)
* init * tmp: works * update example * clean-up * clean-up * tmp * temporary fix on Android
1 parent 79596a9 commit a4c1309

File tree

7 files changed

+62
-22
lines changed

7 files changed

+62
-22
lines changed

example/tests/benchmark.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const TESTS = [
7676
},
7777
]
7878

79-
const BASE_URL = Platform.OS === 'android' ? 'ws://10.0.2.2' : 'ws://localhost'
79+
export const BASE_URL = Platform.OS === 'android' ? '10.0.2.2' : 'localhost'
8080

8181
export function BenchmarkUI() {
8282
return (
@@ -278,7 +278,7 @@ async function runSingleTest(opts: TestCase): Promise<TestResult> {
278278
const { Ws, port, messageCount, testCase, payload } = opts
279279

280280
return new Promise((resolve) => {
281-
const ws = new Ws(`${BASE_URL}:${port}`)
281+
const ws = new Ws(`ws://${BASE_URL}:${port}`)
282282
let outgoingTime: number
283283
let incomingTime: number
284284
let received = 0

example/tests/filesystem.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
showOpenFilePicker,
88
} from 'react-native-fast-io'
99

10+
import { BASE_URL } from './benchmark'
11+
1012
export function FileSystemUI() {
1113
const [file, setFile] = useState<File | null>(null)
1214

@@ -21,10 +23,9 @@ export function FileSystemUI() {
2123
if (!file) {
2224
return
2325
}
24-
2526
const body = compression ? file.stream().pipeThrough(new CompressionStream(compression)) : file
2627

27-
await fetch('http://localhost:3002/upload', {
28+
await fetch(`http://${BASE_URL}:3002/upload`, {
2829
method: 'POST',
2930
body,
3031
})
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
package com.margelo.nitro.fastio
22

3+
import java.io.PipedInputStream
4+
import java.io.PipedOutputStream
5+
36
class HybridDuplexStream : HybridDuplexStreamSpec() {
4-
override var inputStream: HybridInputStreamSpec
5-
get() = throw NotImplementedError("HybridDuplexStream.inputStream getter not implemented")
6-
set(_) = throw NotImplementedError("HybridDuplexStream.inputStream setter not implemented")
7+
private val pipeIn = PipedInputStream(HybridStreamFactory.BUFFER_SIZE)
8+
private val pipeOut = PipedOutputStream(pipeIn)
9+
10+
override var inputStream: HybridInputStreamSpec = HybridInputStream(pipeIn).also {
11+
System.err.println("Created input stream wrapper")
12+
}
13+
14+
override var outputStream: HybridOutputStreamSpec = HybridOutputStream(pipeOut).also {
15+
System.err.println("Created output stream wrapper")
16+
}
717

8-
override var outputStream: HybridOutputStreamSpec
9-
get() = throw NotImplementedError("HybridDuplexStream.outputStream getter not implemented")
10-
set(_) = throw NotImplementedError("HybridDuplexStream.outputStream setter not implemented")
18+
override val memorySize: Long = 0L
1119

12-
override val memorySize: Long
13-
get() = 0L
20+
fun close() {
21+
try {
22+
System.err.println("Closing duplex stream")
23+
pipeOut.close()
24+
pipeIn.close()
25+
} catch (e: Exception) {
26+
System.err.println("Error closing duplex stream: ${e.message}")
27+
}
28+
}
1429
}

packages/react-native-fast-io/android/src/main/java/com/margelo/nitro/fastio/HybridInputStream.kt

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,28 @@ package com.margelo.nitro.fastio
22

33
import com.margelo.nitro.core.ArrayBuffer
44
import com.margelo.nitro.core.Promise
5+
import kotlinx.coroutines.CoroutineScope
6+
import kotlinx.coroutines.Dispatchers
57
import java.io.InputStream
68

7-
class HybridInputStream(public val stream: InputStream) : HybridInputStreamSpec() {
9+
class HybridInputStream(val stream: InputStream) : HybridInputStreamSpec() {
810
override fun read(): Promise<ArrayBuffer> {
9-
return Promise.async {
11+
return Promise.async(CoroutineScope(Dispatchers.IO)) {
1012
val bytes = ByteArray(HybridStreamFactory.BUFFER_SIZE)
1113
val bytesRead = stream.read(bytes, 0, bytes.size)
1214

1315
when {
1416
bytesRead == -1 -> {
15-
// End of stream
16-
ArrayBuffer.allocate(0)
17+
val emptyBuffer = ArrayBuffer.allocate(0)
18+
emptyBuffer
1719
}
1820
bytesRead > 0 -> {
1921
val arrayBuffer = ArrayBuffer.allocate(bytesRead)
20-
2122
val destBuffer = arrayBuffer.getBuffer(false)
2223
destBuffer.put(bytes, 0, bytesRead)
23-
2424
arrayBuffer
2525
}
2626
else -> {
27-
// Error case
2827
throw Error("Unexpected error reading stream")
2928
}
3029
}

packages/react-native-fast-io/android/src/main/java/com/margelo/nitro/fastio/HybridNetwork.kt

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
11
package com.margelo.nitro.fastio
22

33
import com.margelo.nitro.core.Promise
4+
import kotlinx.coroutines.CoroutineScope
5+
import kotlinx.coroutines.Dispatchers
6+
import java.net.HttpURLConnection
7+
import java.net.URL
48

59
class HybridNetwork : HybridNetworkSpec() {
610
override fun request(opts: RequestOptions): Promise<Unit> {
7-
throw NotImplementedError("HybridNetwork.request() not implemented")
11+
Promise.async(CoroutineScope(Dispatchers.IO)) {
12+
val connection = URL(opts.url).openConnection() as HttpURLConnection
13+
connection.apply {
14+
requestMethod = opts.method.name.uppercase()
15+
doInput = true
16+
doOutput = opts.body != null
17+
18+
opts.body?.let { hybridStream ->
19+
(hybridStream as HybridInputStream).stream.use { input ->
20+
outputStream.buffered().use { output ->
21+
input.copyTo(output, HybridStreamFactory.BUFFER_SIZE)
22+
}
23+
}
24+
}
25+
26+
if (responseCode !in 200..299) {
27+
throw Error("HTTP Error: $responseCode")
28+
}
29+
}
30+
}
31+
return Promise.resolved(Unit)
832
}
933

1034
override val memorySize: Long

packages/react-native-fast-io/android/src/main/java/com/margelo/nitro/fastio/HybridOutputStream.kt

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import com.margelo.nitro.core.Promise
55
import java.io.OutputStream
66

77
class HybridOutputStream(private val stream: OutputStream) : HybridOutputStreamSpec() {
8-
98
override fun write(buffer: ArrayBuffer): Promise<Unit> {
109
val byteBuffer = buffer.getBuffer(false)
1110
val bytes = ByteArray(buffer.size)

packages/react-native-fast-io/src/w3c/streams.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ export const toReadableStream = (inputStream: InputStream) => {
1111
controller.close()
1212
return
1313
}
14-
controller.enqueue(new Uint8Array(buffer))
14+
15+
const chunk = new Uint8Array(buffer)
16+
controller.enqueue(chunk)
1517
},
1618
cancel() {
1719
inputStream.close()

0 commit comments

Comments
 (0)